事前定義の例外
事前定義の例外は、事前定義の名前を持つ内部的に定義された例外で、PL/SQLによりパッケージSTANDARD
の中でグローバルに宣言されています。事前定義の例外はランタイム・システムによって暗黙的(自動的)に呼び出されます。事前定義の例外には名前が付いているため、それ専用の例外ハンドラを記述できます。
表12-3に、事前定義の例外の名前とエラー・コードを示します。
表12-3 PL/SQLの事前定義の例外
例外名 | Oracleエラー | エラー・コード |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
例12-6では、企業の株価収益率を計算しています。企業の収益が0(ゼロ)の場合に除算演算を実行すると、事前定義の例外ZERO_DIVIDE
が呼び出され、ブロックの実行部から例外処理部に制御が移ります。
例12-7では、例12-6で処理されている例外を、エラー・チェック・コードを使用して回避しています。
例12-8では、プロシージャは、パラメータdiscrim
の値に応じてEMPLOYEES
表またはDEPARTMENTS
表のカーソル変数をオープンします。無名ブロックは、プロシージャを起動してEMPLOYEES
表のカーソル変数をオープンしますが、DEPARTMENTS
表からフェッチするため、事前定義の例外ROWTYPE_MISMATCH
が発生します。
関連項目:
- 「内部的に定義された例外のRAISE文による呼出し」
- データベース・エラー・メッセージでは、Oracleエラー番号を検索して個々の例外の詳細を確認できます
例12-6 ZERO_DIVIDEを処理する無名ブロック
DECLARE stock_price NUMBER := 9.73; net_earnings NUMBER := 0; pe_ratio NUMBER; BEGIN pe_ratio := stock_price / net_earnings; -- raises ZERO_DIVIDE exception DBMS_OUTPUT.PUT_LINE('Price/earnings ratio = ' || pe_ratio); EXCEPTION WHEN ZERO_DIVIDE THEN DBMS_OUTPUT.PUT_LINE('Company had zero earnings.'); pe_ratio := NULL; END; /
結果:
Company had zero earnings.
例12-7 ZERO_DIVIDEを回避する無名ブロック
DECLARE stock_price NUMBER := 9.73; net_earnings NUMBER := 0; pe_ratio NUMBER; BEGIN pe_ratio := CASE net_earnings WHEN 0 THEN NULL ELSE stock_price / net_earnings END; END; /
例12-8 ROWTYPE_MISMATCHを処理する無名ブロック
CREATE OR REPLACE PACKAGE emp_dept_data AUTHID DEFINER AS TYPE cv_type IS REF CURSOR; PROCEDURE open_cv ( cv IN OUT cv_type, discrim IN POSITIVE ); END emp_dept_data; / CREATE OR REPLACE PACKAGE BODY emp_dept_data AS PROCEDURE open_cv ( cv IN OUT cv_type, discrim IN POSITIVE) IS BEGIN IF discrim = 1 THEN OPEN cv FOR SELECT * FROM EMPLOYEES ORDER BY employee_id; ELSIF discrim = 2 THEN OPEN cv FOR SELECT * FROM DEPARTMENTS ORDER BY department_id; END IF; END open_cv; END emp_dept_data; /
無名ブロックからプロシージャopen_cv
を起動します。
DECLARE emp_rec EMPLOYEES%ROWTYPE; dept_rec DEPARTMENTS%ROWTYPE; cv Emp_dept_data.CV_TYPE; BEGIN emp_dept_data.open_cv(cv, 1); -- Open cv for EMPLOYEES fetch. FETCH cv INTO dept_rec; -- Fetch from DEPARTMENTS. DBMS_OUTPUT.PUT(dept_rec.DEPARTMENT_ID); DBMS_OUTPUT.PUT_LINE(' ' || dept_rec.LOCATION_ID); EXCEPTION WHEN ROWTYPE_MISMATCH THEN BEGIN DBMS_OUTPUT.PUT_LINE ('Row type mismatch, fetching EMPLOYEES data ...'); FETCH cv INTO emp_rec; DBMS_OUTPUT.PUT(emp_rec.DEPARTMENT_ID); DBMS_OUTPUT.PUT_LINE(' ' || emp_rec.LAST_NAME); END; END; /
結果:
Row type mismatch, fetching EMPLOYEES data ...
90 King