【问题标题】:SQL Server TRY...CATCH with XACT_STATESQL Server TRY...CATCH 与 XACT_STATE
【发布时间】:2013-04-16 17:37:58
【问题描述】:

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

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

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

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

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

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

【问题讨论】:

  • 想选择答案还是提供答案?对您在 SO 上的代表有很大帮助

标签: sql sql-server msdn


【解决方案1】:

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

【讨论】:

    【解决方案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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-09
      • 1970-01-01
      • 2010-11-15
      • 2020-01-16
      • 2020-03-13
      • 2020-04-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多