Что означают различные уровни серьезности RAISERROR? - PullRequest
69 голосов
/ 14 июля 2009

Мой лучший результат в Google был this :

  • ниже 11 - предупреждения, а не ошибки
  • 11-16 доступны для использования
  • выше 16 - системные ошибки
  • нет никаких поведенческих различий среди 11-16

Но из BOL «Уровни серьезности от 0 до 18 могут быть заданы любым пользователем».

В моей конкретной хранимой процедуре я хочу, чтобы ошибка возвращалась клиентскому приложению .Net, поэтому похоже, что любой уровень серьезности в диапазоне от 11 до 18 поможет. Есть ли у кого-нибудь достоверная информация о том, что означает каждый из уровней и как их следует использовать?

Ответы [ 2 ]

101 голосов
/ 14 июля 2009

Уровни серьезности ядра СУБД

Вы должны вернуть 16. По умолчанию, наиболее часто используемый уровень ошибок:

Указывает на общие ошибки, которые могут быть исправлено пользователем.

Не возвращайте 17-18, это указывает на более серьезные ошибки, такие как проблемы с ресурсами:

Укажите программные ошибки, которые не могут быть исправлено пользователем. Сообщите ваш системный администратор проблемы.

Также не возвращайте 11-15, потому что они имеют специальное значение, прикрепленное к каждому уровню (14 - безопасный доступ, 15 - синтаксическая ошибка, 13 - тупик и т. Д.).

Уровень 16 не прекращает выполнение.

Если вы хотите записать предупреждение, но продолжить выполнение, используйте уровень серьезности ниже 10.

3 голосов
/ 05 августа 2018

Уровень серьезности 16 может Прекратить выполнение.

Предупреждения TRY-CATCH с RAISERROR ():

RAISERROR() со степенью серьезности 16 прекращает выполнение для всего, что находится за ошибочной строкой.
Однако этот только применяется, когда находится внутри пробного блока.

--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 в качестве строки last внутри вашего Catch-Block для правильного
выбросить исключение SQL для события RAISERROR(), вызванного вашим блоком проб.
Это эффективно остановит выполнение с полной остановкой.
Точка с запятой ; требуется, когда в Catch-Block существуют другие строки перед вызовом ;THROW.
Если ваша логика правильно обрабатывает ошибку в Catch-Block (и вы хотели бы продолжить обработку
остальная часть логики после него), затем не используйте ;THROW.

Вывод:

Не сравнивайте серьезность - 16 , выдаваемую SQL-Server-Engine
с одним вы поднимаете себя, используя RAISERROR().
Для всех намерений и целей (когда сознательно выкидываете собственные ошибки), учитывайте только 2 уровня серьезности:
0 (для информации или предупреждения) и
16 (для Броска Исключения, обработанного в Пробном Блоке - чтобы выбросить его в 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, вы можете никогда не узнать, когда могут появиться ваши информационные сообщения.
Они могут появляться с перерывами на протяжении всей партии или сразу после завершения партии.

...