Как выйти из сценария в 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 ВЫХОД ОТКАЗА ОТКАТА