当INSERT INTO失败时,为什么我的事务会自动回滚?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当INSERT INTO失败时,为什么我的事务会自动回滚?相关的知识,希望对你有一定的参考价值。
令人惊讶的是,我找不到任何有关此问题的相关解释或文档。
在这些SQL语句的情况下:
SELECT 1 AS Test INTO #tmpTest
BEGIN TRAN
SELECT 1 AS Test INTO #tmpTest
ROLLBACK TRAN
当逐个执行时,第3行的SELECT ... INTO
失败,正如预期的那样,带有消息 -
数据库中已经有一个名为“#tmpTest”的对象。
但是,之后,第4行中的ROLLBACK
语句失败:
ROLLBACK TRANSACTION请求没有相应的BEGIN TRANSACTION。
即使交易从第2行成功地做了BEGIN
。
我见过SQL Server - transactions roll back on error?,但答案不适用于此,因为默认的xact_abort
是off
。此外,answer from Quassnoi与answer by Raj More相矛盾。
什么是实际的解释?
请参阅http://www.sommarskog.se/error-handling-I.html
你得到的是这种情况下的批量堕胎导致隐式回滚。该博客是关于SQL Server 2000错误处理,但大多数仍然有效。
编辑:再挖掘一下,发现这个特别提到了尝试创建一个已经存在的表的情况:http://www.sommarskog.se/error_handling/Part2.html#BatchTranAbort
根据这篇微软文章:XACT_STATE (Transact-SQL)
(...)发生错误导致交易被归类为不可提交的交易。请求无法提交事务或回滚到保存点;它只能请求完全回滚事务。
我先跑这个:
SELECT 1 AS Test INTO #tmpTest
SELECT @@TRANCOUNT, XACT_STATE()
BEGIN TRAN
SELECT @@TRANCOUNT, XACT_STATE()
然后:
BEGIN TRY
SELECT 1 AS Test INTO #tmpTest
END TRY
BEGIN CATCH
SELECT @@ERROR, ERROR_MESSAGE()
SELECT @@TRANCOUNT, XACT_STATE()
END CATCH
SELECT
块中的CATCH
返回:“数据库中已经有一个名为'#tmpTest'的对象。”,@@TRANCOUNT
是1
,但XACT_STATE
是-1
,因此SSMS中的错误消息指出:
消息3998,级别16,状态1,行1在批处理结束时检测到不可提交的事务。该事务被回滚。
下一个SELECT @@TRANCOUNT
返回0
。
以上是关于当INSERT INTO失败时,为什么我的事务会自动回滚?的主要内容,如果未能解决你的问题,请参考以下文章