我们可以使用';GO';在SQL事务中多次执行?

我们可以使用';GO';在SQL事务中多次执行?,sql,sql-server,tsql,Sql,Sql Server,Tsql,我们可以在SQL事务中多次使用GO语句吗。我有一个很长的T-SQL脚本,我想在SQL事务中运行它。如果一切顺利,那么我将承诺,否则将回滚 但是,在运行该查询时,我遇到了一个错误,如“create function必须是批处理中唯一的语句”。因为我在其中创建和删除了许多函数和过程 我没有在脚本的任何地方使用GO。我的问题是-我可以在那个长脚本中多次使用GO语句吗。因为,GO创建了一个批处理,如果批处理第一次成功执行,但下次失败,那么rollback事务语句是否能够实际回滚已执行的事务 我的脚本的结

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

但是,在运行该查询时,我遇到了一个错误,如“create function必须是批处理中唯一的语句”
。因为我在其中创建和删除了许多函数和过程

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

我的脚本的结构如下所示:

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是一个很好的关键字。GO将完成最后一个代码块并继续下一个代码块。是的,您可以在一条语句中使用多个GOs将其分解为多个批。但最好将try/catch逻辑与GOs结合使用,因为您正在执行基于事务的逻辑。本网站提供了一些关于如何使用它的示例,如果您遇到故障,您可以输出该错误并继续执行(如果您选择)。

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

事务可以跨批处理。无法尝试/捕获块。CREATE/ALTER语句必须是批处理中的唯一语句(注释不是语句,函数过程体中包含的语句也包含在内)

通过启动事务并在出现第一个错误时中止执行(
-b
at
sqlcmd.exe
start或use),可以实现类似于您想要执行的操作


但在长事务中进行DDL是行不通的。特别是如果你打算将其与DML混合使用。我必须调查的大多数腐败都来自这种组合(Xact、DDL+DML、rollback)。我强烈建议不要这样做

安全部署架构更新的唯一方法是在出现问题时从备份中进行备份、部署和恢复

请注意,Dan推荐的(动态SQL)之所以有效,是因为
sp_executesql
启动了一个新的内部批处理。此批次将满足创建/更改限制。

请注意。它是SQLServerManagementStudio和其他客户端工具使用的客户端批处理分隔符

GO对事务范围没有影响。BEGIN TRAN将在当前连接上启动事务。提交和回滚将结束事务。您可以执行任意数量的语句。GO将分别执行这些语句

按照以下规定:

TRY…CATCH构造不能跨越多个批

因此,“开始尝试”、“结束尝试”、“开始捕获”和“结束捕获”不能通过GO分隔符分隔为单独的批。它们必须出现在同一查询中

如果尝试在try/CATCH语句中包含批处理分隔符,如下面的无效SQL:

begin try
    go
end try
begin catch
    go
end catch
这将执行3个不同的查询,返回语法错误:

1)
开始尝试

Msg 102, Level 15, State 1, Line 1
Incorrect syntax near 'begin'.
2)
end try begin catch

Msg 102, Level 15, State 1, Line 3
Incorrect syntax near 'try'.
Msg 102, Level 15, State 1, Line 6
Incorrect syntax near 'catch'.
3)
end catch

Msg 102, Level 15, State 1, Line 3
Incorrect syntax near 'try'.
Msg 102, Level 15, State 1, Line 6
Incorrect syntax near 'catch'.

是否在此脚本中创建存储过程或函数?我已更新了答案。不管怎样,我正在创建和删除这两个。首先检查它们是否存在。在此处尝试以下答案:是,一个事务可以跨越多个批次(GO命令)。但是,
TRY/CATCH
范围是同一批,一些类似于
CREATE函数的DDL必须在单独的批中。您需要使用动态SQL在相同的
TRY/CATCH
块中创建这些对象,或者放弃使用
TRY/CATCH
。因此,我所需要做的就是使用动态SQL创建视图和过程。正确的?我会将所有脚本保存在一个try/catch中。“但是在长事务中执行DDL是行不通的。特别是如果您计划将其与DML混合使用。”-为什么不呢?XACT_ABORT会在出现错误时回滚所有批处理吗?@metabuddy
XACT_ABORT
会中止所有打开的事务。如果批处理中有多个
GO
语句,客户机将把输入分离为多个往返。如果在具有多个GO
语句的查询中发生错误,则当前事务将中止,但该批将继续执行下一个GO
语句之后的下一批。