2012年6月17日日曜日

[Oracle]PL/SQLでエラーハンドリング

PL/SQLのエラーハンドリングの纏め。

エラーハンドリング方法

エラーハンドリングは、EXCEPTIONブロックで行う。
補足する例外は、when句で指定することができて、名前付き例外を指定したりすることができる。
全ての例外を補足することを意味する「others」は、一番最後のwhen句のみに指定できる。
exception
  when no_data_found then      -- no_data_found例外の場合
    dbms_output.put_line('data not faound');
  when others then             -- 上記に該当しない場合
    dbms_output.put_line('other error');

複数のエラーで同一のエラー処理を行う必要がある場合には、下のようにwhen句で「or」でつないで複数の例外を指定すれば良い。
下の場合だと、no_data_foundかzero_divideが発生した場合に、このwhen句のブロック内のステートメントが実行される。
when no_data_found or zero_divide then

名前付き例外の宣言

名前付き例外として定義されていない例外は、PRAGMA EXCEPTION_INITを使用して名前付き例外を定義することができる。
declare
  hoge_error exception;
  pragma exception_init(hoge_error, -1843);
begin
  raise hoge_error;
exception
  when hoge_error then
    dbms_output.put_line('hoge_error');
    dbms_output.put_line(sqlerrm);
  when others then
    dbms_output.put_line('other error');
    dbms_output.put_line(sqlerrm);
end;
実行結果
hoge_errorが、when hoge_errorで補足できていることがわかる。また、ORA-01843とhoge_errorが紐付けられていることもわかる。
hoge_error
ORA-01843: not a valid month

PL/SQL procedure successfully completed.

名前付き例外を使わない場合は、othersで補足して分岐を書かなければならない。下のコードを見るとわかるけど、明らかに可読性が悪い。
when others then
  if sqlcode = -1843 then
    dbms_output.put_line('-1843');
    return;
  end if;

例外に対応するメッセージの取得

sqlerrmを使用すると、例外に対応するメッセージを取得できる。

sqlerrmは、exception句で使用すると発生した例外に対するメッセージを取得できる。また、任意のエラーコードを引数に指定すると、指定したコードに対するメッセージも取得することができる。

以下のプログラムで動きを見てみると。
declare
begin
  dbms_output.put_line(sqlerrm);     -- exceptionブロック意外でsqlerrmを使用
  dbms_output.put_line(sqlerrm(-1)); -- 一意制約のエラーコードを指定
  raise no_data_found;
exception
  when others then
    dbms_output.put_line(sqlerrm);   -- exceptionブロックで使用
end;

実行結果は、下のようになる。
ORA-0000: normal, successful completion     -- 正常を表すメッセージが取得できる。
ORA-00001: unique constraint (.) violated   -- 一意制約違反を表すメッセージ
ORA-01403: no data found                    -- exceptionブロックで補足した例外のメッセージ