9

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

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

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

4

4 に答える 4

9

ここで興味深いアイデアを見つけました。これを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
于 2012-06-27T23:30:02.930 に答える
4

不可能です。

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

于 2012-06-25T22:10:06.443 に答える
1

スクリプトを終了して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フォームを使用しないことを意味すると思います)。

これができないのは、プレーンSQLステートメントからのエラーを処理することですが、それが問題であるかどうかはわかりません。その場合は、PL/SQLブロック内で動的SQLに変更する必要があります。

于 2012-06-26T08:21:23.250 に答える
-1

私はその古いことを知っていますが、SQLスクリプトの最初の2つの命令が機能します。

SQLERROR EXITFAILUREROLLBACKの場合

OSERROR EXITFAILUREROLLBACKの場合は常に

于 2016-08-25T10:19:08.210 に答える