SQL Server 抛出和事务

Posted

技术标签:

【中文标题】SQL Server 抛出和事务【英文标题】:SQL Server Throw and transactions 【发布时间】:2016-09-26 14:28:18 【问题描述】:

我完全明白向调用程序抛出错误以提供信息是一件奇怪的事情,但是使用我在这里给出的内容,但我有以下代码,我从 C# 调用。

错误被抛出,但数据没有被删除。如果我不抛出,则数据将被删除。鉴于我在事务中有删除,为什么抛出后会导致删除被回滚,这似乎是它正在做的事情。

IF (@action = 'D')
        BEGIN
            BEGIN TRANSACTION
                DELETE FROM dbo.inv_detail WHERE inv_id = @inv_id;
                DELETE FROM dbo.inv_header WHERE inv_id = @inv_id;
            COMMIT TRAN

            --Returns an info message to indicate that the repository invoice has been deleted
            SET @InfoMessage = 'Number: ' + LTRIM(STR(@inv_ref_nbr)) + ' for Site: ' + LTRIM(STR(@site)) + ' has been deleted';
            THROW 50001, @InfoMessage, 1;
        END

这被包裹在一个 try/catch 中,其中 catch 是:

BEGIN CATCH

        SELECT  @ErrorNumber = ERROR_NUMBER(),
                @ErrorMessage = ERROR_MESSAGE(),
                @ErrorSeverity = ERROR_SEVERITY(),
                @ErrorState = ERROR_STATE();

        -- Use RAISERROR inside the CATCH block to return error
        -- information about the original error that caused
        -- execution to jump to the CATCH block.
        RAISERROR (@ErrorMessage,  -- Message text.
                   @ErrorSeverity, -- Severity.
                   @ErrorState     -- State.
                   );
    END CATCH

【问题讨论】:

If I don't throw then the data is deleted. 不是说没有错误吗? 是的,他们正在使用它来将删除的详细信息返回给调用程序。他们没有将它用于真正的错误。我得到正确的做法很可能是一个输出参数,但只是好奇投掷看似回滚上面的删除事务,即使它已被提交。 你总是抛出错误THROW 50001, @InfoMessage, 1; 对,这一切都包含在一个 try catch 中,所以如果在删除过程中发生真正的错误,它将命中外部捕获,但如果没有发生错误,我会抛出这个信息消息,说一切顺利。 听起来您可能会在导致回滚的某些外层触发错误处理。您是否考虑过使用RAISERROR 生成具有“信息”严重性(TRY...CATCH 忽略,并且也应该被任何外部层忽略(取决于它们的编码方式)。 msdn.microsoft.com/en-us/library/ms178592.aspx。 THROW 总是引发严重性为 16 的错误。 【参考方案1】:

从 cmets 推断,问题是由于调用 C# 代码正在事务中执行您的 T-SQL 而引起的。当出现错误时,C# 代码会自动检测并回滚整个事务。

您提到此代码的原始版本使用RAISERROR 引发低严重性错误。 严重性 TRY...CATCH 忽略 - 并且通过推断,您使用的 C# 数据库驱动程序尊重这一点。

相比之下,THROW 总是引发严重性为 16 的错误 - 这被视为实际错误,被 TRY...CATCH 捕获并重新抛出到 C# - 这会触发回滚。

(错误和PRINT 消息被传递到与结果集不同的 TDS 流上的 SQL 客户端。请参阅here 了解读取它们的方法。我的猜测是原始程序员是如何读取返回的低严重性消息。)

【讨论】:

以上是关于SQL Server 抛出和事务的主要内容,如果未能解决你的问题,请参考以下文章

sql server中的事务是啥意思

sql server 2012 事务日志在哪

sql server运行中,是不是能删除主数据库事务日志文件

怎样读sql server 2008 事务日志

SQL Server事务 事务日志

SQL Server 事务异常和游标