web-dev-qa-db-ja.com

エラーが発生したときにSQLPlusでスクリプトを終了し、SQLPlusを切断したり終了したりせずに、SQLPlusプロンプトに戻るにはどうすればよいですか?

常に接続されたSQLPlusセッション内から頻繁に実行されるスクリプトがいくつかあります。

エラーが発生したときにスクリプトを終了する方法が必要ですなし SQLPlus自体を切断または終了します。 100%の場合、エラーが発生すると、接続されたDBAはセッションに1つ以上のコマンドを発行する必要があります。 100%の場合、エラーが発生すると、スクリプトの後半に他のSQLPlusステートメントがあります(したがって、must be outside of BEGIN..END;してはいけません実行しないと、深刻な問題が発生する可能性があります。

注:WHENEVER SQLERROR EXITを提案した場合は、上記のテキストを読んでいません。これにより、SQLPlus に加えてスクリプトが切断されて終了しますが、これは許容できない動作です。

9
Thought

興味深いアイデアを見つけました ここ これを 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
_
8
Thought

不可能です。

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コマンドを実行できないことです。

4
spencer7593

スクリプトを終了して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に変更する必要があります。

1
Alex Poole