プロが教えるわが家の防犯対策術!

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とすると、 プロシージャのファンクション呼び出し以降の処理は行なわれず、処理は終了しますか?
この方法ができるかどうかと、他に方法があれば教えてください。

A 回答 (2件)

返り値は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);

参考URL:http://biz.rivus.jp/functions/sqlcode_sqlerrm.html
    • good
    • 0
この回答へのお礼

なるほど。そういう方法もあるのですね。
ありがとうございました。

お礼日時:2006/11/29 20:21

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以外なら処理終了します。
#インデントができないのでちょっと見難いソースですが。
    • good
    • 0
この回答へのお礼

インデントを付けて見てみました。
ありがとうございます。
>ファンクションだけを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が発生した場合も異常終了で返されるということですね。
ありがとうございました。

お礼日時:2006/11/29 20:12

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

関連するカテゴリからQ&Aを探す