循环内 TRY/CATCH 内 RAISERROR 的行为

red*_*alx 1 sql-server-2008-r2 raiserror

我刚刚遇到了 SQL 的一部分,它的行为与我预期的不同(请参阅下面的有关 SQL 的提炼版本,该版本演示了问题模式)。

(这是在 SQL Server 2008 R2 SP2 64 位上)

“在这里做一些工作”部分会引发错误并触发 CATCH 块中的错误处理。错误编号为 515(尝试将空值插入不可为空的列),因此 RAISERROR 报告错误,但随后循环继续,再次尝试工作,在无限循环中引发错误等。

我希望 RAISERROR 导致执行退出循环。这里发生了什么?

谢谢

WHILE (@Applied <> 1)
BEGIN

    BEGIN TRY

        -- === Do some work here ===

        -- Successfully applied
        SET @Applied = 1;

    END TRY
    BEGIN CATCH

        -- Save the error details
        SELECT
            @ErrorNumber = ERROR_NUMBER(),
            @ErrorMessage = ERROR_MESSAGE(), 
            @ErrorSeverity = ERROR_SEVERITY(), 
            @ErrorState = ERROR_STATE();

        -- Test for a deadlock or uncommittable transaction
        IF (@ErrorNumber = 1205 OR @ErrorNumber = 3930)
            -- Sleep for 5 seconds
            WAITFOR DELAY '00:00:05';
        ELSE
            RAISERROR(@ErrorMessage, @ErrorSeverity, @ErrorState);

    END CATCH
END
Run Code Online (Sandbox Code Playgroud)

Sol*_*zky 6

RAISERROR通常不会停止执行。 THROW确实如此,但这是在 SQL 2012 中引入的。

将一个RETURN;RETURN -1;之后RAISERROR

以下内容摘自RAISERROR的 MSDN 页面的“备注”部分:

当 RAISERROR 在 TRY 块中以 11 或更高的严重性运行时,它会将控制转移到关联的 CATCH 块。如果运行 RAISERROR,错误将返回给调用者:

  • 在任何 TRY 块的范围之外。
  • TRY 块中的严重性为 10 或更低。
  • 严重性为 20 或更高的终止数据库连接。

下面是对行为的简单测试。如果在 2012 年之前的 SQL Server 版本上运行,请注释掉或删除带有THROW.

RAISERROR(N'This is from RAISERROR - Severity 16', 16, 1);
PRINT N'----- 1';

;THROW 50505, N'This is from THROW', 1;
PRINT N'----- 2';

GO

PRINT N'----- 3';

-- WITH LOG needed for severity > 18
RAISERROR(N'This is from RAISERROR - Severity 20', 20, 1) WITH LOG;
PRINT N'----- 4';

GO

PRINT N'----- 5';
Run Code Online (Sandbox Code Playgroud)

上述测试在“消息”选项卡中返回以下内容:

Msg 50000, Level 16, State 1, Line 2
这是来自 RAISERROR - Severity 16
----- 1
Msg 50505, Level 16, State 1, Line 5
这是来自 THROW
----- 3
Msg 2745, Level 16 ,状态 2,第 4 行
进程 ID 54 引发了用户错误 50000,严重性为 20。SQL Server 正在终止此进程。
Msg 50000, Level 20, State 1, Line 4
这是来自 RAISERROR - Severity 20
Msg 0, Level 20, State 0, Line 0
当前命令发生严重错误。结果,如果有的话,应该被丢弃。

在 SSMS 的左下角,它将指示“已断开连接”。