如何使 SET XACT_ABORT ON 回滚事务?
Posted
技术标签:
【中文标题】如何使 SET XACT_ABORT ON 回滚事务?【英文标题】:How to make SET XACT_ABORT ON rollback the transaction? 【发布时间】:2012-07-23 19:36:54 【问题描述】:基于Books Online documentation of SET XACT_ABORT ON
,我的印象是,如果 T-SQL 语句引发运行时错误,则整个事务将终止并回滚:
备注
当 SET XACT_ABORT 为 ON 时,如果 Transact-SQL 语句引发运行时错误,则整个事务将终止并回滚。
在 SQL Server 2008 R2 中对此进行测试:
SET XACT_ABORT ON;
BEGIN TRANSACTION;
PRINT 'TranCount befor an error = '+CAST(@@Trancount AS varchar(50))
DROP TABLE QuertyAsdf
PRINT 'TranCount after an error = '+CAST(@@Trancount AS varchar(50))
给出输出:
TranCount befor an error = 1
Msg 3701, Level 11, State 5, Line 6
Cannot drop the table 'QwertyAsdf', because it does not exist or you do not have permission.
TranCount after an error = 1
我也觉得SET XACT_ABORT ON
terminates the batch if there's an error:
SET XACT_ABORT ON 指示 SQL Server 回滚整个事务并在发生运行时错误时中止批处理。
听起来很方便。我怎样才能让它也这样做?
【问题讨论】:
"when XACT_ABORT is ON, not all errors terminate the batch ... Compilation errors (which normally terminate the scope) do not terminate the batch." @MartinSmith 大概这不是编译错误,因为它通过了编译并开始执行批处理 一般来说,引用不存在对象的语句会被延迟编译。不确定 DDL 语句是否属于这种情况。 ***.com/questions/917773/… 【参考方案1】:SQL Server 仅在 Severity 级别大于或等于 16 时回滚事务。
查看示例:
Msg 544, Level 16, State 1, Line 1
Cannot insert explicit value for identity column in table 'ORC_ORCAMENTO' whenIDENTITY_INSERT is set to OFF.
在 SQL Server 2008 R2 上测试
SET XACT_ABORT ON;
BEGIN TRANSACTION;
PRINT 'TranCount befor an error = '+CAST(@@Trancount AS varchar(50))
insert into ORC_ORCAMENTO (ORCID, ORCNOME, ORCATIVO) VALUES (1, 'TESTE_ALEXP', 0);
PRINT 'TranCount after an error = '+CAST(@@Trancount AS varchar(50))
返回
TranCount befor an error = 1
Msg 544, Level 16, State 1, Line 5
Cannot insert explicit value for identity column in table 'ORC_ORCAMENTO' when IDENTITY_INSERT is set to OFF.
TranCount after an error = 0
查看 Microsoft 错误消息级别
https://docs.microsoft.com/en-us/sql/relational-databases/errors-events/database-engine-events-and-errors
【讨论】:
【参考方案2】:当您使用 xact abort on 时,在 try
catch
语句中,您可以手动引发错误以使事务回滚。
set xact_abort on;
begin try
...dml statements here....
if conditions here...
raiseerror(....);
end try
begin catch
end catch
【讨论】:
以上是关于如何使 SET XACT_ABORT ON 回滚事务?的主要内容,如果未能解决你的问题,请参考以下文章
在存储过程中写SET XACT_ABORT ON 有什么用,不写会发生什么问题
postgres 中 SET XACT_ABORT ON 的替代方法是啥