Остановка исполнения SQL-скрипта на SQL Server: условный выход
Быстрый ответ
Если необходимо прервать выполнение скрипта на SQL Server, можно обратиться к конструкции RAISERROR('Текст ошибки', 11, 1)
и применить к ней оператор RETURN
. Пример выглядит следующим образом:
-- Начинаем выполнение...
SELECT 'Поехали!';
-- Прерываем выполнение
RAISERROR('Выполнение остановлено.', 11, 1);
RETURN;
-- Этот блок не будет выполнен
SELECT 'Этот код уже не выполнится.';
Учтите, что RAISERROR
прервёт выполнение только в пределах текущего блока, поэтому тщательно планируйте структуру вашего скрипта.
Простые и эффективные способы приостановить выполнение
Если ваша задача – контролировать выполнение SQL-скрипта, представлены различные способы установки "стоп-сигнала" в нужный момент.
Использование "set noexec on/off" для "мягкой" остановки
Чтобы "мягко" приостановить выполнение скрипта, используйте set noexec on
. Снять блокировку и продолжить исполнение можно с помощью set noexec off
:
-- Начинаем
PRINT 'Где ты, Ромео?';
-- Останавливаем
SET NOEXEC ON;
-- Этот блок будет пропущен
INSERT INTO LoveStory VALUES('Ромео', 'Джульетта');
-- Возобновляем выполнение
SET NOEXEC OFF;
Элегантный выход с "RETURN"
Оператор RETURN
позволяет изящно прекратить выполнение скрипта, без возникновения ошибок:
IF @@ROWCOUNT = 0
BEGIN
PRINT 'Строк нет. Отменяю действия...';
RETURN;
END
Использование локальных переменных для контроля выполнения
Через IF
и переменные можно управлять ходом выполнения и внедрить нужную логику:
DECLARE @is_valid BIT = 1; -- Запускаем
-- Проверяем условие
IF EXISTS(SELECT * FROM Drama WHERE Twist = 'Недопустим')
SET @is_valid = 0;
-- Если условие не выполняется, завершаем
IF @is_valid = 0
RETURN;
"TRY...CATCH" для управления исключениями
С помощью TRY...CATCH
можно перехватывать и обрабатывать ошибки, контролируя ход выполнения скрипта:
BEGIN TRY
-- Проблемное действие
INSERT INTO Protagonists(ID, Name) VALUES(1, 'Главный герой');
END TRY
BEGIN CATCH
-- Обработка ошибки
THROW;
END CATCH
Использование "IF NOT EXISTS" для предотвращения дублирования данных
Употребляйте IF NOT EXISTS
, чтобы избежать добавления дублирующих данных:
IF NOT EXISTS(SELECT * FROM Protagonists WHERE ID=1)
INSERT INTO Protagonists(ID, Name) VALUES(1, 'Главный герой');
ELSE
RAISERROR('Главный герой уже есть, повторное добавление невозможно.', 16, 1);
Визуализация
Логику работы SQL-скрипта можно ассоциировать с поездкой на поезде:
🚂 Поездка: [| Старт |-->| Всё в порядке 🟢 |-->| Продолжаем |-->| Стоп 🛤️ |]
[| Старт |-->| Произошла ошибка 🔴 |-->| Экстренное торможение: RAISERROR |]
Зелёный сигнал – выполнение без ошибок (BEGIN TRY
), красный – серьёзная ошибка (BEGIN CATCH
+ RAISERROR
).
BEGIN TRY
-- Код без ошибок
END TRY
BEGIN CATCH
-- Ошибка!
RAISERROR('Произошла ошибка.', 16, 1)
END CATCH
Управление потоком и обработка ошибок: на пути к мастерству
Развитие умений в обработке ошибок и управлении потоком данных предполагает применение расширенных методов.
Работа с "SQLCMD mode"
Используйте режим sqlcmd.exe
и директиву :on error exit
для детального контроля над скриптом:
:on error exit
GO
SELECT * FROM TableOfDoom; -- Серьёзная ошибка. Скрипт останавливается.
Контроль сложных процессов с помощью флагов
Для эффективного контроля над скриптами необходимо задействовать структурированные флаги:
DECLARE @ControlFlags TABLE(FlagKey VARCHAR(100), FlagValue INT);
INSERT INTO @ControlFlags VALUES('IsValid', 1);
-- Усложняем сюжет
IF EXISTS(...) UPDATE @ControlFlags SET FlagValue = 0 WHERE FlagKey = 'IsValid';
-- Проверяем состояние перед концовкой
IF (SELECT FlagValue FROM @ControlFlags WHERE FlagKey = 'IsValid') = 0
THROW 50001, 'Герой пал, действие закончено.', 1;
Использование 'RAISERROR' без прав администратора
Если нет административных прав, но нужно контролировать выполнение:
BEGIN TRY
-- Рискованное действие
SELECT 1/0; -- Ошибочная операция
END TRY
BEGIN CATCH
PRINT 'Операция не удалась, прерываем.';
SET NOEXEC ON;
END CATCH
Разбиение скрипта на блоки с помощью 'GO'
Команда GO
помогает разбивать скрипт на независимые блоки:
-- Часть 1
SELECT 'Прекрасная Верона, здесь начинает развиваться наше действие.';
-- Ошибка прервет только следующие блоки
GO
RAISERROR('Проклятие на оба ваши дома!', 16, 1);
GO
-- Часть 2 не будет выполнена
SELECT 'Все виноваты.';
Применение 'THROW' для взаимодействия с пользователями
THROW
помогает формировать индивидуальные сообщения об ошибках:
-- Проверяем условие
IF NOT EXISTS(SELECT * FROM Audience WHERE Bored>'Extremely')
THROW 50002, 'Внимание! Мы потеряли зрителей.', 1;
Использование 'PRINT' для прояснения процесса
С помощью команды PRINT
можно добавить комментарии для более чёткого понимания происходящего:
-- Подготовка зрителей к развязке
PRINT 'Распутываем тайну фантома...';
-- Ответ
PRINT 'Фантом – это дворецкий!';
Рекомендации MSDN
Microsoft Developer Network (MSDN) предоставляет большой объём знаний по SQL, включая детали использования THROW
, который по умолчанию генерирует ошибку уровня 16, и другую ценную информацию.