事务中的T-SQL抛出异常

时间:2015-07-07 16:24:50

标签: .net sql-server tsql

今天我试图在一个存储过程中编写一个事务,在某个特定的回程中返回不同的数字。 C#代码必须知道错误究竟是什么。问题是,如果事务没有完成,它会抛出相同的异常。

我无法在事务中抛出异常,总是给出错误的语法。我正在尝试这种模式:

THROW 51000, 'The record does not exist.', 1;

是否可以制作这样的东西:

BEGIN TRAN
  TRY

  IF...
     THROW ERROR 4;

  IF..
    THROW ERROR 2;

COMPLETE TRAN;
CATCH
   RETURN ERROR NUMBER;

我只需要从存储过程返回的特定错误数。

你能举个例子吗?

P.S。我忘了哪个是我们的sql server的版本,不,我不在办公室。它是2008年或2012年。

2 个答案:

答案 0 :(得分:3)

您可以使用以下语法:

BEGIN TRY
     BEGIN TRANSACTION
          IF ...  RAISERROR(51001, 16, 1)
          IF ...  RAISERROR(51002, 16, 1)
     COMMIT TRANSACTION
END TRY
BEGIN CATCH
     DECLARE @ErrorNumber INT = ERROR_NUMBER();
     DECLARE @ErrorLine INT = ERROR_LINE();
     DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE();
     DECLARE @ErrorSeverity INT = ERROR_SEVERITY();
     DECLARE @ErrorState INT = ERROR_STATE();

     IF @@TRANCOUNT > 0
          ROLLBACK TRANSACTION;

     RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState);
END CATCH

错误编号应大于50000。您可以添加sp_addmessage程序。 Throw中引入了Sql Server 2012。有一些差异。您可以在MSDN中轻松找到它们。

答案 1 :(得分:0)

您应该使用RAISERROR(在documentation中阅读更多内容)而不是THROW(请参阅documentation)。

THROW只会在CATCH块中重新抛出现有异常,而不会触发完整的新异常。它是在SQL Server 2012中引入的。抛出错误的两个函数的主要用法非常简单。如果TRY内发生错误,并且您使用CATCHRAISERROR块中重新抛出错误 - 这是2008年的最新状态 - 它可能会提供许多有用的信息但是发生错误的代码行转移到使用RAISERROR引发错误的行,而不是错误发生的行。使用THROW它将使用所有信息重新抛出错误,甚至是最初发生错误的原始行。

相反,您可以使用此方法抛出自己的异常:

RAISERROR(N'Your Errormessage',16,1)

顺便说一下,RAISERROR使用的每条错误消息的错误消息都是50000或更高。您可以使用自己的ID定义自己的错误消息(大于50000)。如果您定义了自己的消息ID,则可以使用RAISERROR抛出用户定义的错误,如下所示:

RAISERROR(50001,16,1)

旁边信息:您可以重载RAISERROR以将值解析为错误消息。

RAISERROR(N'A error occurred while iterating over row ID %i',16,1,@rowId)