为什么我的事务会在 INSERT INTO 失败时自动回滚?
Why is my transaction being rolled back automatically when INSERT INTO fails?
令人惊讶的是,对于我遇到的这个问题,我找不到任何相关的解释或文档。
在这些 SQL 语句的情况下:
SELECT 1 AS Test INTO #tmpTest
BEGIN TRAN
SELECT 1 AS Test INTO #tmpTest
ROLLBACK TRAN
当一个接一个执行时,第 3 行的 SELECT ... INTO
失败,如预期的那样,消息为 -
There is already an object named '#tmpTest' in the database.
然而,在那之后,第 4 行的 ROLLBACK
语句失败了:
The ROLLBACK TRANSACTION request has no corresponding BEGIN
TRANSACTION.
即使交易 完成了 BEGIN
从第 2 行成功。
我看过SQL Server - transactions roll back on error? but answers don't apply here because the default xact_abort
is off
. In addition, the answer from Quassnoi contradicts the answer by Raj More.
实际的解释是什么?
参考http://www.sommarskog.se/error-handling-I.html
在这种情况下,您得到的是批量中止,这会导致隐式回滚。该博客是关于 SQL Server 2000 错误处理的,但其中大部分仍然有效。
编辑:进一步挖掘发现了这个,它特别提到了尝试创建一个已经存在的 table 的情况:
http://www.sommarskog.se/error_handling/Part2.html#BatchTranAbort
根据这篇 Microsoft 文章:XACT_STATE (Transact-SQL)
(...) an error has occurred that has caused the transaction to be classified
as an uncommittable transaction. The request cannot commit the
transaction or roll back to a savepoint; it can only request a full
rollback of the transaction.
我先运行这个:
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
CATCH
块中的SELECT
返回:“数据库中已经有一个名为'#tmpTest'的对象。”,@@TRANCOUNT
是 1
,但 XACT_STATE
是 -1
,因此 SSMS 中的错误消息指出:
Msg 3998, Level 16, State 1, Line 1 Uncommittable transaction is
detected at the end of the batch. The transaction is rolled back.
下一个SELECT @@TRANCOUNT
returns0
.
令人惊讶的是,对于我遇到的这个问题,我找不到任何相关的解释或文档。
在这些 SQL 语句的情况下:
SELECT 1 AS Test INTO #tmpTest
BEGIN TRAN
SELECT 1 AS Test INTO #tmpTest
ROLLBACK TRAN
当一个接一个执行时,第 3 行的 SELECT ... INTO
失败,如预期的那样,消息为 -
There is already an object named '#tmpTest' in the database.
然而,在那之后,第 4 行的 ROLLBACK
语句失败了:
The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.
即使交易 完成了 BEGIN
从第 2 行成功。
我看过SQL Server - transactions roll back on error? but answers don't apply here because the default xact_abort
is off
. In addition, the answer from Quassnoi contradicts the answer by Raj More.
实际的解释是什么?
参考http://www.sommarskog.se/error-handling-I.html
在这种情况下,您得到的是批量中止,这会导致隐式回滚。该博客是关于 SQL Server 2000 错误处理的,但其中大部分仍然有效。
编辑:进一步挖掘发现了这个,它特别提到了尝试创建一个已经存在的 table 的情况: http://www.sommarskog.se/error_handling/Part2.html#BatchTranAbort
根据这篇 Microsoft 文章:XACT_STATE (Transact-SQL)
(...) an error has occurred that has caused the transaction to be classified as an uncommittable transaction. The request cannot commit the transaction or roll back to a savepoint; it can only request a full rollback of the transaction.
我先运行这个:
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
CATCH
块中的SELECT
返回:“数据库中已经有一个名为'#tmpTest'的对象。”,@@TRANCOUNT
是 1
,但 XACT_STATE
是 -1
,因此 SSMS 中的错误消息指出:
Msg 3998, Level 16, State 1, Line 1 Uncommittable transaction is detected at the end of the batch. The transaction is rolled back.
下一个SELECT @@TRANCOUNT
returns0
.