«Решаем проблему: Sql Server не останавливается после raiserror»

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Чтобы прервать транзакцию после RAISERROR, используйте SET XACT_ABORT ON;. Однако, помните, что RAISERROR останавливает выполнение только при условии, что уровень серьёзности ошибки превышает 18. Установите более высокий уровень серьёзности или воспользуйтесь RETURN непосредственно после RAISERROR, чтобы транзакция была немедленно прервана.

SQL
Скопировать код
SET XACT_ABORT ON;
  
BEGIN TRY
    -- Здесь наши SQL-команды

    RAISERROR('Серьёзная ошибка, но не просто "пролитый кофе"', 20, 1); -- Уровень серьёзности 20, всё очень серьёзно!
    RETURN;  -- Прерываем выполнение, если уровень серьёзности < 19
END TRY
BEGIN CATCH
    -- Принципы перехвата и обработки ошибок
END CATCH

Основное правило: Сочетайте XACT_ABORT ON с RAISERROR высокого уровня серьёзности или оператором RETURN для надёжной остановки при возникновении ошибок. Конструкция TRY...CATCH идеально подходит для глубокой обработки ошибок.

Кинга Идем в IT: пошаговый план для смены профессии

Что происходит?

Опция XACT_ABORT ON предназначена для немедленной остановки транзакций при появлении ошибок в процессе выполнения. Что касается RAISERROR, он не останавливает транзакцию, если уровень серьёзности ошибки не достигает 18.

Если произошла ошибка RAISERROR, SQL Server, ни капли не торопясь, продолжит работу, если мы не остановим его самостоятельно. Как это предотвратить? Мы можем прекратить выполнение при помощи RETURN или установить уровень серьёзности выше 20.

Необходимость использования "RETURN"

Использование RAISERROR с уровнем серьёзности ниже 20 действует как сигнал тревоги, который игнорируют; выполнение продолжается. Чтобы прервать процесс, добавьте RETURN после RAISERROR. Это гарантирует прерывание так же, как и XACT_ABORT:

SQL
Скопировать код
RAISERROR('Ошибку эту исправить недолго: нужно остановить выполнение.', 16, 1); 
RETURN;  -- Эффективный способ прервать выполнение SQL-кода

Лучшая практика: Всегда сочетайте RAISERROR с оператором RETURN для ясной демонстрации ваших намерений.

Мощь XACT_ABORT и уровни серьёзности ошибок

Даже включив XACT_ABORT ON, ошибки с уровнем серьёзности ниже 20 не прерват выполнение следующих команд в SQL Server. Для того чтобы прервать работу принудительно, используйте уровень ошибки 20 и выше. Это неотвратимо приведёт к остановке выполнения, независимо от XACT_ABORT.

SQL
Скопировать код
RAISERROR('Уровень серьёзности 20 активирован; SQL Server будет остановлен!', 20, 1);
-- За этой строкой больше ничего не будет выполнено, даже скорость Усэйна Болта не спасёт

Оповещение об ошибках до применения RAISERROR

Предупреждение о проблеме гораздо лучше, чем ее исправление. Поэтому отслеживайте ошибки до того, как произойдёт вызов RAISERROR. Анализируйте условия и прогнозируйте их:

SQL
Скопировать код
IF @ErrorDiscovered = 1
BEGIN
    RAISERROR('Ошибку заметили заранее!', 16, 1);
    RETURN;
END

Совет: Предупреждение проблем влияет на целостность вашего транзакционного процесса.

Визуализация

Представьте SQL Server как поезд (🚂), движущийся по рельсам, а XACT_ABORT – как механизм экстренного торможения (🛑).

Markdown
Скопировать код
`RAISERROR` = 🚦 Красный свет | `XACT_ABORT` ON = 🛑 Активировано экстренное торможение
SQL
Скопировать код
BEGIN TRAN
RAISERROR('Ошибка произошла', 16, 1) -- 🚦 красный сигнал, но 🚂 может продолжить движение
-- Остальной SQL код -- 🛤️ идеальное место для 🛑
COMMIT TRAN
Markdown
Скопировать код
Как это происходит?
🚂💭: "Хм, красный свет. Но ведь можно попробовать проехать?"

Что мы ожидали: 🚂🛑 Поезд останавливается на красном сигнале. Что произошло на самом деле: 🚂⚠️ Поезд проехал мимо, не осознав, что нужно было остановиться.

Таким образом, XACT_ABORT = 🛑 не означает мгновенную остановку, это указание подождать подходящую возможность для остановки. 🚂🛤️💤

Особенности и предостережения

Когда RAISERROR вызывает панику и выполнение требуется прервать, вот что важно учесть:

  • Уровень серьёзности: ошибки с низким уровнем серьёзности не прерывают выполнение. Серьёзность вязна для автоматической остановки.
  • Используйте RETURN для контроля: RETURN, расположенный сразу после RAISERROR, гарантирует прекращение выполнения. Игра окончена!
  • TRY...CATCH – ваш надёжный помощник: конструкция TRY…CATCH обеспечивает контроль над обработкой ошибок, позволяя выполнить последние операции или занести ошибки в журнал перед окончанием.

Примеры из практики

Рассмотрим практическое применение:

  • Проверка условий: убедитесь, что условия правильны до вызова RAISERROR.
  • Тестирование различных уровней серьёзности: экспериментируйте с разными уровнями и наблюдайте, как они влияют на выполнение вашего кода.
  • Логирование и откат: используйте TRY...CATCH для логирования ошибок и осуществления отката при его необходимости.

Памятка: Будьте в курсе возможностей ваших инструментов и используйте их умело для создания надёжных и производительных приложений.

Полезные материалы

  1. SET XACT_ABORT (Transact-SQL) – SQL Server | Microsoft Learnофициальная документация поможет разобраться в настройках XACT_ABORT.
  2. Handling Errors in SQL Server 2012 – Simple Talk — руководство по управлению транзакциями и обработке ошибок в SQL Server.
  3. Error and Transaction Handling in SQL Server Part Two — изучение влияния XACT_ABORT на обработку ошибок при использовании хранимых процедур.
  4. SQL Server – transactions roll back on error? – Stack Overflow — обсуждение поведения транзакций при откате из-за ошибок и влияния на это XACT_ABORT.