sql - XACT_ABORT 不回滚 SQL Server 2012 上的事务

标签 sql sql-server t-sql sql-server-2012

这是我编写的一个简单测试。

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

哪个返回

enter image description here

当您到达第 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/

相关文章:

sql - 如何重建/重新安装 ssrs(reportserver、reportservertempdb)数据库?

sql - 获取一组最近的记录

sql-server - Alter 表中的 Case 语句错误

sql - 聚合合并到Elasticsearch的匹配中

php - 根据第二个表的列数比较两个表结果

sql - 如何在 CASE 中执行 SELECT 语句

sql - 如何将多个字符串行中的字符串压缩到单个字段中?

python - SQLAlchemy 正确的模型定义和选择/插入

mysql - 在mysql中按月和年生成报告

Sql:选择所有类型的条件都为 true 的位置