我有一个关于TRY CATCH
块的MSDN文档的问题。查看这篇文章并向下滚动到示例C"使用TRY…CATCH with XACT_STATE"
该示例首先将COMMIT TRANSACTION
放在Try块中,然后将第二个XACT_STATE()=1
放在Catch块中。
然而,我认为Catch块只会在出现错误的情况下执行。那么,Catch块如何执行而XACT_STATE
返回1呢?这似乎很矛盾。
在XACT_STATE
文档中有一个未回答的注释,它问了同样的问题
@user1181412分析如下:注释:
——表中存在一个FOREIGN KEY约束。
——该语句将生成约束违反错误
是你问题的答案。实际情况是,当执行DELETE语句时,它会生成约束违反错误,并且随后的COMMIT不会执行。事务的XACT_STATE现在为1,CATCH块正在执行。
顶部是
SET XACT_ABORT ON;
这会导致事务状态不可提交,因此此代码块将回滚事务:
-- Test whether the transaction is uncommittable.
IF (XACT_STATE()) = -1
BEGIN
PRINT
N'The transaction is in an uncommittable state.' +
'Rolling back transaction.'
ROLLBACK TRANSACTION;
END;
然而,如果您更改为"SET XACT_ABORT OFF;",则CATCH块将被命中,尽管事务状态将作为XACT_STATE = 1是"可提交的"。
注意:删除仍然不会被执行,因为违反了约束,但是你会看到这样打印:
(1行)受影响)事务是可提交的。提交事务。
XACT_STATE是一个向用户返回正在运行的事务状态的函数。
XACT_STATE表示请求是否有活动的用户事务,以及该事务是否能够提交。(请记住,错误通常发生在update/insert而不是update/insert上)选择查询)。
XACT_STATE有3种状态:
1: Transaction块内的查询是活动且有效的(没有抛出错误)。
0:查询不会抛出错误(例如,在没有更新/插入查询的事务中执行select查询)。
-1:事务内部的查询抛出了一个错误(当进入catch块时),并将执行完整的回滚(如果我们有4个)查询成功且1次抛出错误,所有5次查询将滚动回)。
的例子:
BEGIN TRY
BEGIN TRANSACTION;
-- A FOREIGN KEY constraint exists on this table.
-- This statement will generate a constraint violation error.
DELETE FROM Production.Product
WHERE ProductID = 980;
-- If the delete operation succeeds, commit the transaction. The CATCH
-- block will not execute.
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
-- Test XACT_STATE for 0, 1, or -1.
-- Test whether the transaction is uncommittable.
IF (XACT_STATE()) = -1
BEGIN
PRINT 'The transaction is in an uncommittable state.' +
' Rolling back transaction.'
ROLLBACK TRANSACTION;
END;
-- Test whether the transaction is active and valid.
IF (XACT_STATE()) = 1
BEGIN
PRINT 'The transaction is committable.' +
' Committing transaction.'
COMMIT TRANSACTION;
END;
END CATCH
引用:
https://learn.microsoft.com/en-us/sql/t-sql/functions/xact-state-transact-sqlhttp://www.advancesharp.com/blog/1017/sql-transaction-status-and-xact-state