例外処理 (PL/SQL)

デフォルトでは、PL/SQL プログラム内でエラーが発生すると、プログラムの実行が停止します。 EXCEPTION セクションを使用することにより、エラーをトラップし、そこから回復することができます。

例外ハンドラーの構文は、BEGIN ブロックの構文を拡張したものです。

構文

構文図を読む構文図をスキップするDECLAREdeclarationBEGINstatement EXCEPTIONWHENexception-conditionORconditionTHENhandler-statementEND

エラーが発生しなかった場合、ブロックでは単に 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 を指定できます。

次の例では、DECLARE セクションに 3 つの名前付き例外の定義があります。 ブロック本体はプロシージャー MyApp.Main の呼び出しです。 EXCEPTION セクションには次の 3 つの例外のハンドラーがあります。
  1. exception1 は sqlcode および sqlstate のどちらとも関連付けられていません。
  2. exception2 は sqlcode -942 (名前が未定義) と関連付けられています。
  3. 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');
END
注: データ・サーバーが PRAGMA EXCEPTION_INIT の引数として受け入れることのできる Oracle sqlcode は限られています。 完全なリストは Oracle-IBM Db2 on Cloud、IBM Db2 Warehouse on Cloud、および IBM Db2 Warehouse エラー・マッピング (PL/SQL) を参照してください。

PRAGMA EXCEPTION_INIT で初期化された例外がキャッチされた場合、SQLCODE 関数から返される値はその例外に関連付けられた sqlcode であり、Oracle の値ではありません。前述の例で、exception2 がキャッチされた場合、SQLCODE から返される値は -204 になります。これは Oracle sqlcode -942 に対応する sqlcode です。PRAGMA EXCEPTION_INIT で指定された Oracle sqlcode が Oracle- エラー・マッピング表にリストされていない場合はコンパイルが失敗します。これは、PRAGMA EXCEPTION_INIT を PRAGMA DB2_EXCEPTION_INIT に置き換えて、判別対象のエラーに対応する sqlstate を指定することによって回避できます。

表 1 は、使用可能な、組み込み例外を要約したものです。 特別の例外名 OTHERS は、すべての例外と一致します。 条件名には、大文字と小文字の区別がありません。
表 1. 組み込み例外名
例外名 説明
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 ゼロによる除算が試行されました。