常に接続されたSQLPlusセッション内から頻繁に実行されるスクリプトがいくつかあります。
エラーが発生したときにスクリプトを終了する方法が必要ですなし SQLPlus自体を切断または終了します。 100%の場合、エラーが発生すると、接続されたDBAはセッションに1つ以上のコマンドを発行する必要があります。 100%の場合、エラーが発生すると、スクリプトの後半に他のSQLPlusステートメントがあります(したがって、must be outside of BEGIN..END;
) してはいけません実行しないと、深刻な問題が発生する可能性があります。
注:WHENEVER SQLERROR EXIT
を提案した場合は、上記のテキストを読んでいません。これにより、SQLPlus に加えてスクリプトが切断されて終了しますが、これは許容できない動作です。
興味深いアイデアを見つけました ここ これを spencer759 の答えと組み合わせると、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
_は空のテキストファイルです。
UPDATE:これのほとんどを_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は、スクリプトの実行に対してそのレベルの制御を提供しません。
明らかに、WHENEVER SQLERROR EXIT ...
コマンドを使用して回避する必要があります。
PL/SQLを使用して発生した例外(エラー)の結果として実行されるSQL文または実行されないSQL文を条件付きで制御することができます。ただし、SQLPlusコマンド(PL/SQLブロック内から実行することはできません)には対応していません。
DECLARE
lb_continue BOOLEAN;
BEGIN
lb_continue := TRUE;
BEGIN
sql statement
EXCEPTION
WHEN OTHERS THEN
lb_continue = FALSE;
END;
IF lb_continue THEN
BEGIN
sql statements
EXCEPTION
WHEN OTHERS THEN
lb_continue := FALSE;
END;
END;
もちろん、そのアプローチには独自の制限と問題があります。 DDLステートメントは動的に呼び出す必要があります。これを行う最も簡単な方法はEXECUTE IMMEDIATE statement
です。
(あなたの場合の)最大の問題は、PL/SQLブロック内からSQLPlusコマンドを実行できないことです。
スクリプトを終了してSQL * Plusにとどまることができませんが、実行を停止することはできます。きれいではありませんが、スクリプトを変更して制御フローを追加できると仮定すると、バインド変数を使用してこれを行うことができます。
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ブロック内でエラーが発生すると、直接または例外ハンドラでバインド変数フラグを更新できます。また、PL/SQL以外のDMLには、フラグのステータスをチェックするための追加のwhere
句を含めることができるため、ステートメントに到達するまでにN
に設定されている場合、作業は行われません。 (insert
の場合、それはvalues
フォームを使用しないことを意味すると思います)。
これができないのは、エラーを処理することですfromプレーンSQLステートメントですが、それが問題かどうかはわかりません。その場合は、PL/SQLブロック内で動的SQLに変更する必要があります。