例外の処理(実行時エラー)
PL/SQLコードで実行時に発生する例外を処理できます。
See Also: Oracle Database PL/SQL Language Reference for more information about handling PL/SQL errors
例外および例外ハンドラについて
PL/SQLコードで実行時にエラーが発生すると、例外が発生します。例外が発生したサブプログラム(またはブロック)に例外処理部分がある場合は制御が転送され、そうでない場合は実行が停止します。
実行時エラーは、設計障害、コードの誤り、ハードウェア障害およびその他の多くの原因によって発生する可能性があります。
Oracle Databaseには多くの事前定義済の例外があり、プログラムがデータベース・ルールに違反したり、システム固有の制限を超過すると、自動で例外が発生しました。たとえば、SELECT INTO文が行を戻さない場合、Oracle Databaseでは事前定義の例外NO_DATA_FOUNDが呼び出されます。事前定義のPL/SQL例外のサマリーは、Oracle Database PL/SQL言語リファレンスを参照してください。
PL/SQLを使用して、ユーザー固有の例外を定義(宣言)できます。例外の宣言の構文は次のとおりです。
exception_name EXCEPTION;
事前定義済の例外とは異なり、ユーザー定義の例外は、RAISE文またはDBMS_STANDARD.RAISE_APPLICATION_ERRORプロシージャのいずれかを使用して明示的に発生します。たとえば:
IF condition THEN RAISE exception_name;
DBMS_STANDARD.RAISE_APPLICATION_ERRORプロシージャの詳細は、『Oracle Database PL/SQL言語リファレンス』に関する項を参照してください。
サブプログラムの例外処理部には、1つ以上の例外ハンドラが含まれます。例外ハンドラの構文は次のとおりです。
WHEN { exception_name [ OR exception_name ]... | OTHERS } THEN
statement; [ statement; ]...
(「サブプログラム構造について」には、サブプログラムの例外処理部分を挿入する場所が示されています。)
WHEN OTHERS例外ハンドラは、予期しないランタイム・エラーを処理します。使用されると、最後に配置されます。たとえば:
EXCEPTION
WHEN exception_1 THEN
statement; [ statement; ]...
WHEN exception_2 OR exception_3 THEN
statement; [ statement; ]...
WHEN OTHERS THEN
statement; [ statement; ]...
RAISE; -- Reraise the exception (very important).
END;
WHEN OTHERS例外ハンドラのかわりにEXCEPTION_INITプラグマを使用することも可能です。これを使用すると、Oracle Databaseのエラー番号にユーザー定義の例外名を関連付けることもできます。
関連情報:
-
例外宣言の構文は、Oracle Database PL/SQL言語リファレンスを参照
-
例外ハンドラ構文の詳細は、Oracle Database PL/SQL言語リファレンスを参照してください。
-
EXCEPTION_INITプラグマの詳細は、Oracle Database PL/SQL言語リファレンスを参照してください
例外ハンドラを使用するタイミング
例外ハンドラは、次の状況でのみ使用します。
-
例外を予期して処理します。
たとえば、最終的にSELECT INTO文で行が返されず、Oracle Databaseで事前定義済の例外NO_DATA_FOUNDが発生すると想定します。例5-13のとおり、サブプログラムまたはブロックでその例外(エラーではない)を処理して続行します。
-
次の例に示すように、リソースを放棄するか、閉じる必要があります。
... file := UTL_FILE.OPEN ... BEGIN statement statement]... -- If this code fails for any reason, EXCEPTION WHEN OTHERS THEN UTL_FILE.FCLOSE(file); -- then you want to close the file. RAISE; -- Reraise the exception (very important). END; UTL_FILE.FCLOSE(file); ... -
コードの最上位レベルで、エラーを記録する場合。
たとえば、クライアント・プロセスがこのブロックを発行する場合があります。
BEGIN proc(...); EXCEPTION WHEN OTHERS THEN log_error_using_autonomous_transaction(...); RAISE; -- Reraise the exception (very important). END; /または、クライアントが起動するスタンドアロンのサブプログラムは、同じ例外処理ロジックを含むことができますが、最上位レベルのみです。
事前定義済の例外の処理
事前定義済の例外を処理できます。例5-13では、EMP_EVAL.EVAL_DEPARTMENTプロシージャを変更して事前定義済の例外NO_DATA_FOUNDを処理する方法を示します。変更を実行し、変更したプロシージャをコンパイルします。(パッケージ本体の変更方法の例は、「チュートリアル: サブプログラム内の変数および定数の宣言」を参照してください。)
例5-13事前定義済の例外NO_DATA_FOUNDの処理
PROCEDURE eval_department(dept_id IN employees.department_id%TYPE) AS
emp_cursor emp_refcursor_type;
current_dept departments.department_id%TYPE;
BEGIN
current_dept := dept_id;
FOR loop_c IN 1..3 LOOP
OPEN emp_cursor FOR
SELECT *
FROM employees
WHERE current_dept = eval_department.dept_id;
DBMS_OUTPUT.PUT_LINE
('Determining necessary evaluations in department #' ||
current_dept);
eval_loop_control(emp_cursor);
DBMS_OUTPUT.PUT_LINE
('Processed ' || emp_cursor%ROWCOUNT || ' records.');
CLOSE emp_cursor;
current_dept := current_dept + 10;
END LOOP;
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ('The query did not return a result set');
END eval_department;
関連項目:事前定義済例外の詳細は、Oracle Database PL/SQL言語リファレンスを参照してください。
ユーザー定義例外の宣言と処理
ユーザー定義の例外を宣言および処理できます。例5-14では、EMP_EVAL.CALCULATE_SCOREファンクションを変更して2つのユーザー定義の例外wrong_weightおよびwrong_scoreを宣言して処理する方法を示します。変更を実行し、変更したファンクションをコンパイルします。(パッケージ本体の変更方法の例は、「チュートリアル: サブプログラム内の変数および定数の宣言」を参照してください。)
例5-14ユーザー定義の例外の処理
FUNCTION calculate_score ( evaluation_id IN scores.evaluation_id%TYPE
, performance_id IN scores.performance_id%TYPE )
RETURN NUMBER AS
weight_wrong EXCEPTION;
score_wrong EXCEPTION;
n_score scores.score%TYPE;
n_weight performance_parts.weight%TYPE;
running_total NUMBER := 0;
max_score CONSTANT scores.score%TYPE := 9;
max_weight CONSTANT performance_parts.weight%TYPE:= 1;
BEGIN
SELECT s.score INTO n_score
FROM SCORES s
WHERE evaluation_id = s.evaluation_id
AND performance_id = s.performance_id;
SELECT p.weight INTO n_weight
FROM PERFORMANCE_PARTS p
WHERE performance_id = p.performance_id;
BEGIN
IF (n_weight > max_weight) OR (n_weight < 0) THEN
RAISE weight_wrong;
END IF;
END;
BEGIN
IF (n_score > max_score) OR (n_score < 0) THEN
RAISE score_wrong;
END IF;
END;
running_total := n_score * n_weight;
RETURN running_total;
EXCEPTION
WHEN weight_wrong THEN
DBMS_OUTPUT.PUT_LINE(
'The weight of a score must be between 0 and ' || max_weight);
RETURN -1;
WHEN score_wrong THEN
DBMS_OUTPUT.PUT_LINE(
'The score must be between 0 and ' || max_score);
RETURN -1;
END calculate_score;
関連項目:ユーザー定義の例外の詳細は、「Oracle Database PL/SQL言語リファレンス」を参照してください。