我有一个包含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;'
答案 0 :(得分:2)
据我了解,如果您希望执行停止,则需要在TRY
块中引发错误,然后在CATCH
块中再次引发错误,这将确保错误被“提升”给调用者。
或者您可以在RETURN
块中的RAISERROR
语句后添加CATCH
语句。这将退出程序并返回给调用者。
此外,根据MSDN的建议,您应该尝试使用THROW语句而不是RAISERROR
语句,因为它(RAISERROR
)将被淘汰。
答案 1 :(得分:2)
这不是它在T-SQL中的工作方式。 TRY...CATCH
或RAISERROR
的文档中没有任何内容指定任何会覆盖的特殊情况:
当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.
);