严重级别16 可以终止执行。
使用 RAISERROR() 的 TRY-CATCH 警告:
RAISERROR() 的严重性为 16 会终止违规行以下的所有内容的执行。
但是仅此 适用于 Try-Block 内。
--DECLARE @DivideByZero Int = 1/0--Uncommenting this will Skip everything below.
RAISERROR (N'Before Try: Raise-Error 16.', 16, 0)--Works.
SELECT 'Before Try: Select.'[Marker]--Works.
BEGIN TRY
RAISERROR (N'Inside Try: Raise-Error 16.', 16, 0)--Not displayed,but sends to Catch-Block.
SELECT 'Inside Try: Select.'[Marker]--Skipped.
END TRY
BEGIN CATCH
RAISERROR (N'Inside Catch: Raise-Error 16.', 16, 0)--Works.
SELECT 'Inside Catch: Select.'[Marker]--Works.
--RETURN --Adding Return will only skip what is After the Catch-Block for this scope only.
--;THROW--Shows the RAISERROR() from the Try-Block and Halts Execution. Must include ";".
END CATCH
RAISERROR (N'After Try-Catch: Raise-Error 16.', 16, 0)--Works.
SELECT 'After Try-Catch: Select.'[Marker]--Works.
惊讶吗?我也是。
也让我陷入困境的是并非所有严重性 -16 都是相同的。
如果您取消注释最顶部的除零线,那么它下面的任何内容都不会运行。
除零逻辑也会生成严重性-16异常,
但它是用句号处理的,不像用RAISERROR()抛出。
注意:使用 ;THROW 作为您的 Catch-Block 中的 最后 行以正确
为 Try-Block 触发的 RAISERROR() 事件抛出 SQL 异常。
这将有效地停止执行。
在调用 ;THROW 之前,如果 Catch-Block 中存在其他行,则需要 ; 分号。
如果您的逻辑正确处理 Catch-Block 中的错误(并且您希望继续处理
之后的其余逻辑),然后不使用;THROW。
结论:
不要将 SQL-Server-Engine 抛出的 Severity-16 混为一谈
使用RAISERROR().
出于所有意图和目的(当故意抛出您自己的错误时),请仅考虑 2 个严重性:
0(用于信息或警告)和
16(用于在 Try-Block 中处理抛出异常 - 将其踢出到 Catch-Block)。
立即提供信息!
注意:如果您使用RAISERROR() 显示信息性消息,
那么我建议使用WITH NOWAIT:
RAISERROR('Read me right now!', 0, 1) WITH NOWAIT
RAISERROR('Read me whenever.' , 0, 1)
DECLARE @WaitSeconds Int = 10
DECLARE @WaitFor DateTime = DATEADD(SECOND, @WaitSeconds, 0)
WAITFOR DELAY @WaitFor
当您需要一些洞察力时,这在长时间批处理操作中特别有用
当您在整个批次中达到某些里程碑标记时,了解事情的进展情况。
不使用WITH NOWAIT,您可能永远不知道您的信息消息何时会出现。
它们可能在整个批处理过程中间歇出现,或者在批处理完成时同时出现。