【问题标题】:set xact_abort on and try catch together设置 xact_abort 并尝试一起捕捉
【发布时间】:2013-04-05 16:59:09
【问题描述】:

我的 sp 中有一个 try catch 块,在 try 中只有一个 insert 语句。如果是 pk 违规,则 catch 检查错误代码,如果是则进行更新。但有时我会得到“当前事务无法提交,并且无法支持写入日志文件的操作。回滚事务。

在批处理结束时检测到不可提交的事务。事务已回滚。”所以我添加了 xact_abort,但随后我不断收到“EXECUTE 后的事务计数表明 BEGIN 和 COMMIT 语句的数量不匹配。”我找到了这个。 http://www.ashishsheth.com/post/2009/08/14/Set-XACT_ABORT-ON-and-TryCatch-block-in-Sql-Server-2005.aspx

如果这是真的。如果打开 xact_abort 的 try 块中出现错误,我的 catch 代码会不会运行?

【问题讨论】:

    标签: sql-server try-catch xact-abort


    【解决方案1】:

    至少对于 SQL SERVER 2008,SET XACT_ABORT ON 不会导致跳过 CATCH 块的错误:

    这是我尝试使用 Northwind 数据库的代码

    SET XACT_ABORT OFF
    BEGIN TRY
        SELECT 1,  @@TRANCOUNT
    BEGIN TRAN
        UPDATE [dbo].[Categories]
        SET Description='BLAH'
        WHERE [CategoryID]=2
        SELECT 2,  @@TRANCOUNT
    
        SELECT 1/0 as whoops
    
    
    COMMIT
        SELECT 3,  @@TRANCOUNT
    
    END TRY
    BEGIN CATCH
        SELECT 'In Catch. Error occured', 4,  @@TRANCOUNT
    
         IF (XACT_STATE()) = 0
        BEGIN
            SELECT
                N'There is no transaction'
    
        END;
    
    
         IF (XACT_STATE()) = -1
        BEGIN
            SELECT
                N'The transaction is in an uncommittable state.' +
                'Rolling back transaction.'
            ROLLBACK TRANSACTION;
        END;
    
        -- Test whether the transaction is committable.
        IF (XACT_STATE()) = 1
        BEGIN
            SELECT
                N'The transaction is committable.' +
                'Committing transaction.'
            COMMIT TRANSACTION;   
        END;
    
    END CATCH
    

    这显然会在遇到 SELECT 1/0 语句时强制出错。在 SET XACT_ABORT OFF 的情况下,当到达 CATCH 块时,XACT_STATE() 函数返回的值为 1,从而导致运行提交事务的代码。当 SET XACT_ABORT 开启时,在 CATCH 块中返回的值为 -1,因此执行回滚事务的代码。

    这是基于:

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

    【讨论】:

    • 对不起,我迟到了...我同意迈克尔的观点,如果您启用了 XACT_ABORT,则在回滚之前“正在”执行 catch 块。有趣的是,你在 catch 块中所做的任何事情都会被回滚,因此看起来你甚至没有执行其中的任何内容。如果您在 CATCH 块中放置一条 select 语句,即使会引发错误,您也会看到它在 SSMS 中吐出。
    • @Eli - 当 XACT_ABORT 设置为 ON 时,try catch 是否有任何用途?因为无论如何所有错误都会导致事务回滚。
    • @variable 这是个好问题,我没想到。
    【解决方案2】:

    让我补充一点,在那种特定情况下(尝试插入,如果 PK 违规然后捕获并更新),最好使用 IF EXISTS (select....) 来查看该行是否存在并将您的那里有 UPDATE 语句。将您的 INSERT 语句放在 ELSE 块中。干净多了。

    【讨论】:

      猜你喜欢
      • 2014-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-25
      • 1970-01-01
      • 2011-08-07
      • 1970-01-01
      相关资源
      最近更新 更多