RAISERROR何时在存储过程中触发?

时间:2013-08-14 03:22:09

标签: sql sql-server tsql sql-server-2012

我有一个包含try-catch块的存储过程。在catch块中,我调用raiserror()以在某些上下文中重新抛出错误。

我原以为如果发生错误,将调用raiserror(),执行将立即从存储过程返回到调用代码。但是,情况似乎并非如此。看起来存储过程的执行一直持续到它返回一个return语句,然后raiserror()生效。

这是正确的 - 在调用return或者到达存储过程结束之前,raiserror()不起作用吗?

我正在使用SQL Server 2012。

修改 在回复对存储过程的详细信息的请求时,这里是相关的代码片段:

DECLARE @ErrMsg VARCHAR(127) = 'Error in stored procedure ' + OBJECT_NAME(@@PROCID) + ': %s';

declare @UpdateDateRecordCount table (LastUpdated datetime, NumberRecords int);
begin try;
    insert into @UpdateDateRecordCount (LastUpdated, NumberRecords)
    exec sp_ExecuteSql 
        @UpdateCountQuery, 
        N'@LastUpdated datetime', 
        @LastUpdated = @LastUpdated;

    if @@rowcount <= 0
    begin;
        return 0;
    end; 
end try
begin catch;
    declare @InsertError varchar(128) = 'Error getting updated date record count: ' 
        + ERROR_MESSAGE();
    RAISERROR (@ErrMsg, 16, 1, @InsertError);
end catch;

-- Attempt to loop through the records in @UpdateDateRecordCount...

@UpdateCountQuery参数将设置为:

N'select LastUpdated, count(*) from dbo.Part where LastUpdated > @LastUpdated group by LastUpdated;'

3 个答案:

答案 0 :(得分:2)

据我了解,如果您希望执行停止,则需要在TRY块中引发错误,然后在CATCH块中再次引发错误,这将确保错误被“提升”给调用者。

或者您可以在RETURN块中的RAISERROR语句后添加CATCH语句。这将退出程序并返回给调用者。

此外,根据MSDN的建议,您应该尝试使用THROW语句而不是RAISERROR语句,因为它(RAISERROR)将被淘汰。

答案 1 :(得分:2)

这不是它在T-SQL中的工作方式。 TRY...CATCHRAISERROR的文档中没有任何内容指定任何会覆盖的特殊情况:

  

当CATCH块中的代码完成时,控制将立即传递到END CATCH语句之后的语句。 CATCH块捕获的错误不会返回给调用应用程序。如果必须将错误信息的任何部分返回给应用程序,则CATCH块中的代码必须通过使用SELECT结果集或RAISERROR和PRINT语句等机制来执行此操作。

如果您希望退出存储过程,则还需要RETURN语句。

答案 2 :(得分:0)

这取决于您使用的严重性级别。以下链接提供了更多信息:

http://technet.microsoft.com/en-us/library/ms178592.aspx

但要引用这篇文章:

  

RAISERROR生成的错误与生成的错误相同   通过数据库引擎代码。 RAISERROR指定的值是   由ERROR_LINE,ERROR_MESSAGE,ERROR_NUMBER报告,   ERROR_PROCEDURE,ERROR_SEVERITY,ERROR_STATE和@@ ERROR系统   功能。当RAISERROR在a中以11或更高的严重性运行时   TRY块,它将控制转移到相关的CATCH块。该   如果运行RAISERROR,则会向调用者返回错误...

因此,如果您的严重性级别为11或更高,则控件将立即转移到CATCH块。

以下示例显示严重性级别为16:

RAISERROR ('Error raised in TRY block.', -- Message text.
16, -- Severity.
1 -- State.
);