PL / SQL: есть ли инструкция полностью остановить выполнение скрипта?
Я пытаюсь выполнить некоторые проверки схемы БД в начале скрипта PL/SQL.
Если проверки дают неудачные результаты, я хочу остановить скрипт, чтобы предотвратить выполнение следующих инструкций.
у меня что-то вроде этого
-- 1st line of PL/SQL script
DECLARE
SOME_COUNT INTEGER;
BEGIN
SELECT COUNT(*) INTO SOME_COUNT FROM SOME_TABLE WHERE <SOME_CONDITIONS>;
IF (SOME_COUNT > 0) THEN
DBMS_OUTPUT.PUT_LINE('Test failed, I don''want the rest of the script'
|| ' to be executed.');
--EXIT or something like that?... <= STOP EXECUTION HERE
END IF;
END;
/
-- OTHER SQL INSTRUCTIONS...
ALTER TABLE SOME_TABLE ...
Я ищу инструкцию(ы), позволяющую делать "STOP EXECUTION HERE
".
4 ответов
основываясь на вопросе, я не согласен с принятым ответом. В вопросе показан пакетный сценарий с несколькими операторами. RAISE_APPLICATION_ERROR () выходит только из блока PL/SQL (подпрограмма), а не из общего скрипта (как указал Джастин), поэтому он будет продолжаться с инструкциями, которые следуют.
для пакетных сценариев лучше всего использовать при выходе SQLERROR. Да, это директива SQL * Plus, а не стандартный SQL, но довольно портативный; большинство популярных инструментов Oracle, которые поддерживают скрипты поддерживают эту директиву, по крайней мере, частично. Следующий пример работает в SQL*Plus, SQL*Developer, Toad, SQLsmith и, возможно, других и демонстрирует проблему, если вы прокомментируете строку.
set serveroutput on
-- Without this line, things keep going
WHENEVER SQLERROR EXIT SQL.SQLCODE ROLLBACK;
BEGIN
IF (1 > 0) THEN
DBMS_OUTPUT.PUT_LINE('First thing');
RAISE_APPLICATION_ERROR(-20000, 'Test failed'); -- not enough
END IF;
END;
/
-- This will execute if you remove WHEN SQLERROR.., so RAISE_APPLICATION_ERROR is not enough
BEGIN
DBMS_OUTPUT.PUT_LINE('Second thing - Executes anyway');
END;
/
Если вы удалите WHEN SQLERROR, скрипт продолжит и выполнит 2-й блок и т. д. именно этого вопроса и следует избегать.
преимущество в этом случае графических инструментов, эмулирующих sqlplus, заключается в том, что они действительно останавливают скрипт и не отправляйте оставшуюся часть скрипта в командную оболочку как команды оболочки, что происходит, если вы вставляете скрипты в SQL*Plus, запущенные в окне консоли. SQL * Plus может выйти при ошибке, но остальные буферизованные команды будут обрабатываться оболочкой ОС, что немного грязно и потенциально рискованно, если у вас были команды оболочки в комментариях (что не является неслыханным). С SQLPlus всегда лучше подключиться, а затем выполнить сценарий или передать его в командной строке
Если вы не хотите создавать исключение, вы можете попробовать что-то вроде (непроверенное):
declare
SOME_COUNT INTEGER;
begin
SELECT COUNT(*) INTO SOME_COUNT FROM SOME_TABLE WHERE <SOME_CONDITIONS>;
IF (SOME_COUNT > 0) THEN
DBMS_OUTPUT.PUT_LINE('Test failed, I don''want the rest of the script'
|| ' to be executed.');
goto end_proc;
END IF;
-- A bunch of great code here
<<end_proc>>
null; -- this could be a commit or other lines of code
end;
некоторые люди ненавидят любые заявления GOTO, поскольку они могут привести к спагетти-коду, если злоупотреблять, но в простых ситуациях, подобных этой (опять же, если вы не хотите создавать исключение), они хорошо работают.
еще несколько секунд googling дали мне ответ: функция RAISE_APPLICATION_ERROR()
IF (SOME_COUNT > 0) THEN
RAISE_APPLICATION_ERROR(-20000, 'Test failed');
END IF;
пользовательский код ошибки должен находиться между -20000 и -20999.
подробности о Oracle doc здесь:http://docs.oracle.com/cd/B10501_01/appdev.920/a96624/07_errs.htm#877 (раздел определение собственных сообщений об ошибках: процедура RAISE_APPLICATION_ERROR)
вместо того, чтобы бросать ошибку приложения, гораздо проще просто использовать RETURN
ключевое слово который выходит из текущего блока PL/SQL очень плавно.
просто убедитесь, что вы делаете DBMS_OUTPUT.PUT_LINE('Exited because <error')
перед ним, чтобы предоставить пользователю хорошее сообщение о том, почему вы выходите, конечно!