11

我对块的 MSDN 文档有疑问TRY CATCH。查看这篇文章并向下滚动到示例 C“使用 TRY…CATCH 和 XACT_STATE”

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

该示例首先将 aCOMMIT TRANSACTION放在 Try 块中,然后将第二个放在 Catch 块中 if XACT_STATE()=1

但是我认为 Catch 块只会在出现错误的情况下执行。那么 Catch 块如何执行并XACT_STATE返回 1 呢?这似乎很矛盾。

文档中有一条未答复的评论XACT_STATE提出了同样的问题

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

4

2 回答 2

5

@user1181412 我的分析如下: 此评论:

-- 此表上存在 FOREIGN KEY 约束。

--该语句会产生约束违规错误

是您问题的答案。发生的情况是,当 DELETE 语句执行时,它会生成约束冲突错误,并且后续的 COMMIT 不会执行。事务的 XACT_STATE 现在为 1,并且正在执行 CATCH 块。

在顶部,您有

设置 XACT_ABORT 开;

这会导致事务状态不可提交,因此此代码块将回滚事务:

-- 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 行受影响)事务是可提交的。正在提交事务。

于 2013-07-15T11:51:33.483 回答
2

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

于 2018-04-12T21:17:19.280 回答