SQL Server TRY ...使用XACT_STATE进行捕获

时间:2013-04-16 17:37:59

标签: sql sql-server msdn

我对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文档中有一条未回答的评论,询问同一个问题

http://msdn.microsoft.com/en-us/library/ms189797.aspx

2 个答案:

答案 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