这是我编写的一个简单测试。
SET XACT_ABORT ON
BEGIN TRANSACTION
GO
CREATE PROCEDURE [usp_MyTest1]
AS
GO
CREATE PROCEDURE [usp_MyTest1]
AS
GO
CREATE PROCEDURE [usp_MyTest2]
AS
GO
COMMIT TRANSACTION
据我了解,由于我设置了SET XACT_ABORT ON
,因此当第二个创建过程失败时,整个事务将回滚。相反,只有发生错误的事情(第一个创建过程)才会回滚,最后一个创建过程执行得很好。然后我收到一条消息,提示 COMMIT TRANSACTION 请求没有相应的 BEGIN TRANSACTION。
我见过人们对 RAISEERROR 有疑问,但 XACT_ABORT 的文档说 RAISEERROR 不支持 XACT_ABORT。但这并没有提及任何有关错误的信息,例如创建不遵守 XACT_ABORT 的重复过程。
https://learn.microsoft.com/en-us/sql/t-sql/statements/set-xact-abort-transact-sql
The THROW statement honors SET XACT_ABORT RAISERROR does not. New Applications should use THROW instead of RAISERROR.
如果相关的话,这是针对 SQL Server 2012 的。
最佳答案
它确实回滚事务。
你可以很清楚地看到这一点
SET XACT_ABORT ON
BEGIN TRANSACTION
GO
SELECT @@TRANCOUNT, 'Point1'
GO
CREATE PROCEDURE [usp_MyTest1] AS
GO
SELECT @@TRANCOUNT, 'Point2'
GO
CREATE PROCEDURE [usp_MyTest1] AS
GO
/*
The earlier transaction has now been rolled back and
now running outside an explicit transaction. @@TRANCOUNT is 0
*/
SELECT @@TRANCOUNT, 'Point3'
GO
CREATE PROCEDURE [usp_MyTest2] AS
GO
SELECT @@TRANCOUNT, 'Point4'
GO
/*Nothing to commit so error*/
COMMIT TRANSACTION
哪个返回
当您到达第 3 点时,事务已回滚(包括 usp_MyTest1
的初始创建),并且 usp_MyTest2
的创建发生在新的 auto commit transaction 中。因此,最终结果是数据库包含 usp_MyTest2
而不是 usp_MyTest1
(假设两者一开始都不存在)。
这就是为什么您也会在最后看到错误
Msg 3902, Level 16, State 1, Line 19 The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION.
要在发生错误并回滚事务后终止脚本执行(而不是继续执行后续批处理),最可靠的方法是在 SSMS 中启用 sqlcmd 模式并将其添加到脚本顶部 :错误退出
关于sql - XACT_ABORT 不回滚 SQL Server 2012 上的事务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48153532/