如何在SQL Server存储过程中执行RAISERROR且让过程成功结束?
问题场景
现有SQL Server存储过程通过RAISERROR输出统计数量,以此触发日志系统写入日志文件供Hangfire监控使用。但RAISERROR会导致存储过程被标记为执行失败;用BEGIN TRY/BEGIN CATCH包裹后,日志记录又无法触发。需要实现RAISERROR正常触发日志,同时让存储过程成功结束。
原代码片段
IF EXISTS (SELECT 1 FROM @UnprocessedCollaterals) BEGIN DECLARE @ErrorMessage NVARCHAR(MAX); DECLARE @Count int; SELECT @Count = COUNT(DISTINCT CollUpdProcessPK) FROM @Unprocessed; RAISERROR ('Total: %d', 16, 1, @Count); END;
尝试的代码
BEGIN TRY RAISERROR ('Total: %d', 16, 1, @Count); END TRY BEGIN CATCH END CATCH
解决方案
核心思路是调整错误消息的触发逻辑,既要让日志系统捕获到信息,又不触发存储过程的失败标记。
方法1:降低RAISERROR的错误级别
SQL Server中,错误级别1-10属于信息性消息,不会触发异常、不会标记存储过程失败,但仍会输出消息。如果日志系统能捕获这类信息,直接修改级别即可:
IF EXISTS (SELECT 1 FROM @UnprocessedCollaterals) BEGIN DECLARE @Count int; SELECT @Count = COUNT(DISTINCT CollUpdProcessPK) FROM @Unprocessed; -- 将错误级别从16改为10(信息级别),加NOWAIT确保消息即时输出 RAISERROR ('Total: %d', 10, 1, @Count) WITH NOWAIT; END;
方法2:捕获异常后重新输出消息(针对必须用级别16的场景)
如果日志系统只能捕获级别≥16的错误,可在CATCH块中重新输出消息,避免存储过程因异常终止:
IF EXISTS (SELECT 1 FROM @UnprocessedCollaterals) BEGIN DECLARE @Count int; SELECT @Count = COUNT(DISTINCT CollUpdProcessPK) FROM @Unprocessed; BEGIN TRY RAISERROR ('Total: %d', 16, 1, @Count); END TRY BEGIN CATCH -- 用PRINT输出错误信息,或用低级别RAISERROR保持格式 PRINT ERROR_MESSAGE(); -- 可选:RAISERROR(ERROR_MESSAGE(), 10, 1) WITH NOWAIT; END CATCH END;
方法3:用THROW配合TRY/CATCH(SQL Server 2012+)
如果使用SQL Server 2012及以上版本,用THROW抛出自定义错误,再在CATCH中处理,既能触发日志又能让存储过程正常结束:
IF EXISTS (SELECT 1 FROM @UnprocessedCollaterals) BEGIN DECLARE @Count int; SELECT @Count = COUNT(DISTINCT CollUpdProcessPK) FROM @Unprocessed; DECLARE @Msg NVARCHAR(MAX) = FORMATMESSAGE('Total: %d', @Count); BEGIN TRY -- 自定义错误号(需在50000-2147483647范围内) THROW 50000, @Msg, 1; END TRY BEGIN CATCH PRINT ERROR_MESSAGE(); -- 可选:RAISERROR(ERROR_MESSAGE(), 10, 1) WITH NOWAIT; END CATCH END;
内容的提问来源于stack exchange,提问作者B. Baxter
相关产品推荐
相关产品推荐

