不同的 RAISERROR 严重级别是啥意思?

Posted

技术标签:

【中文标题】不同的 RAISERROR 严重级别是啥意思?【英文标题】:What do the different RAISERROR severity levels mean?不同的 RAISERROR 严重级别是什么意思? 【发布时间】:2009-07-14 00:46:04 【问题描述】:

我最好的谷歌搜索结果是this:

以下 11 个是警告,而不是错误 11-16可用 超过 16 个是系统错误 11-16 之间没有行为差异

但是,根据 BOL,“任何用户都可以指定从 0 到 18 的严重级别。”

在我的特定存储过程中,我希望将错误返回给 .Net 客户端应用程序,因此看起来 11-18 之间的任何严重级别都可以解决问题。有没有人有任何关于每个级别的含义以及应该如何使用它们的权威信息?

【问题讨论】:

我不知道其他版本,但我很惊讶地看到,对于 SQL Server 2008,严重性 16 确实 NOT 终止执行。 我在 Delphi 应用程序中使用相同的技巧,经过反复试验后我使用 level = 13。这样执行不会停止(我在触发器中引发错误以显示用户信息)并且用户收到消息。当然,这是一种“非常糟糕的做法”,但很有效。 “可怕的不良做法”对于绕过许多、许多、许多 MS 障碍是必要的。不过,绕过 MS 障碍通常是一种“好习惯”。 任何有兴趣更深入探索 sqlserver 错误处理的人,请参阅 Erland Sommarskog 的优秀系列sommarskog.se/error_handling/Part1.html 【参考方案1】:

Database Engine Severity Levels

你应该返回 16。是默认的,最常用的错误级别:

表示可能出现的一般错误 由用户更正。

不要返回 17-18,那些表示更严重的错误,比如资源问题:

指出不能出现的软件错误 由用户纠正。通知您的 系统管理员的问题。

也不要返回 11-15,因为它们具有附加到每个级别的特殊含义(14 - 安全访问,15 - 语法错误,13 - 死锁等)。

第 16 级不会终止执行。

如果您打算记录警告但继续执行,请改用低于 10 的严重性级别。

【讨论】:

MSDN 链接说明了一切——信息就在 BOL 中,我以前从未见过。谢谢! 当你说“默认”时,你的意思是如果我调用RAISERROR,不传递任何参数,就会使用16的错误级别。即它会被一个 catch 块捕获? 16 级不会终止执行。见***.com/questions/76346/…。除非我遗漏了什么,否则您可能需要更新您的答案。 外键违规错误的严重性也为 16。其他数据完整性错误也可能具有此严重性,我不知道,但如果您提出和处理“业务规则”错误,则可能为 16误导。就我而言,我最终使用 out 参数来表示成功(真或假)和错误消息。 @mcNux 绝对正确,第 16 级确实终止刚刚在 SQL Server 2008 R2 和 SQL Server 2012 上测试的执行。Rolled back edit.【参考方案2】:

严重级别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,您可能永远不知道您的信息消息何时会出现。 它们可能在整个批处理过程中间歇出现,或者在批处理完成时同时出现。

【讨论】:

即使使用 @divideByZero 也不会在 Sql 2016 上终止

以上是关于不同的 RAISERROR 严重级别是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

sql server数据库中raiserror函数的用法

latex 中 \ra 是啥意思 ?

在 raiserror sqlserver 上终止进程

电脑文件属性为R,RS,A,SA,S,RA是啥意思,谢谢

英文名fedora是啥意思

overriding是啥意思