Уровень серьезности 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
, вы можете никогда не узнать, когда могут появиться ваши информационные сообщения.
Они могут появляться с перерывами на протяжении всей партии или сразу после завершения партии.