为何Catch块执行RAISERROR后,Inner Catch后续代码未触发?
问题:为什么Inner Catch的后续代码没有执行?
执行下方存储过程后,只得到了error outer - INTERESTING THIS FIRES的输出,却没有看到Inner Catch- INTERESTING THIS FIRES,这是什么原因?
存储过程代码
/* EXEC SP_RAISERROR_TRYCATCHTEST3 */ CREATE PROCEDURE [dbo].[SP_RAISERROR_TRYCATCHTEST3] AS SET NOCOUNT ON DECLARE @ERRMSG VARCHAR(200) BEGIN TRY SELECT 'IN 1ST TRY IE OUTER' PRINT 'IN 1ST TRY IE OUTER' BEGIN TRY SELECT 'IN 2ND TRY IE INNER' PRINT 'IN 2ND TRY IE INNER' RAISERROR('THROWN FROM INNER', 16, 1) SELECT 'ENDING NORMAL IN 2ND TRY IE INNER' PRINT 'ENDING NORMAL IN 2ND TRY IE INNER' END TRY BEGIN CATCH SET @ERRMSG = 'CAUGHT IN INNER CATCH. ERRMSG IS: ' + ERROR_MESSAGE() SELECT @ERRMSG AS ERRMSG PRINT @ERRMSG RAISERROR ('Totally New Throw from INNER CATCH', 16, 1) SELECT 'Inner Catch- INTERESTING THIS FIRES' PRINT 'Inner catch - INTERESTING THIS FIRES' END CATCH SELECT 'ENDING NORMAL IN 1ST TRY IE OUTER' PRINT 'ENDING NORMAL IN 1ST TRY IE OUTER' END TRY BEGIN CATCH SET @ERRMSG = 'CAUGHT IN OUTER CATCH. ERRMSG IS: ' + ERROR_MESSAGE() SELECT @ERRMSG AS ERRMSG PRINT @ERRMSG RAISERROR ('Totally New Throw from Outer CATCH', 16, 1) SELECT 'error outer - INTERESTING THIS FIRES' PRINT 'error outer - INTERESTING THIS FIRES' END CATCH SELECT 'SP END' PRINT 'SP END'
执行结果
IN 1ST TRY IE OUTER IN 2ND TRY IE INNER CAUGHT IN INNER CATCH. ERRMSG IS: THROWN FROM INNER CAUGHT IN OUTER CATCH. ERRMSG IS: Totally New Throw from INNER CATCH Msg 50000, Level 16, State 1, Procedure SP_RAISERROR_TRYCATCHTEST3, Line 68 [Batch Start Line 15] Totally New Throw from Outer CATCH error outer - INTERESTING THIS FIRES SP END
原因分析
核心原因是:当在BEGIN CATCH块中使用RAISERROR抛出严重级别≥11的错误时,会立即中断当前CATCH块的执行流程,直接跳转到外层的TRY/CATCH结构(如果存在)。
具体到你的代码执行流程:
- 内层TRY块抛出错误后,进入内层CATCH块,先执行了错误信息的输出语句。
- 随后执行的
RAISERROR ('Totally New Throw from INNER CATCH', 16, 1)中,错误级别为16(属于≥11的级别),这条语句执行后,内层CATCH块中后续的SELECT 'Inner Catch- INTERESTING THIS FIRES'和PRINT语句直接被跳过,程序直接进入外层CATCH块。 - 而外层CATCH块执行
RAISERROR时,因为已经没有更上层的TRY/CATCH结构,所以该错误只会返回给客户端,不会中断当前CATCH块的执行——因此外层CATCH里的error outer - INTERESTING THIS FIRES语句能正常执行。
如果想让内层CATCH的后续代码执行,有两种办法:
- 降低
RAISERROR的错误级别到10及以下(这类错误不会触发CATCH块的跳转); - 将
RAISERROR语句放在内层CATCH块的最后一行。
内容的提问来源于stack exchange,提问作者americano
相关产品推荐
相关产品推荐

