Почему T-SQL не останавливается на ошибках - PullRequest
0 голосов
/ 16 мая 2018

Если я выполняю следующий запрос

EXEC spFoo
PRINT 'TEST'

и spFoo выдает ошибку, он все равно выполняет оператор печати. ​​

Однако, если я делаю

BEGIN TRY
    EXEC cdb.spFoo
    PRINT 'TEST'
END TRY
BEGIN CATCH
    THROW;
END CATCH

Он ведет себя так, как я ожидал, и не продолжает работать после ошибки.

Может кто-нибудь объяснить мне это поведение?Это все еще продолжается, даже если я включу его в транзакцию.Это не только с печатным заявлением, но и с любой другой вещью.Сначала я думал, что это проблема серьезности, но серьезность была 16-го уровня. Это нормальное поведение T-SQL?Если это так, что мотивирует этот дизайн, который противоречит любому другому языку, с которым я когда-либо работал, который напрямую увеличивает ошибку?

Я пробовал и видел такое же поведение в SQL Server 2012, 2014 и 2017 на нескольких разных машинах.Рассматриваемая хранимая процедура связана с SQL CLR.

Ответы [ 3 ]

0 голосов
/ 16 мая 2018

TRY .. CATCH

Не остановит процесс запроса.Если вы не хотите продолжать после обнаружения ошибки, используйте RETURN.Это остановит процесс.Также, если вы используете BEGIN TRANSACTION, пожалуйста, используйте ROLLBACK, прежде чем вернуться из процесса.В противном случае это приведет к незафиксированным транзакциям.

0 голосов
/ 16 мая 2018

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

В первом примере:

EXEC spFoo
PRINT 'TEST'

это независимые операторы и, хотя spFoo может произойти сбой, сервер перейдет к следующему оператору.Это связано с тем, что уровень серьезности меньше 20, партия не была автоматически прервана.

Во втором примере

BEGIN TRY
    EXEC cdb.spFoo
    PRINT 'TEST'
END TRY
BEGIN CATCH
    THROW;
END CATCH

вы приняли решение решить, что связано счто .

Так как один элемент в блоке TRY вышел из строя, он не перейдет к следующему.

THROW всегда завершает пакет .

После того, как вы позвонили THROW, если у вас есть какой-либо код, который будет продолжаться впоследствии, это не будет выполнено.Если это важно, вы можете использовать RAISERROR для продолжения.

Подробное объяснение ошибок

Часть 2 объяснений

Ответ от того же человека

Уровни серьезности

0 голосов
/ 16 мая 2018

Необходимо пояснение, приведенное здесь для TRY ... CATCH

Конструкция TRY ... CATCH отлавливает все ошибки выполнения с серьезностью выше 10, которые не закрываютсоединение с базой данных.

В SQL TRY..CATCH работает совсем не так, как C # / VB и т. д., поэтому в зависимости от серьезности работает.

Если вам нужно выяснить, произошла ли какая-либо ошибка в предыдущем выражении, используйте @@ ERROR .

Пример, IF @@ERROR <> 0 PRINT 'TEST'

Попробуйте напечатать чторезультат @@ ОШИБКА дает.Он может дать вам любую подсказку.

Возвращает 0, если предыдущий оператор Transact-SQL не обнаружил ошибок.

(ссылка сверху) @@ ERROR Возвращает номер ошибки, если предыдущийВ заявлении обнаружена ошибка.Если ошибка была одной из ошибок в представлении каталога sys.messages, то @@ ERROR содержит значение из столбца sys.messages.message_id для этой ошибки.Вы можете просмотреть текст, связанный с номером ошибки @@ ERROR, в sys.messages.

Проверьте, найдена ли какая-либо полезная информация из @@ ERROR

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...