対象DBMSバージョン、エディション
動作確認はOracle Autonomous Transaction Processing Cloud Service(バージョン19.5)で実施していますが、エディションは問いません。また、マニュアルを机上確認する限り、Oracle7以降にて対応しています。
はじめに
障害テストなどのためにわざとORAエラーを発生させたい場合があります。制約違反や参照先テーブルがないテストパターンなどは比較的楽に実装できますが、例えばORA-600とかORA-7445といった内部エラーを故意に発生させるにはどうすればいいでしょうか?
実はPL/SQLを使用すると、任意の番号のORAエラーを発生させることが可能です。
ただし、欠点もないわけではないので、注意点含め解説したいと思います。
大きくは以下の2つの方法があります。
1. RAISE_APPLICATION_ERRORプロシージャ
対応エラーコード範囲が限定されるので、掲題の趣旨とは少し異なりますが、RAISE_APPLICATION_ERRORプロシージャを用いると、お手軽に特定の番号のORAエラーを発生させることが可能です。対応ししているエラー番号の範囲は、-20000~-20999となります。
RAISE_APPLICATION_ERRORプロシージャには、以下の3つの引数が存在します。
- エラー番号:-20000~-20999の範囲内で指定
- エラーメッセージ:2048バイト以内の文字列
- エラー表示形式:FALSE(デフォルト)はエラースタックを本プロシージャによるエラーに置換、TRUEはエラースタックの最上位に本プロシージャによるエラーを配置
使い方は、以下のように簡単です。例だと雑なIF文ですが、何らかのチェックを行ってアプリケーション上問題となる場合にRAISE_APPLICATION_ERRORプロシージャを呼び出すのが典型的な利用方法となります。
SQL> BEGIN
2 IF 1 < 2 THEN
3 RAISE_APPLICATION_ERROR(-20000, 'エラー発生');
4 END IF;
5 END;
6 /
BEGIN
*
行1でエラーが発生しました。:
ORA-20000: エラー発生
ORA-06512: 行3
2. ユーザー定義例外
RAISE_APPLICATION_ERRORプロシージャは簡便に利用できる半面、意図的にORA-942やORA-600といった、Oracle Database自身が利用するエラー番号のエラーを発生させることはできません。しかし、以下のようにユーザー定義例外を利用すると、自前で任意の番号のORAエラーを発生させることが可能です。
SQL> DECLARE
2 E942 EXCEPTION;
3 PRAGMA EXCEPTION_INIT(E942, -942);
4 BEGIN
5 RAISE E942;
6 END;
7 /
DECLARE
*
行1でエラーが発生しました。:
ORA-00942: 表またはビューが存在しません。 ORA-06512: 行5
まず、2行目でユーザー定義例外(EXCEPTION)を定義しています。この例だと、「E942」が例外の名称となります。
3行目は、2行目のユーザー定義例外と、実際のORAエラー番号(エラー番号はマイナスです)を紐づけるプラグマを定義しています。
5行目で、2行目で定義した例外を呼び出すと、3行目で定義したエラー番号で例外が発生します。
上記の例のような、固定のエラーメッセージはこれで問題ないのですが、例えばORA-1のような、エラー対象のオブジェクト名がエラーメッセージに含まれるエラーの場合、エラーとなったオブジェクトが実際には存在しないので、該当箇所が空白となります。ですので、エラーとなったオブジェクト名を拾いたい場合にはこの方法は利用できず、エラーが発生する状況を実直に作り出すしかありません。以下の例では、意図したエラー番号でエラーを発生させることはできているのですが、「スキーマ名.制約名」の部分が、スキーマ名と制約名を分ける「.」だけになってしまっています。
SQL> DECLARE
2 E1 EXCEPTION;
3 PRAGMA EXCEPTION_INIT(E1, -1);
4 BEGIN
5 RAISE E1;
6 END;
7 /
DECLARE
*
行1でエラーが発生しました。:
ORA-00001: 一意制約(.)に反しています ORA-06512:
行5
ORA-600のような内部エラーも、ORA-600自体は発生させられますが、エラーメッセージ内の内部番号欄は空になります。トレースファイルも出力はされますが、実際に内部エラーが発生しているわけではないので、内容はほぼヘッダーのみとなります。
SQL> DECLARE
2 FATAL_ERROR EXCEPTION;
3 PRAGMA EXCEPTION_INIT(FATAL_ERROR, -600);
4 BEGIN
5 RAISE FATAL_ERROR;
6 END;
7 /
DECLARE
*
行1でエラーが発生しました。:
ORA-00600: 内部エラー・コード, 引数: [600], [], [], [], [], [], [], [], [], [], [], []
ORA-06512: 行5