我对TRY CATCH
块的MSDN文档有疑问。查看本文并向下滚动到示例C“使用TRY ... CATCH与XACT_STATE”
http://msdn.microsoft.com/en-us/library/ms175976.aspx
该示例首先在Try块中放置COMMIT TRANSACTION
,然后在XACT_STATE()=1
中将第二个放在Catch块中。
但是我认为只有在出现错误时才会执行Catch块。那么Catch块如何执行并XACT_STATE
返回1?这似乎是矛盾的。
XACT_STATE
文档中有一条未回答的评论,询问同一个问题
答案 0 :(得分:2)
@ 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;”然后,虽然交易状态 可以“提交”为 XACT_STATE = 1 ,但CATCH块会被击中。
注意:由于约束违规仍然存在,仍然无法执行删除,但您会看到此内容:
(1行(s)受影响)交易是可提交的。提交 事务。
答案 1 :(得分:1)
XACT_STATE 是一个向用户返回正在运行的事务状态的函数。
XACT_STATE 表示请求是否具有活动用户事务,以及事务是否能够提交。
(请记住,通常在更新/插入时会发生错误而不会发生错误 选择查询)。
XACT_STATE有3种状态:
1 :Transaction块内的查询处于活动状态且有效(未抛出错误)。
0 :查询不会抛出错误(例如,没有更新/插入查询的事务中的选择查询)。
-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://docs.microsoft.com/en-us/sql/t-sql/functions/xact-state-transact-sql
http://www.advancesharp.com/blog/1017/sql-transaction-status-and-xact-state