- 締切済み
PL/SQLの例外
PL/SQLの例外処理で、 プロシージャからファンクションをコールしてデータを取得しています。 ファンクションでデータを取得できたのか、NO_DATA_FOUNDだったのか、WHEN OTHERS THENブロックに入ったのか、呼び出し元に通知したいのです。 ・データが取得できた場合、RETURN TRUE ・NO_DATA_FOUND、またはWHEN OTHERS THENブロックに入ってきた場合にRETURN FALSE とすると、呼び出し元のプロシージャで区別が付かないのです。 ファンクションでWHEN OTHERS THENブロックに入った場合、プロシージャのWHEN OTHERS THENブロックに飛ばしたいと思います。 この場合の方法ですが、ファンクションのWHEN OTHERS THENでRAISE 独自例外Aとし、プロシージャのEXCEPTIONでWHEN 独自例外A THENとすると、 プロシージャのファンクション呼び出し以降の処理は行なわれず、処理は終了しますか? この方法ができるかどうかと、他に方法があれば教えてください。
- みんなの回答 (2)
- 専門家の回答
みんなの回答
- ossan_hiro
- ベストアンサー率66% (88/132)
BEGIN~EXCEPTION~END;のブロックをどのように構成するかで、例外後の処理をどうするかを決定することができます。 たとえば、こんな関数(function)があったとします。 create or replace function ex_throw(val number ) return number is ret_val number(1):=-1; -- -1で初期化 begin if val=1 then select 0 into ret_val from dual where 1=2; -- NO_DATA_FOUND else ret_val:=10/val; -- 引数に0を設定するとZERO_DIVIDEが発生 end if; return ret_val; exception -- 別にここでexceptionで捕捉しないで親ブロックで捕捉しても -- いいが、なにが起こったかわかるようにあえて捕捉する when NO_DATA_FOUND then dbms_output.put_line('ex_throw:データなし'); raise; -- NO_DATA_FOUNDをそのまま返す when OTHERS then dbms_output.put_line('ex_throw:予想外だ'); raise; -- 起きた例外をそのまま返す end; / このファンクションで ・NO_DATA_FOUND は処理継続 ・NO_DATA_FOUND以外なら処理終了 としたい場合 declare ret number:=-1; begin begin ret := ex_throw(0); -- 引数が1ならNO_DATA_FOUND、0ならZERO_DIVIDE exception when NO_DATA_FOUND then dbms_output.put_line('関数呼出元:レコードなし'); end; dbms_output.put_line('実行結果='||ret); dbms_output.put_line('それ以降の処理実行'); exception when others then dbms_output.put_line('エラー検出'); dbms_output.put_line(SQLERRM); end; / のようにファンクションだけを BEGIN~EXCEPTION~END;のブロックで囲んで 捕捉したい例外(NO_DATA_FOUND)だけをEXCEPTIONで書けば NO_DATA_FOUNDがこの関数内で起きてもそれ以降の処理は 継続され、NO_DATA_FOUND以外なら処理終了します。 #インデントができないのでちょっと見難いソースですが。
- lovesens
- ベストアンサー率30% (48/158)
返り値はBoolean型で返した方がよいですか? Integer型で返して、0:成功、それ以外:Oracleのエラーコードで返すとかいうのはだめですか? sqlcodeでエラーコード、sqlerrm(sqlcode))でエラーメッセージが取れます。例外部分に書いておけば返ってきますよ。 例:デバッグメッセージを出しています exception when OTHERS then dbms_output.put_line('-- デバッグメッセージ --'); dbms_output.put_line('SQL コード = ' || sqlcode); dbms_output.put_line('エラー内容 = ' || sqlerrm(sqlcode)); 参考: ゼロの割り算 ORA-01476の冷害が発生すると、SQLCODEとしてはORA-1476の値がマイナスで返る。ORA-01476なら、-1476。 但し、ORA-01403は、SQLCODEとして+100が返るので注意する。 SQLERRMでは、SQLCODEに対応するエラーメッセージを取得できる。 errmsg := sqlerrm(-6511);
お礼
なるほど。そういう方法もあるのですね。 ありがとうございました。
お礼
インデントを付けて見てみました。 ありがとうございます。 >ファンクションだけをBEGIN~EXCEPTION~END;のブロックで囲んで >捕捉したい例外(NO_DATA_FOUND)だけをEXCEPTIONで書けば >NO_DATA_FOUNDがこの関数内で起きてもそれ以降の処理は >継続され、NO_DATA_FOUND以外なら処理終了します。 プログラム⇒プロシージャ⇒ファンクションという流れになっているのですが、ファンクションでNO_DATA_FOUND以外の例外が発生した場合、プロシージャのEXCEPTION WHEN OTHERS THENブロックにくるということですね。 プロシージャからプログラムへ結果を返さないといけないのですが、プロシージャのEXCEPTION WHEN OTHERS THENで戻り値に異常終了を代入しておけば、ファンクションでWHEN OTHERS THENが発生した場合も異常終了で返されるということですね。 ありがとうございました。