例外のトラップ
この項では、事前定義のTimesTenエラーまたはユーザー定義のエラーをトラップする方法について説明します。
事前定義済TimesTenエラーのトラップ
事前定義のTimesTenエラーをトラップするには、例外処理ルーチンで事前定義の名前を参照します。PL/SQLでは、STANDARD
パッケージで事前定義例外が宣言されています。
詳細は、次を参照してください。
事前定義済例外のリファレンス
TimesTenでサポートされている事前定義済の例外を示します。
表4-1に、例外について、関連するORA
エラー番号とSQLCODE
値、および説明を示します。
「サポートされていない事前定義済エラー」も参照してください。
表4-1 事前定義済例外
例外名 | Oracle Databaseエラー番号 | SQLCODE | 説明 |
---|---|---|---|
|
|
-6530 |
初期化されていないオブジェクトの属性に値を割り当てようとしました。 |
|
|
-6592 |
|
|
|
-6531 |
EXISTS以外のコレクション・メソッドを初期化されていないネストした表やVARRAYに適用しようとしたか、または初期化されていないネストした表やVARRAYの要素に値を割り当てようとしました。 |
|
|
-6511 |
すでにオープンされているカーソルをオープンしようとしました。 |
|
|
-1 |
プログラムは一意索引によって制約されている列に重複値を挿入しようとしました。 |
|
|
-1001 |
無効なカーソル操作があります。 |
|
|
-1722 |
文字列から数値への変換に失敗しました。 |
|
|
+100 |
単一行の |
|
|
-6501 |
PL/SQLに内部的な問題が発生しました。 |
|
|
-6504 |
代入文のホスト・カーソル変数とPL/SQLカーソル変数の戻り型に互換性がありません。 |
|
|
-6500 |
PL/SQLのメモリーが不足しているか、メモリーが破損しています。 |
|
|
-6533 |
コレクション内の要素の数より大きい索引番号を使用して、ネストした表またはVARRAYを参照しました。 |
|
|
-6532 |
有効範囲外の索引番号(たとえば-1)を使用して、ネストした表またはVARRAY要素を参照しました。 |
|
|
-1410 |
文字列が |
|
|
-1422 |
単一行 |
|
|
-6502 |
算術、変換、切捨てまたはサイズ制限のエラーが発生しました。 |
|
|
-1476 |
数値を0(ゼロ)で割ろうとしました。 |
事前定義済例外の例
この例のPL/SQLプログラムでは、数値を0で割ろうとします。事前定義例外ZERO_DIVIDE
を使用して、例外処理ルーチン内でエラーをトラップします。
Command> DECLARE v_invalid PLS_INTEGER;
BEGIN
v_invalid := 100/0;
EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE ('Attempt to divide by 0');
END;
/
Attempt to divide by 0
PL/SQL procedure successfully completed.
ユーザー定義例外のトラップ
TimesTenのPL/SQLでは、ユーザー独自の例外を定義することができ、またPL/SQL RAISE
文またはRAISE_APPLICATION_ERROR
プロシージャで明示的にユーザー定義の例外を発生させることができます。
これらのプロセスについては、次の項で説明します。
RAISE文の使用方法
RAISE
文を使用すると、PL/SQLブロックまたはサブプログラムの実行を停止し、制御を例外ハンドラに渡すことができます。RAISE
文では、事前定義例外または自分で名前を付けたユーザー定義例外を呼び出すことができます。
次の例では、部門番号500は存在しないため、departments
表内の行は更新されません。RAISE
文を使用して例外を明示的に呼び出し、SQLERRM
組込みファンクションによって戻されるエラー・メッセージとSQLCODE
組込みファンクションによって戻されるエラー・コードを表示します。例外ハンドラ内で、RAISE
文を単独で使用して同じ例外を再度呼び出し、コール元の環境に伝播します。
Command> DECLARE
v_deptno NUMBER := 500;
v_name VARCHAR2 (20) := 'Testing';
e_invalid_dept EXCEPTION;
BEGIN
UPDATE departments
SET department_name = v_name
WHERE department_id = v_deptno;
IF SQL%NOTFOUND THEN
RAISE e_invalid_dept;
END IF;
ROLLBACK;
EXCEPTION
WHEN e_invalid_dept THEN
DBMS_OUTPUT.PUT_LINE ('No such department');
DBMS_OUTPUT.PUT_LINE (SQLERRM);
DBMS_OUTPUT.PUT_LINE (SQLCODE);
END;
/
No such department
User-Defined Exception
1
PL/SQL procedure successfully completed.
The command succeeded.
ノート:
TimesTenとOracle Databaseでエラー条件が同じ場合、SQLCODE
によって戻されるエラー・コードは同じですが、SQLERRM
によって戻されるエラー・メッセージは同じとはかぎりません。これについては、「TimesTenのエラー・メッセージおよびSQLコード」でも説明しています。
RAISE_APPLICATION_ERRORプロシージャの使用
RAISE_APPLICATION_ERROR
プロシージャは、PL/SQLプログラムの実行可能セクションまたは例外セクション(あるいはその両方)で使用します。TimesTenによってアプリケーションにエラーがレポートされるため、未処理例外を戻すのを回避できます。
-20,000から-20,999の範囲のエラー番号を使用します。メッセージには最大2,048バイトの文字列を指定します。
次の例では、employees
表からlast_name=Patterson
のデータを削除しようとします。RAISE_APPLICATION_ERROR
プロシージャで、エラー番号-20201を使用してエラーを呼び出します。
Command> DECLARE
v_last_name employees.last_name%TYPE := 'Patterson';
BEGIN
DELETE FROM employees WHERE last_name = v_last_name;
IF SQL%NOTFOUND THEN
RAISE_APPLICATION_ERROR (-20201, v_last_name || ' does not exist');
END IF;
END;
/
8507: ORA-20201: Patterson does not exist
8507: ORA-06512: at line 6
The command failed.