Как выйти из сценария в SQLPlus при возникновении ошибки и вернуться в приглашение SQLPlus без отключения или выхода из SQLPlus?
у меня есть несколько скриптов, которые запускаются часто, всегда из подключенного сеанса SQLPlus.
мне нужен способ выхода из скрипта при возникновении ошибки,без отключение или выход из самого SQLPlus. В 100% случаев, когда возникает ошибка, подключенному DBA необходимо будет выполнить одну или несколько команд в сеанс. В 100% случаев, когда возникает ошибка, существуют другие операторы SQLPlus (и, следовательно,должны быть за пределами в BEGIN..END;
) далее в скрипт не должен быть выполнены или могут возникнуть серьезные проблемы.
Примечание: Если вы предлагаете WHENEVER SQLERROR EXIT
тогда вы не читали текст выше. Это отключит и выйдет из SQLPlus кроме сценарий, который не является приемлемым поведением.
4 ответов
Я нашел интересную идею здесь и spencer7593ответ, даст мне выборочный вызов подскрипта, к которому я могу передать выходные значения PL/SQL. А именно:
VAR continue number;
EXEC :continue := 1;
BEGIN
SELECT some_bool_test() INTO :continue FROM dual;
END;
SET termout OFF
COLUMN script_name NEW_VALUE v_script_name
SELECT decode(:continue, 1, 'run_stuff.sql', 'skip.sql') script_name FROM dual;
SET termout ON
@&v_script_name :some_other_values
здесь skip.sql
пустой текстовый файл.
обновление: я переместил большую часть этого в RUN.SQL
файл, где я передаю логическое значение (0 или 1) Как &1
, имя сценария для вызова успеха как &2
, а затем любые другие ожидаемые параметры для передачи вызываемому скрипту. Таким образом, он выглядит примерно так:
VAR continue number;
EXEC :continue := 1;
BEGIN
SELECT some_bool_test() INTO :continue FROM dual;
END;
@run.sql :continue 'run_stuff.sql' :some_other_values
это невозможно.
SQLPlus не обеспечивает такого уровня контроля над выполнением скрипта.
очевидно, вам нужно будет избегать использования
вы не можете выйти из скрипта и остаться в SQL * Plus, но вы можете остановить выполнение вещей. Это не очень красиво, но предполагая, что вы можете изменить сценарий, чтобы добавить поток управления, вы можете сделать это с переменной bind.
set serveroutput on
var flag char;
exec :flag := 'Y';
begin
if :flag != 'Y' then
raise program_error;
end if;
dbms_output.put_line('Doing some work');
/* Check for some error condition */
if 0 != 1 then
raise program_error;
end if;
/* Only reach this if earlier statements didn't fail
* but could wrap in another flag check if needed */
dbms_output.put_line('Doing some more work');
exception
when program_error then
dbms_output.put_line(sqlerrm);
:flag := 'N';
when others then
/* Real exception handling, obviously */
dbms_output.put_line(sqlerrm);
:flag := 'N';
end;
/
-- DML only does anything if flag stayed Y
select sysdate from dual
where :flag = 'Y';
-- Optional status message at the end of the script, for DBA info
set feedback off
set head off
select 'Something went wrong' from dual where :flag != 'Y';
set feedback on
set head on
при выполнении:
SQL> @script
PL/SQL procedure successfully completed.
Doing some work
ORA-06501: PL/SQL: program error
PL/SQL procedure successfully completed.
no rows selected
Something went wrong
SQL>
любые блоки PL / SQL в скрипте могут проверить статус флага в начале и поднять program_error
(как раз как сподручное предопределенное исключение) для того чтобы прыгнуть назад вне. Все, что ошибки внутри блока PL/SQL могут обновить флаг переменной bind, либо непосредственно, либо в обработчике исключений. И любой не-PL / SQL DML может иметь дополнительный where
предложение для проверки статуса флага, поэтому, если он установлен в N
к тому времени, когда это утверждение будет достигнуто, никакая работа не будет выполнена. (Для insert
Я думаю, это означало бы не использовать values
форма).
то, что это не может сделать, это иметь дело с любыми ошибками С простые операторы SQL, но я не уверен, что это проблема. Если это так, то они, возможно, должны быть изменен на динамический SQL внутри блока PL/SQL.
Я знаю его старый, но эти две инструкции в самом начале сценария SQL делают работу:
ВСЯКИЙ РАЗ, КОГДА SQLERROR ЗАВЕРШАЕТ ОТКАЗ ОТКАТА
ВСЯКИЙ РАЗ, КОГДА OSERROR ВЫХОД ОТКАЗА ОТКАТА