我们可以在GO中多次使用SQL Transaction语句吗?我的T-SQL脚本很长,我想用SQL Transaction运行它。如果一切顺利,那么我将 promise 否则将回滚。

但是,在运行该查询时,出现类似'create function must be the only statement in the batch'的错误。当我在其中创建和删除许多功能和过程时。

我没有在脚本中的任何地方使用GO。我的问题是-我可以在那个长脚本中多次使用GO语句。因为,GO创建一个批处理,并且如果该批处理第一次成功执行但下次失败,那么rollback transaction语句将能够实际回滚已执行的代码吗?

我的脚本结构如下:

PRINT 'Transaction Started'
BEGIN TRY
    BEGIN TRAN

    Drop Function
    ....
    ....
    Create Function
    ....
    ....
    Drop Procedure
    ....
    ....
    Lots of statements
    ....
    ....

    COMMIT TRAN
    PRINT 'Transaction Succeeded'
END TRY
BEGIN CATCH
    PRINT 'Transaction Failed'
    IF(@@TRANCOUNT > 0)
        ROLLBACK TRAN
END CATCH

我正在创建此脚本,以便在单个脚本中将一些更改从newDB迁移到oldDB。

最佳答案

您正在混合概念。 GO不是Transact-SQL概念,不是语言的一部分,也不为SQL Server所理解。 GO是工具批处理定界符。默认情况下,sqlcmd.exe和SSMS都使用GO作为批处理定界符。批次定界符用于标识SQL源文件中的各个批次。客户端工具一次向服务器发送一批(当然,省略定界符)。

事务可以跨越批次。 TRY / CATCH块不能。 CREATE / ALTER语句必须是批处理中的唯一语句(注释不是语句,而包含在函数过程主体中的语句也是如此)。

可以通过启动事务并在第一个错误时中止执行(在-b start处使用sqlcmd.exe或使用 :on error exit in SSMS)来实现与您想要执行的操作类似的操作。

但是在长事务中执行DDL是行不通的。特别是如果您计划将其与DML混合使用。我必须调查的大多数损坏都来自这种组合(Xact,DDL + DML,回滚)。我强烈建议您反对。

安全地部署架构更新的唯一方法是在出现问题时进行备份,部署,从备份还原。

注意Dan推荐的(动态SQL)是有效的,因为sp_executesql启动了一个新的内部批处理。该批次将满足CREATE / ALTER限制。

关于sql - 我们可以在SQL事务中多次使用 'GO'吗?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34178270/

10-12 14:17
查看更多