TSQL – 如何在BEGIN .. END块中使用GO?
我正在生成一个脚本,用于自动将更改从多个开发数据库迁移到分段/生产。 基本上,它需要一堆更改脚本,并将它们合并成一个脚本,将每个脚本包装在IF whatever BEGIN ... END
语句。
但是,某些脚本需要GO
语句,因此,例如,SQL分析器在创build后就知道新的列。
ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL GO -- Necessary, or next line will generate "Unknown column: EMP_IS_ADMIN" UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever
但是,一旦我把它包装在IF
块中:
IF whatever BEGIN ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL GO UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever END
它失败了,因为我发送一个BEGIN
没有匹配的END
。 但是,如果我删除GO
它再次抱怨一个未知的列。
有没有什么办法可以创build和更新单个IF
块中的同一列?
GO
不是SQL – 它只是一些MS SQL工具中使用的批处理分隔符。
如果你不使用它,你需要确保这些语句是分开执行的 – 不pipe是在不同的批处理中还是通过使用dynamicSQL来处理群体(谢谢@gbn):
IF whatever BEGIN ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL; EXEC ('UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever') END
您可以尝试sp_executesql
,将每个GO
语句之间的内容拆分为一个单独的string以执行,如下面的示例所示。 此外,还有一个@statementNovariables来跟踪哪个语句正在执行,以便于在发生exception的情况下进行debugging。 行号将相对于导致错误的相关语句编号的开头。
BEGIN TRAN DECLARE @statementNo INT BEGIN TRY IF 1=1 BEGIN SET @statementNo = 1 EXEC sp_executesql N' ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL' SET @statementNo = 2 EXEC sp_executesql N' UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = 1' SET @statementNo = 3 EXEC sp_executesql N' UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = 1x' END END TRY BEGIN CATCH PRINT 'Error occurred on line ' + cast(ERROR_LINE() as varchar(10)) + ' of ' + 'statement # ' + cast(@statementNo as varchar(10)) + ': ' + ERROR_MESSAGE() -- error occurred, so rollback the transaction ROLLBACK END CATCH -- if we were successful, we should still have a transaction, so commit it IF @@TRANCOUNT > 0 COMMIT
如上例所示,您也可以轻松地执行多行语句,只需用单引号( '
)将它们包装起来即可。 在生成脚本时,不要忘记在string中包含任何单引号( ''
)。
我最终通过用自己的行取代GO
每个实例来工作
END GO ---Automatic replacement of GO keyword, need to recheck IF conditional: IF whatever BEGIN
这比将每一组语句包装在一个string中都要好得多 ,但还是远远不够理想。 如果有人find一个更好的解决scheme,发布它,我会接受它。
我有同样的问题,并最终设法解决它使用SET NOEXEC 。
IF not whatever BEGIN SET NOEXEC ON; END ALTER TABLE dbo.EMPLOYEE ADD COLUMN EMP_IS_ADMIN BIT NOT NULL GO UPDATE dbo.EMPLOYEE SET EMP_IS_ADMIN = whatever SET NOEXEC OFF;
你可以把这些语句放在BEGIN和END中,而不是GO中间
IF COL_LENGTH('Employees','EMP_IS_ADMIN') IS NULL --Column does not exist BEGIN BEGIN ALTER TABLE dbo.Employees ADD EMP_IS_ADMIN BIT END BEGIN UPDATE EMPLOYEES SET EMP_IS_ADMIN = 0 END END
(在Northwind数据库上testing)
编辑:(可能在SQL2012上testing)
您可以合并GOTO
和LABEL
语句来跳过代码,从而使GO
关键字保持不变。