質問: 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とすると、 プロシージャのファンクション呼び出し以降の処理は行なわれず、処理は終了しますか? この方法ができるかどうかと、他に方法があれば教えてください。
回答: 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以外なら処理終了します。 #インデントができないのでちょっと見難いソースですが。