例外処理 (PL/SQL)
デフォルトでは、PL/SQL プログラム内でエラーが発生すると、プログラムの実行が停止します。 EXCEPTION セクションを使用することにより、エラーをトラップし、そこから回復することができます。
例外ハンドラーの構文は、BEGIN ブロックの構文を拡張したものです。
構文
エラーが発生しなかった場合、ブロックでは単に statement が実行され、END 後のステートメントに制御が渡されます。 一方、statement 実行中にエラーが発生した場合、その後の statement の処理は中止され、EXCEPTION セクションに制御が渡されます。 発生したエラーと一致する最初の例外を見つけるために、WHEN 節が検索されます。 一致するものが見つかると、対応する handler-statement が実行され、END 後のステートメントに制御が渡されます。 一致するものが見つからないと、プログラムは実行を停止します。
handler-statement の実行中に新たなエラーが発生した場合は、周囲の EXCEPTION 節によってのみエラーをキャッチできます。
WHEN 節に示す例外は、ユーザー定義と組み込みのどちらにでもすることができます。 ユーザー定義の例外は、現在のブロックまたは現在のブロックを囲むブロックのどちらかにある DECLARE セクション、あるいは PL/SQL パッケージの DECLARE セクションで定義できます。 例外定義の直後に PRAGMA EXCEPTION_INIT または PRAGMA DB2_EXCEPTION_INIT 構文を使用して、ユーザー定義例外に対応する sqlcode または sqlstate を指定できます。
MyApp.Mainの呼び出しです。 EXCEPTION セクションには次の 3 つの例外のハンドラーがあります。exception1は sqlcode および sqlstate のどちらとも関連付けられていません。exception2は、sqlcode -942 (名前が未定義) と関連付けられています。exception3は、sqlstate 42601 (構文エラー) と関連付けられています。
DECLARE
exception1 EXCEPTION;
exception2 EXCEPTION;
PRAGMA EXCEPTION_INIT(exception2,-942);
exception3 EXCEPTION;
PRAGMA DB2_EXCEPTION_INIT(exception3,'42601');
BEGIN
MyApp.Main(100);
EXCEPTION
WHEN exception1 THEN
DBMS_OUTPUT.PUT_LINE('User-defined exception1 caught');
WHEN exception2 THEN
DBMS_OUTPUT.PUT_LINE('User-defined exception2 (Undefined name) caught');
WHEN exception3 THEN
DBMS_OUTPUT.PUT_LINE('User-defined exception3 (Syntax error) caught');
ENDPRAGMA EXCEPTION_INIT で初期化された例外がキャッチされた場合、SQLCODE 関数から返される値はその例外に関連付けられた sqlcode であり、Oracle の値ではありません。 前述の例で、exception2 がキャッチされた場合、SQLCODE から返される値は -204 になります。これは、Oracle sqlcode -942 に対応する sqlcode です。 PRAGMA EXCEPTION_INIT で指定された Oracle sqlcode が Oracle-Db2 エラー・マッピング表にリストされていない場合、コンパイルは失敗します。 これは、PRAGMA EXCEPTION_INIT を PRAGMA Db2_EXCEPTION_INIT に置き換えて、判別対象のエラーに対応する Db2 sqlstate を指定することによって回避できます。
| 例外名 | 説明 |
|---|---|
| CASE_NOT_FOUND | CASE ステートメント内のいずれのケースも「TRUE」と評価されず、かつ ELSE 条件がありません。 |
| CURSOR_ALREADY_OPEN | 既にオープン済みのカーソルをオープンしようとしました。 |
| DUP_VAL_ON_INDEX | 索引キーに重複した値があります。 |
| INVALID_CURSOR | オープンしていないカーソルにアクセスしようとしました。 |
| INVALID_NUMBER | 数値が無効です。 |
| LOGIN_DENIED | ユーザー名またはパスワードが無効です。 |
| NO_DATA_FOUND | 選択基準を満たす行がありませんでした。 |
| NOT_LOGGED_ON | データベース接続が存在しません。 |
| OTHERS | 例外セクション内の先行する条件によってキャッチされなかった例外のすべてが対象です。 |
| SUBSCRIPT_BEYOND_COUNT | 添字が、範囲外であるか、または存在しません。 |
| SUBSCRIPT_OUTSIDE_LIMIT | 配列索引式のデータ・タイプを配列索引タイプに割り当てることはできません。 |
| TOO_MANY_ROWS | 複数の行が選択基準を満たしましたが、返すことが許可されているのは 1 行のみです。 |
| VALUE_ERROR | 値が無効です。 |
| ZERO_DIVIDE | ゼロによる除算が試みられました。 |
