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)

您可以合并GOTOLABEL语句来跳过代码,从而使GO关键字保持不变。