首页 > 解决方案 > 如何忽略 IF EXISTS 块中的 GO 语句?

问题描述

我正在尝试根据 IF NOT EXISTS 条件执行脚本。但是,即使 IF NOT EXISTS 返回 1,BEGIN 和 END 中的块也会被执行。我无法更改 BEGIN 和 END 块中的语句。如何处理这种情况?

IF NOT EXISTS(SELECT 1 FROM [dbo].[UPGRADEHISTORY] WHERE SCRIPTNAME='001-MarkSubmitted.sql' AND RELEASENUMBER= '1')
BEGIN
    IF NOT EXISTS(SELECT 1 FROM [dbo].[Action] WHERE Name='mark As Submitted')
        BEGIN
        SET IDENTITY_INSERT [dbo].[Action] ON 
        INSERT INTO [dbo].[Action](Id,Name,CreatedBy,CreatedOn) VALUES (6,'mark As Submitted',1,getdate())
        SET IDENTITY_INSERT [dbo].[Action] OFF
        END
    GO
    INSERT INTO [dbo].[StatusActionMapping](ArtifactType,StatusId,ActionId,RoleId) VALUES ('Report',11,6,1)
    GO

    INSERT INTO [dbo].[UpgradeHistory] ([ReleaseNumber],[ScriptNumber],[ScriptName],[ExecutionDate]) VALUES (1, (SELECT FORMAT(MAX(SCRIPTNUMBER) + 1, 'd3') FROM UpgradeHistory WHERE ReleaseNumber= 1),'001-MarkSubmitted.sql',GETDATE());
END
GO

标签: sqlsql-server

解决方案


正如我在评论中提到的,GO不是Transact-SQL 运算符,它被您的 IDE/CLI 解释为批处理分隔符。SQL Server 实用程序语句 - GO

SQL Server 提供的命令不是 Transact-SQL 语句,但可以被 sqlcmd 和 osql 实用程序以及 SQL Server Management Studio 代码编辑器识别。这些命令可用于促进批处理和脚本的可读性和执行。

GO 向 SQL Server 实用程序发出一批 Transact-SQL 语句结束的信号。

答案很简单,去掉GOs。这里不需要它们;这是因为它们在那里,您会收到错误消息,因为将语句分成不同的批次在这里没有意义。你所拥有的相当于拥有以下 3 个“文件”并尝试独立运行它们:

文件 1:

IF NOT EXISTS(SELECT 1 FROM [dbo].[UPGRADEHISTORY] WHERE SCRIPTNAME='001-MarkSubmitted.sql' AND RELEASENUMBER= '1')
BEGIN
    IF NOT EXISTS(SELECT 1 FROM [dbo].[Action] WHERE Name='mark As Submitted')
        BEGIN
        SET IDENTITY_INSERT [dbo].[Action] ON 
        INSERT INTO [dbo].[Action](Id,Name,CreatedBy,CreatedOn) VALUES (6,'mark As Submitted',1,getdate())
        SET IDENTITY_INSERT [dbo].[Action] OFF
        END

由于没有BEGINout会出错END

文件 2:

INSERT INTO [dbo].[StatusActionMapping](ArtifactType,StatusId,ActionId,RoleId) VALUES ('Report',11,6,1)

这会运行良好。

文件 3:

INSERT INTO [dbo].[UpgradeHistory] ([ReleaseNumber],[ScriptNumber],[ScriptName],[ExecutionDate]) VALUES (1, (SELECT FORMAT(MAX(SCRIPTNUMBER) + 1, 'd3') FROM UpgradeHistory WHERE ReleaseNumber= 1),'001-MarkSubmitted.sql',GETDATE());
END

由于END没有BEGIN.

您的查询中没有任何内容会导致解析错误,例如您将新列添加到现有表并稍后在批处理中引用它,因此无需分隔批处理。只需删除GOs 中间的BEGIN...ENDs 即可按您的要求工作:

IF NOT EXISTS (SELECT 1
               FROM [dbo].[UPGRADEHISTORY]
               WHERE SCRIPTNAME = '001-MarkSubmitted.sql'
                 AND RELEASENUMBER = '1')
BEGIN
    IF NOT EXISTS (SELECT 1
                   FROM [dbo].[Action]
                   WHERE Name = 'mark As Submitted')
    BEGIN
        SET IDENTITY_INSERT [dbo].[Action] ON;
        INSERT INTO [dbo].[Action] (Id, Name, CreatedBy, CreatedOn)
        VALUES (6, 'mark As Submitted', 1, GETDATE());
        SET IDENTITY_INSERT [dbo].[Action] OFF;
    END;
    INSERT INTO [dbo].[StatusActionMapping] (ArtifactType, StatusId, ActionId, RoleId)
    VALUES ('Report', 11, 6, 1);

    INSERT INTO [dbo].[UpgradeHistory] ([ReleaseNumber], [ScriptNumber], [ScriptName], [ExecutionDate])
    VALUES (1, (SELECT FORMAT(MAX(SCRIPTNUMBER) + 1, 'd3') --This is a REALLY bad idea. Use an IDENTITY or SEQUENCE
                FROM UpgradeHistory
                WHERE ReleaseNumber = 1), '001-MarkSubmitted.sql', GETDATE());
END;
GO

还要注意我对你的最终观点INSERT。最终会出现竞争FORMAT(MAX(SCRIPTNUMBER) + 1, 'd3')条件使用IDENTITYSEQUENCE


推荐阅读