【PL/SQL】EXCEPTIONの処理(例外処理)


ここではORACLE社が提供するPL/SQL言語のEXCEPTIONの処理(例外処理)を紹介しています。

EXCEPTIONの処理(例外処理)

EXCEPTION(例外)とは

PL/SQLのプログラムを実行した時に発生するエラーをEXCEPTION(例外)と呼びます。

プログラムでは、コーディングしたとき、コンパイルエラーにならないもので実行時にエラーとなるものがあります。

例えば次のように1桁の文字列型の変数を宣言として、2桁の文字列を格納しようとするとエラーが発生します。このようなエラーをEXCEPTION(例外)と呼びます。

SQL> CREATE OR REPLACE PROCEDURE pro1 IS
  2        a VARCHAR2(1);
  3  BEGIN
  4        a := 'ab';
  5        DBMS_OUTPUT.PUT_LINE(a);
  6  END;
  7  /

プロシージャが作成されました。

SQL> exec pro1
BEGIN pro1; END;

*
行1でエラーが発生しました。:
ORA-06502: PL/SQL: 数値または値のエラー:
文字列バッファが小さすぎます。が発生しました
ORA-06512: "USER1.PRO1", 行4
ORA-06512: 行1

例外の種類

例外は事前定義例外とユーザ定義例外の大きく2つの種類に分けられます。

事前定義例外とは、ORACLEデータベースによって事前に定義されている例外です。宣言した変数にサイズ以上の値をセットしようとするとORA-06512のVALUE_ERRORが発生します。

ユーザ定義例外とは、ユーザが独自に定義することのできる例外です。システムの仕様や要件に応じて独自に作成することが出来ます。

EXCEPTION WHEN:例外処理

例外処理とは、PL/SQLでエラーが発生した時に実行する処理です。

例外処理は、次のようにEXCEPTION WHEN~で書くことが出来ます。

PL/SQLのプログラムでエラーが発生すると、EXCEPTION文以降のが処理が実行されます。

WHENで記述した条件と発生したEXCEPTIONの種類や値が一致する場合、処理が実行されます。

DECLARE
    -- 宣言部
BEGIN
    -- 処理部
EXCEPTION
  -- 例外処理部
  WHEN 条件 THEN
     処理;
END;
/

OTHERS:全ての例外をキャッチする

例外処理部の条件でOTHERSを使うことで、全ての例外をキャッチすることが出来ます。

予期せぬエラーが発生した場合の処理を書く時に使います。

次の例ではOTHERSを使って全ての例外をキャッチして処理を実行しています。

BEGIN
    RAISE VALUE_ERROR;
EXCEPTION
    WHEN OTHERS THEN
        DBMS_OUTPUT.PUT_LINE('ERROR');
END;
ERROR
PL/SQLが実行されました(197 msec.)

RAISE:例外をスローする

RAISE文を使うことで、EXCEPTION(例外)をスローし、任意のタイミングでエラーを発生させることが出来ます。

RAISE文では事前定義例外、ユーザ定義例外をスローすることが出来ます。

次の例では、VALUE_ERROR例外をスローし、強制的にエラーを発生させています。

BEGIN
      RAISE VALUE_ERROR;
EXCEPTION
      WHEN OTHERS THEN
             DBMS_OUTPUT.PUT_LINE('***');
END;
***
PL/SQLが実行されました(6 msec.)

ユーザー定義例外

ユーザー定義例外とは、ユーザーが独自に定義した例外のことです。

例えば変数aの値がNULLの場合は、「USER_ERROR1」という例外を発生させえることが出来ます。

ユーザー定義例外の書き方は次の通りです。

DECLARE
    --ユーザ定義例外の宣言
    名前 EXCEPTION
BEGIN
    --ユーザ定義例外のスロー
    RAISE 名前
EXCEPTION
  --ユーザ定義例外が発生した場合の処理
  WHEN 名前 THEN
     処理;
END;
/

次の例では、変数aの値がNULLの場合ユーザ定義例外の「USER_ERROR1」を発生させています。

宣言部で「USER_ERROR1 EXCEPTION;」として定義し、処理部で「RAISE USER_ERROR1;」としてスローしています。

例外処理部では「WHEN USER_ERROR1 THEN」で例外をキャッチし処理(ここではメッセージ出力)しています。

SQL> CREATE OR REPLACE PROCEDURE pro2 IS
  2      a VARCHAR2(5);
  3      USER_ERROR1 EXCEPTION;
  4  BEGIN
  5      IF a IS NULL THEN
  6          RAISE USER_ERROR1;
  7      END IF;
  8  EXCEPTION
  9      WHEN USER_ERROR1 THEN
 10          DBMS_OUTPUT.PUT_LINE('USER_ERROR1');
 11  END;
 12  /

プロシージャが作成されました。

SQL> EXEC pro2;
USER_ERROR1

PL/SQLプロシージャが正常に完了しました。

事前定義例外の一覧

EXCEPTION(例外)ORAエラー 
ACCESS_INTO_NULL06530 
CASE_NOT_FOUND06592 
COLLECTION_IS_NULL06531 
CURSOR_ALREADY_OPEN06511 
DUP_VAL_ON_INDEX00001 
INVALID_CURSOR01001 
INVALID_NUMBER01722 
LOGIN_DENIED01017 
NO_DATA_FOUND01403 
NOT_LOGGED_ON01012 
PROGRAM_ERROR06501 
ROWTYPE_MISMATCH06504 
SELF_IS_NULL30625 
STORAGE_ERROR06500 
SUBSCRIPT_BEYOND_COUNT06533 
SUBSCRIPT_OUTSIDE_LIMIT06532 
SYS_INVALID_ROWID01410 
TIMEOUT_ON_RESOURCE00051 
TOO_MANY_ROWS01422 
VALUE_ERROR06502 
ZERO_DIVIDE01476 

・ACCESS_INTO_NULL
 初期化していないオブジェクトに値を代入しようとしたとき

・CURSOR_ALREADY_OPEN
 オープンされているカーソルをオープンしようとしたとき

・DUP_VAL_ON_INDEX
 一意制約に違反したとき(UNIQUE索引の列に重複値の登録を試みたとき)

・INVALID_CURSOR
 オープンしていないカーソルの操作などをしようとしたとき

・INVALID_NUMBER
 文字列や日付などを数値変換が出来なかったとき

・LOGIN_DENIED
 ログインに失敗したとき

・NO_DATA_FOUND
 SELECT INTO文で結果を返さなかったとき

・NOT_LOGGED_ON
 Oracleデータベースへ接続していないプログラムが、データベースへアクセスしたとき
 または接続が途中で途切れてしまったとき

・STORAGE_ERROR
 メモリーエラーが発生したとき(不足や破壊など)

・SUBSCRIPT_BEYOND_COUNT
 コレクション型で要素数より大きな要素にアクセスしたとき

・SUBSCRIPT_OUTSIDE_LIMIT
 コレクション型で有効範囲外の要素にアクセスしたとき(マイナスの値など)

・TIMEOUT_ON_RESOURCE
 ORACLEがリソースを求め待機しているときにタイムアウトが発生したとき

・TOO_MANY_ROWS
 SELECT INTO文で複数の行を返したとき

・VALUE_ERROR
 値のサイズエラーや型変換エラー、制約エラーが発生したとき

・ZERO_DIVIDE
 0除算(ゼロ除算)を行ったとき