例外の明示的な呼出し
例外を明示的に呼び出すには、RAISE
文またはRAISE_APPLICATION_ERROR
プロシージャのいずれかを使用します。
ここでのトピック
RAISE文
RAISE
文は、例外を明示的に呼び出します。例外ハンドラの外側では、例外名を指定する必要があります。例外ハンドラの内側で、例外名を省略すると、RAISE
文は現行の例外を再度呼び出します。
ここでのトピック
ユーザー定義の例外のRAISE文による呼出し
例12-10のプロシージャでは、past_due
という名前の例外を宣言し、この例外をRAISE
文で明示的に呼び出し、例外ハンドラで処理しています。
例12-10 ユーザー定義の例外の宣言、呼出しおよび処理
CREATE PROCEDURE account_status ( due_date DATE, today DATE ) AUTHID DEFINER IS past_due EXCEPTION; -- declare exception BEGIN IF due_date < today THEN RAISE past_due; -- explicitly raise exception END IF; EXCEPTION WHEN past_due THEN -- handle exception DBMS_OUTPUT.PUT_LINE ('Account past due.'); END; / BEGIN account_status (TO_DATE('01-JUL-2010', 'DD-MON-YYYY'), TO_DATE('09-JUL-2010', 'DD-MON-YYYY')); END; /
結果:
Account past due.
内部的に定義された例外のRAISE文による呼出し
内部的に定義された例外はランタイム・システムにより暗黙的に呼び出されますが、名前が付いている場合はRAISE
文を使用して明示的に呼び出すことができます。表12-3に、事前定義の名前を持つ内部的に定義された例外を示します。内部的に定義された例外にユーザーが宣言した名前を指定する方法は、「内部的に定義された例外」を参照してください。
内部的に定義された名前付き例外の例外ハンドラは、その例外の呼出しが暗黙的か明示的かに関係なく、例外を処理します。
例12-11のプロシージャでは、事前定義の例外INVALID_NUMBER
が明示的または暗黙的に呼び出され、必ずINVALID_NUMBER
例外ハンドラによって処理されます。
例12-11 事前定義の例外の明示的な呼出し
DROP TABLE t; CREATE TABLE t (c NUMBER); CREATE PROCEDURE p (n NUMBER) AUTHID DEFINER IS default_number NUMBER := 0; BEGIN IF n < 0 THEN RAISE INVALID_NUMBER; -- raise explicitly ELSE INSERT INTO t VALUES(TO_NUMBER('100.00', '9G999')); -- raise implicitly END IF; EXCEPTION WHEN INVALID_NUMBER THEN DBMS_OUTPUT.PUT_LINE('Substituting default value for invalid number.'); INSERT INTO t VALUES(default_number); END; / BEGIN p(-1); END; /
結果:
Substituting default value for invalid number. BEGIN p(1); END; /
結果:
Substituting default value for invalid number.
現行の例外のRAISE文による再呼出し
例外ハンドラでは、RAISE
文を使用して処理中の例外を「再呼出し」できます。例外を再呼出しすると、外側のブロックに例外を渡してさらに処理することができます。(呼び出された例外を外側のブロックで処理できない場合は例外が伝播します。詳細は「例外の伝播」を参照してください。)現行の例外を再呼出しする場合、例外名を指定する必要はありません。
例12-12の例外処理は、内側のブロックから開始して外側のブロックで終了します。外側のブロックで例外を宣言しているため、両方のブロックに例外名が存在し、各ブロックにこの例外専用の例外ハンドラがあります。内部ブロックが例外を呼び出すと、内部ブロックの例外ハンドラは最初の処理を実行した後にこの例外を再度呼び出し、さらに処理するために外側のブロックに渡しています。
例12-12 例外の再呼出し
DECLARE salary_too_high EXCEPTION; current_salary NUMBER := 20000; max_salary NUMBER := 10000; erroneous_salary NUMBER; BEGIN BEGIN IF current_salary > max_salary THEN RAISE salary_too_high; -- raise exception END IF; EXCEPTION WHEN salary_too_high THEN -- start handling exception erroneous_salary := current_salary; DBMS_OUTPUT.PUT_LINE('Salary ' || erroneous_salary ||' is out of range.'); DBMS_OUTPUT.PUT_LINE ('Maximum salary is ' || max_salary || '.'); RAISE; -- reraise current exception (exception name is optional) END; EXCEPTION WHEN salary_too_high THEN -- finish handling exception current_salary := max_salary; DBMS_OUTPUT.PUT_LINE ( 'Revising salary from ' || erroneous_salary || ' to ' || current_salary || '.' ); END; /
結果:
Salary 20000 is out of range. Maximum salary is 10000. Revising salary from 20000 to 10000.
RAISE_APPLICATION_ERRORプロシージャ
(DBMS_STANDARDパッケージで定義されている)
RAISE_APPLICATION_ERROR
プロシージャは、ストアド・サブプログラムまたはメソッドからのみ起動できます。このプロシージャを起動する通常の目的は、ユーザー定義の例外を呼び出してそのエラー・コードとエラー・メッセージを起動元に戻すことです。
RAISE_APPLICATION_ERROR
プロシージャには、SUPPRESSES_WARNING_6009
プラグマのマークが付いています。
セマンティクスの詳細は、「「SUPPRESSES_WARNING_6009プラグマ」を参照してください。
RAISE_APPLICATION_ERROR
を起動するには、次の構文を使用します。
RAISE_APPLICATION_ERROR (error_code, message[, {TRUE | FALSE}]);
EXCEPTION_INIT
プラグマを使用してerror_code
をユーザー定義の例外に代入しておく必要があります。構文は次のとおりです:
PRAGMA EXCEPTION_INIT (exception_name, error_code)
error_code
は-20000から-20999の範囲の整数で、message
は長さが2048バイト以内の文字列です。
セマンティクスの詳細は、「EXCEPTION_INITプラグマ」を参照してください。
message
は長さが2048バイト以内の文字列です。
TRUE
を指定すると、PL/SQLによりerror_code
がエラー・スタックの最上位に配置されます。それ以外の場合は、PL/SQLによりエラー・スタックがerror_code
に置き換えられます。
例12-13の無名ブロックでは、past_due
という名前の例外を宣言し、この例外にエラー・コード-20000を代入し、ストアド・プロシージャを起動しています。このストアド・プロシージャは、エラー・コード-20000とメッセージを使用してRAISE_APPLICATION_ERROR
プロシージャを起動し、制御が無名ブロックに戻ったところで例外を処理します。例外に関連付けられているメッセージを取得するために、無名ブロックの例外ハンドラがSQLERRM
ファンクション(詳細は、「エラー・コードとエラー・メッセージの取得」を参照)を起動しています。
例12-13 RAISE_APPLICATION_ERRORによるユーザー定義の例外の呼出し
CREATE OR REPLACE PROCEDURE account_status (
due_date DATE,
today DATE
) AUTHID DEFINER
IS
BEGIN
IF due_date < today THEN -- explicitly raise exception
RAISE_APPLICATION_ERROR(-20000, 'Account past due.');
END IF;
END;
/
DECLARE
past_due EXCEPTION; -- declare exception
PRAGMA EXCEPTION_INIT (past_due, -20000); -- assign error code to exception
BEGIN
account_status (TO_DATE('01-JUL-2010', 'DD-MON-YYYY'),
TO_DATE('09-JUL-2010', 'DD-MON-YYYY')); -- invoke procedure
EXCEPTION
WHEN past_due THEN -- handle exception
DBMS_OUTPUT.PUT_LINE(TO_CHAR(SQLERRM(-20000)));
END;
/
結果:
ORA-20000: Account past due.