ここまで3種類の例外について見てきました。最後に、例外処理に関する考慮事項を3つ解説します。
例外が発生すると制御は例外処理部に移動し、例外処理が終わるとそのPL/SQLブロックは(実行部に戻ることなく)終了します。
そのため、ある処理の途中で例外が発生した場合、それ以降の処理は実行されません。これを防ぐためには、PL/SQLブロックにネスト(ブロック内にブロックを埋め込むこと)を適用します。
では、PL/SQLブロックにネストがないサンプルプログラムを見て、何が起こるのか確かめてみましょう。
SQL> DECLARE err EXCEPTION; CURSOR dept_cur IS SELECT * FROM dept; BEGIN FOR dept_rec IN dept_cur LOOP IF dept_rec.deptno = 30 THEN RAISE err; ELSE null; END IF; DBMS_OUTPUT.PUT_LINE(dept_rec.deptno); END LOOP; EXCEPTION WHEN err THEN DBMS_OUTPUT.PUT_LINE('値は無効'); END; / 10 20 値は無効 PL/SQLプロシージャが正常に完了しました。
このプログラムはDEPT表のDEPTNO列の値(10、20、30、40を格納済み)をカーソルFORループによって順番に変数へ代入しています。値が30の場合は例外処理に飛び、その他の値の場合はDBMS_OUT.PUT_LINEで変数の値を画面上に表示します。
ループ処理の1回目に変数に代入される値は10、2回目は20のため、DBMS_OUT.PUT_LINEにより変数内の値を表示します。
3回目の値が30のため、IF文内でRAISE文を実行し、例外処理部に移動して例外処理(DBMS_OUT.PUT_LINEにより「値は無効」と表示)を実行します。WHEN句の次行の記述が「END」のため、このままPL/SQLブロックが終了してしまい、値40を処理することはありません。
例外処理によって処理が途中で終了してしまうことを防ぐには、例外処理部を含むPL/SQLブロックにネストを作ります。では、修正版のサンプルプログラムを見てみましょう。
SQL> DECLARE err EXCEPTION; CURSOR dept_cur IS SELECT * FROM dept; BEGIN FOR dept_rec IN dept_cur LOOP BEGIN IF dept_rec.deptno = 30 THEN RAISE err; ELSE null; END IF; DBMS_OUTPUT.PUT_LINE(dept_rec.deptno); EXCEPTION WHEN err THEN DBMS_OUTPUT.PUT_LINE('値は無効'); END; END LOOP; END; / 10 20 値は無効 40 PL/SQLプロシージャが正常に完了しました。
修正点は例外処理部を含むPL/SQLブロックにネストを適用して、そのブロックをLOOP文で囲んだことです。このようにすれば、例外処理部で例外に対処した後、外側にあるPL/SQLブロックの「END LOOP」により「LOOP」に戻り、再度ネストを適用したPL/SQLブロックで処理を継続できます。
例外が発生した箇所によって制御の移動先は異なります。
Copyright © ITmedia, Inc. All Rights Reserved.