2017-12-07 8 views
4

私は、FlywayスクリプトとOracleのいくつかのOracle PL/SQLブロックで大文字小文字の例外ハンドラを使用しようとしています。例外ハンドラのスコープは、すべての例外を最初のブロックの例外ハンドラに送信します。例えば、このコードで:Oracleは後のブロックの最初のブロックから例外ハンドラを使用します

begin 

    begin 
    execute immediate ' 
create table "test" (
    "id" number not null, 
    "name" varchar2(100) not null, 
    constraint "test_pk" primary key ("id") 
) 
'; 
    exception 
    when others then 
    if sqlcode != -955 then raise; end if; 
    end; 

    begin 
    execute immediate 'fail to create index "test_name_idx" on "test" ("name")'; 
    exception 
    when others then 
    if sqlcode != -6512 then raise; end if; 
    end; 

end; 

ORA-06512例外が捕捉されず、発生する例外は役に立たない複数のブロック中のブロックをラッピングライン13

からとしてタグ付けされています。

ここでは何が起こっていますか?これをどうやって止めるのですか?

+0

これは非常に興味深いです。簡単な 'dbms_output'呼び出しを、最初のraise(ifの内側)の前に追加すると、livesql.oracle.comのクイックテストから正しい行番号が報告されます。しかし、さらに多くのデバッグでは、間違った行番号を報告しても、実際にはその最初の例外ハンドラには当てられません。 'dbms_sql'に(解析する)バグのように見えますか?それが同じ無関心なバージョンを動作するかどうかを確認することは興味深いかもしれません。 –

+2

10gからバグ8856896のように見えますが、少なくともそのサイトでは12cR2です。オラクル社のサポートでサービスリクエストを提出する時間はありますか? –

+1

FWIW、Oracle 12.1.0.2.0の問題を再現しました。あなたが興味を持っていると思う実際の例外は、ORA-00955(「名前は既に使用されています」という意味で、ORA-06512(「エラーはオンラインになっています」)をキャッチしようとしているのはなぜですか?既存のオブジェクト」)およびORA-01408(「そのような列リストはすでに索引付けされています」)。 –

答えて

3

これは11.2.0.4、12.1.0.2、および12.2.0.1で(これまで)再現されているバグです。最初のサブブロックでDDLや実際のアクションは必要ないようです(ただし、プレースホルダーとしてnull;を実行してもトリガーされない可能性がありますが、これはコンパイラーが削除する可能性があります)。ifが必要です両方の例外ハンドラ:

begin 
    begin 
    dbms_output.put_line('Dummy message'); 
    exception 
    when others then 
     dbms_output.put_line('In first exception handler'); 
     if 1=1 then 
     raise; 
     end if; 
    end; 

    begin 
    execute immediate 'invalid'; 
    exception 
    when others then 
     dbms_output.put_line('In second exception handler'); 
     if 1=1 then 
     raise; 
     end if; 
    end; 
end; 
/

Dummy message 
In second exception handler 

ORA-00900: invalid SQL statement 
ORA-06512: at line 8 
ORA-06512: at line 13 

例のように、例外は13行目でスローされますので、18行目で(再)呼び出される必要があります。代わりに、それは8行目から提起されたと報告されていますが、これは意味をなさないものです。 (at line 13メッセージは12.2にのみ表示され、11.2と12.1では最初のORA-06512が報告されていますが、これはかなり混乱します.1230 2 3あなたが見ることができるデバッグは、実際には最初の例外ハンドラを使用せず、2番目の例外ハンドラに入ります。それは間違ったコードを実行するのではなく、間違った行番号に対して報告するように思えます。

それはすぐにraise前に何とか物事修正、if内の実際の作業を行っていることが表示されます - いずれか例外処理セクションでは、第二に

begin 
    begin 
    dbms_output.put_line('Dummy message'); 
    exception 
    when others then 
     dbms_output.put_line('In first exception handler'); 
     if 1=1 then 
     dbms_output.put_line('This avoids the bug somehow'); 
     raise; 
     end if; 
    end; 

    begin 
    execute immediate 'invalid'; 
    exception 
    when others then 
     dbms_output.put_line('In second exception handler'); 
     if 1=1 then 
     raise; 
     end if; 
    end; 
end; 
/

Dummy message 
In second exception handler 

ORA-00900: invalid SQL statement 
ORA-06512: at line 19 
ORA-06512: at line 14 

及びこれを:報告された行番号が正しいの両方の場合において

begin 
    begin 
    dbms_output.put_line('Dummy message'); 
    exception 
    when others then 
     dbms_output.put_line('In first exception handler'); 
     if 1=1 then 
     raise; 
     end if; 
    end; 

    begin 
    execute immediate 'invalid'; 
    exception 
    when others then 
     dbms_output.put_line('In second exception handler'); 
     if 1=1 then 
     dbms_output.put_line('This avoids the bug somehow'); 
     raise; 
     end if; 
    end; 
end; 
/

Dummy message 
In second exception handler 

ORA-00900: invalid SQL statement 
ORA-06512: at line 19 
ORA-06512: at line 13 

これは到達できない最初のメッセージを追加します。どういうわけか。

dbms_outputコールである必要はありません。余分なサブブロック(例:begin execute immediate 'select * from dual'; end;)でも、ダミーのプロシージャコールやクエリなどは機能しているようです。 into ...)。再びnull;を使うだけではうまくいきません。

これは少し醜いですが、少なくとも、一種のことからそれをやめる方法を提供します。

これは明らかに奇妙で予期しない動作の不一致であり、しばらくお待ちしておりますので、おそらくMy Oracle Supportを通じてサービスリクエストとして提出してください。私は既存のレポートを見ることができませんが、私は非常に難しく見えなかったので、どこかに潜んでいるかもしれません。

関連する問題