連載
» 2019年09月18日 05時00分 公開

超入門「PL/SQL」(9):PL/SQLの例外処理(後編) (1/2)

本連載は、「PL/SQL(Procedure Language/Structured Query Language)」を理解し、活用するための実践講座です。前回に引き続き「例外処理」について解説します。

[小笠原宏幸,@IT]

この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。

連載バックナンバー

 本連載は、Oracle Database向けにデータベース言語「SQL(Structured Query Language)」を拡張したプログラミング言語である「PL/SQL(Procedure Language/Structured Query Language)」を理解し、活用するための実践講座です。SQLは知っているけれど、OracleでのPL/SQLは初めてという人向けに、機能の概要と具体的な書き方を解説します。

 PL/SQLで発生したエラーを「例外」と呼びます。前回に続いて、今回も例外が起きたときの対応方法を記述する「例外処理部」について紹介します。例外には「内部例外」「ユーザー定義例外」「定義外例外」の3種類があり、前回は内部例外について解説しました(内部例外の解説はこちら)。今回は、残り2つの例外の他、例外処理について考慮しなければならないことを解説していきます。

ユーザー定義例外

 ユーザーが独自に定義した例外をユーザー定義例外と呼びます。例えば、「社員番号7369の社員の給与がNULLの場合は例外とし、トランザクションをロールバックする」といった処理が可能です。まずは書式を確認しましょう。

(1) 例外名を定義(宣言部)
<例外名> EXCEPTION ;
(2) ユーザー定義例外の発生(実行部、例外処理部)
RAISE <例外名> ;
(3) 例外への対処方法を定義(例外処理部)
WHEN <例外名> [ OR <例外名> ] THEN 処理文 ;
ユーザー定義例外の書式

 まず宣言部で例外名を定義します。その後、実行部などで特定の処理を行った場合にRAISE文で例外を発生させます。これによって制御は即座に例外処理部に移動します。例外処理部では、内部例外と同様にWHEN句で例外名を指定し、THEN句で例外に対する対処を記述します。

 以下のサンプルプログラムで具体的に見ていきましょう。

DECLARE
  e_sal NUMBER;
  null_sal EXCEPTION;
BEGIN
  SELECT sal INTO e_sal FROM emp WHERE empno = 7369;
    IF e_sal IS NULL
      THEN RAISE null_sal;
    ELSE null;
    END IF;
      UPDATE e_emp SET deptno = 30 WHERE empno = 7369;
EXCEPTION
  WHEN null_sal THEN rollback;
END;
/
PL/SQLプロシージャが正常に完了しました。

 サンプルプログラムでは、まず宣言部で例外名null_salを定義しています。その後、実行部のIF文でe_sal変数に代入されている値を評価し、NULLだった場合はRAISE文で例外を発生させます。RAISE文が実行されると処理は即座に例外処理部に移動します。例外処理部では、前回紹介した内部例外と同様にWHEN句で例外名null_salを指定し、THEN句でロールバックするように指定しています。

定義外例外

 PL/SQLブロック内で対処方法が指定されていない例外を定義外例外と呼びます。

 通常、定義外例外が発生すると、PL/SQLブロックが異常終了してしまいます。明示的に対処方法を指定していないその他の例外が発生した場合であってもPL/SQLブロックを正常終了させたい場合は、OTHERSハンドラを使用します。

 定義外例外を記述するには、次のサンプルプログラムのように例外処理部のWHEN句にOTHERSハンドラを指定し、THEN句で対処方法を記述します。全ての例外に対応するため、定義外例外は例外処理部の最後に記述するようにしましょう。

SQL> DECLARE
       e_empno NUMBER;
     BEGIN
       SELECT empno INTO e_empno FROM emp;
     EXCEPTION
       WHEN too_many_rows THEN rollback;
       WHEN others THEN rollback;
     END;
     /
PL/SQLプロシージャが正常に完了しました。

 OTHERSハンドラでは全ての定義外例外に対処できますが、実際にどういった例外が発生していたのかは分かりません。どのような例外なのかを調査したい場合は、エラー報告関数を使用します。エラー報告関数はその名の通り、発生した例外の情報を提供する関数で、2種類あります。

関数名 機能
SQLCODE エラー番号を返す
SQLERRM エラーメッセージを返す

 次のサンプルプログラムでは、DBMS_OUTPUT.PUT_LINEにエラー報告関数を指定して画面上に例外情報を表示しています(※1)。なお、関数の戻り値を変数に代入し、エラー記録用の表に挿入するような処理も可能です。

※1 エラー報告関数はSQLに直接指定できない。いったん変数に代入してから操作する必要がある。



SQL> DECLARE
       e_empno NUMBER;
     BEGIN
       SELECT empno INTO e_empno FROM emp;
     EXCEPTION
       WHEN others THEN DBMS_OUTPUT.PUT_LINE(sqlcode);
                        DBMS_OUTPUT.PUT_LINE(sqlerrm);
     END;
     /
-1422
ORA-01422: 完全フェッチがリクエストよりも多くの行を戻しました
PL/SQLプロシージャが正常に完了しました。
       1|2 次のページへ

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。