PL/SQL の例外処理 (EXCEPTION WHEN)

EXCEPTION 文による例外処理

PL/SQL の BEGIN と END 間で発生した例外は、そのブロック中で定義した EXCEPTION 文で取り扱う。
同じブロックで例外処理が定義されていない場合には上位のブロックに伝播する。
例外をキャッチしても例外処理部で何も処理をしなければ何も起こらない(※) 。但し 「例外の再呼び出し」 を行なわなければブロック内で例外の処理が行なわれたと判断されて上位のブロックに例外が通知されなくなる。⇒ 例外の再呼び出し

(※) 例外を処理することだけでは PL/SQL はトランザクションのロールバックや何らかの初期化も行なわない。トランザクション処理も含めてすべてユーザープログラムに任せられている。SQL エラーによる 文レベルのロールバック は例外処理に関係なく発生する。

BEGIN
   <プログラム本体>
EXCEPTION
 WHEN <例外名> THEN
   <例外処理>
END;

事前に定義済みの例外の名前

例外処理付き PL/SQL ブロック定義

例外処理 は WHEN 文を複数記述することで場合分けして処理することができる。
複数の例外を同時に処理したい場合には WHEN 例外名 or 例外名 or ... と並べることも可能。

記述例:すべての例外が発生しても何もなかったことにして終了する。(メッセージは表示されない)

DECLARE
	vNum	NUMBER(2);
BEGIN
	vNum := 1 / 0;
	DBMS_OUTPUT.PUT_LINE('数値=' || vNum);
EXCEPTION
	WHEN OTHERS THEN
		NULL; -- NULL; は何もしないという命令
END;
/

OTHERS 例外は特別な例外名で、すべての例外をあらわすことができる。 ただし、OTHERS は他の例外と一緒に並べることはできない。

複数の例外処理の記述と上位への例外の伝播

ゼロ除算の例外が発生した場合エラーメッセージを表示する。ゼロ除算例外発生時には呼び出し元には例外は伝播しない。 ゼロ除算以外のすべて例外発生の場合には <例外処理> を実行し RAISE を使用して呼び出し元に同じ例外情報を伝播する。

DECLARE
	vNum	NUMBER(2);
BEGIN
	-- ZERO DIVIDE EXCEPTION
	vNum := 1 / 0;
	DBMS_OUTPUT.PUT_LINE('数値=' || vNum);
EXCEPTION
	WHEN ZERO_DIVIDE THEN
		DBMS_OUTPUT.PUT_LINE('計算できませんでした');
	WHEN OTHERS THEN
	--	< 例外処理 > 
		RAISE;
END;
/

OTHERS 例外は、すべての例外を包括する例外名であり、例外処理の最後に記述しなければとコンパイルエラーとなる。 (後述の例外ハンドラが呼び出されることがなくなるため)

ネストしたブロックの例外処理

ブロックの構造はネストすることが可能
ループ処理の内部でハンドリング可能な例外が発生する可能性を想定している場合、 その処理ループから抜け出さないようするなどが可能。

DECLARE
	vNum	NUMBER(2);
BEGIN
	BEGIN
		-- ZERO DIVIDE EXCEPTION
		vNum := 1 / 0;
	EXCEPTION
		WHEN ZERO_DIVIDE THEN
			NULL;
	END;
EXCEPTION
	WHEN OTHERS THEN
		< 例外処理 > 
		RAISE;
END;
/


関連事項

日本オラクル
■ 日本オラクル 株式会社
■ オラクルマスター資格 (オラクルマスターとは
■ Oracle のライセンスがわからない…
Oracle Direct (ネットで聞いても最後はここで要確認)