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 抛出和事务的主要内容,如果未能解决你的问题,请参考以下文章