PolarDB for PostgreSQL(Oracle 互換) は、ネイティブ PostgreSQL エラー処理システムをサポートし、Oracle 構文の一般的なエラー処理メカニズムとも互換性があります。
主なエラー処理メカニズムには、次のタイプがあります。
定義済み例外: ネイティブ PostgreSQL のすべての定義済み例外をサポートし、Oracle 構文の一般的な定義済み例外と互換性があります。
定義されていない例外: Oracle 構文の例外変数と互換性があり、
EXCEPTION_INITを使用して例外変数にエラーコードを設定することをサポートしています。カスタム例外(RAISE_APPLICATION_ERROR): Oracle 構文の
RAISE_APPLICATION_ERROR関数と互換性があり、カスタムエラーコードとエラーメッセージを発生させるために使用されます。エラーコードとエラーメッセージ: ネイティブ PostgreSQL
SQLSTATEエラーコードと、Oracle 構文の一般的なSQLCODEエラーコードの両方をサポートしています。また、詳細なエラーメッセージを表示するためのSQLERRMもサポートしています。
定義済み例外
division_by_zero などの PostgreSQL の定義済み例外と、zero_divide などの Oracle の定義済み例外を使用できます。これらの例外は、SQL ブロック内で発生させたり、キャッチしたりできます。
例外を発生させる
例外を発生させるには、エラーが発生する PL/SQL 文を実行して暗黙的に発生させる方法と、RAISE 文を使用して明示的に発生させる方法の 2 つの方法があります。
例外を発生させる方法の例を次に示します。
PL/SQL 文を実行して暗黙的に発生させる
DECLARE
result INT;
BEGIN
result := 1 / 0;
END;
/* ゼロ除算エラーが発生します */RAISE 文を使用して明示的に発生させる
-- PostgreSQL スタイル
BEGIN
RAISE division_by_zero;
END;
/* division_by_zero 例外が発生します */
-- Oracle スタイル
BEGIN
RAISE zero_divide;
END;
/* zero_divide 例外が発生します */例外をキャッチする
EXCEPTION ブロックを使用して例外をキャッチできます。WHEN 句を使用して名前で特定の例外をキャッチするか、WHEN OTHERS を使用してすべての例外をキャッチします。
名前で特定の例外をキャッチする
-- PostgreSQL スタイル
DECLARE
result INT;
BEGIN
result := 1 / 0;
EXCEPTION
WHEN division_by_zero THEN
DBMS_OUTPUT.PUT_LINE('division by zero'); /* ゼロ除算例外を処理します */
END;
-- Oracle スタイル
DECLARE
result INT;
BEGIN
result := 1 / 0;
EXCEPTION
WHEN zero_divide THEN
DBMS_OUTPUT.PUT_LINE('zero divide'); /* ゼロ除算例外を処理します */
END;
WHEN OTHERS を使用してすべての例外をキャッチする
DECLARE
result INT;
BEGIN
result := 1 / 0;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('division by zero'); /* すべての例外を処理します */
END;
定義されていない例外
Oracle 構文には、名前付きの定義済み例外ではないエラーコードが多数含まれています。これらのエラーを名前で処理するには、例外変数を宣言し、Oracle エラーコードに関連付けます。
プロセスには、次の 3 つのステップが含まれます。
DECLAREセクションで、my_exception EXCEPTION;などの例外を宣言します。PRAGMA EXCEPTION_INIT文を使用して、変数をSQLCODE(PRAGMA EXCEPTION_INIT(my_exception, -1476);など)にバインドします。重要関連付けられたエラーコードは、100(
no_data_found例外の場合)または -1000000 から -1 までの負の整数である必要があります。 -65535 から -1 までの範囲のみが有効な Oracle SQLCODE にマップされます。EXCEPTIONセクションで、WHEN my_exceptionまたはWHEN OTHERSを使用して例外をキャッチします。
例
DECLARE
result INT;
my_exception EXCEPTION;
PRAGMA EXCEPTION_INIT(my_exception, -66666); /* 例外を特定のエラーコードに関連付けます */
BEGIN
result := 1 / 0;
EXCEPTION
WHEN my_exception THEN
DBMS_OUTPUT.PUT_LINE('zero divide'); /* 特定の例外を処理します */
END;
カスタム例外(RAISE_APPLICATION_ERROR)
Oracle は、-20999 から -20000 までの整数範囲を 定義済み例外 と 定義されていない例外 用に予約しています。RAISE_APPLICATION_ERROR プロシージャを使用して、この範囲内の特定のエラーコードとメッセージを持つカスタム例外を発生させることができます。
例
DECLARE
salary NUMBER := 4000;
BEGIN
-- ビジネスルールを検証し、条件が満たされない場合はエラーをトリガーします
IF salary < 5000 THEN
RAISE_APPLICATION_ERROR(-20001, 'Salary is below the allowed minimum.'); /* カスタムエラーを発生させます */
END IF;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('SQLCODE: ' || SQLCODE); /* エラーコードを表示します */
DBMS_OUTPUT.PUT_LINE('Custom Error: ' || SQLERRM); /* カスタムエラーメッセージを表示します */
END;
エラーコードとエラーメッセージ
EXCEPTION ブロック内では、次のビルトイン関数を使用してエラーに関する情報を取得できます。
SQLSTATE: ネイティブ PostgreSQL エラーコード。これは 5 文字の文字列で、最初の 2 文字はエラークラスを表します。
SQLCODE: Oracle 互換の整数エラーコード。次の 3 つのカテゴリのいずれかに分類されます。
100:
no_data_found例外を示し、クエリ文が結果を返さなかったことを示します。-65535 から -1: 標準の Oracle エラーを示します。
-99999: PolarDB for PostgreSQL(Oracle 互換) で無効な値またはサポートされていないシナリオを示します。
SQLERRM: 例外について詳しく説明するエラーメッセージ。
例
DECLARE
result INT;
BEGIN
result := 1 / 0;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('SQLCODE: ' || SQLCODE); /* エラーコードを表示します */
DBMS_OUTPUT.PUT_LINE('SQLSTATE: ' || SQLSTATE); /* エラー状態を表示します */
DBMS_OUTPUT.PUT_LINE('SQLERRM: ' || SQLERRM); /* エラーメッセージを表示します */
END;
出力は次のとおりです。
SQLCODE: -1476
SQLSTATE: 22012
SQLERRM: division by zero
エラーコードマッピング
次の表に、サポートされているエラーシナリオを示し、Oracle スタイルの SQLCODE を対応する PostgreSQL スタイルの SQLSTATE にマップします。
SQLCODE | Oracle 例外名 | SQLSTATE | PostgreSQL 例外名 | エラーの説明 |
100 | NO_DATA_FOUND | P0002 | no_data_found | クエリ文が結果を返さない |
-1 | DUP_VAL_ON_INDEX | 23505 | unique_violation | 重複キーを挿入するときに一意制約違反が発生する |
-54 | なし | 55P03 | lock_not_available | ロックの取得に失敗しました |
-939 | なし | 54023 | too_many_arguments | 関数の引数が多すぎます |
-957 | なし | 42701 | duplicate_column | 列名が重複しています |
-960 | なし | 42702 | ambiguous_column | 列名が曖昧です |
-1001 | INVALID_CURSOR | 34000 | invalid_cursor_name | カーソルが未定義か、カーソル名が無効です |
-1031 | なし | 42501 | insufficient_privilege | 権限が不十分です |
-1422 | TOO_MANY_ROWS | P0003 | too_many_rows | クエリ文が返す行が多すぎます |
-1428 | なし | 2201E | invalid_argument_for_logarithm | ログ関数の引数が無効です |
-1428 | なし | 2201F | invalid_argument_for_power_function | べき乗関数の引数が無効です |
-1476 | ZERO_DIVIDE | 22012 | division_by_zero | ゼロ除算 |
-1578 | なし | XX001 | data_corrupted | データの破損 |
-1821 | なし | 22007 | invalid_datetime_format | 日付形式エラー |
-3125 | なし | 08P01 | protocol_violation | 通信プロトコルエラー |
-4020 | なし | 40P01 | deadlock_detected | デッドロックが検出されました |
-6035 | なし | 53000 | insufficient_resources | リソースが不十分です |
-6113 | なし | 53300 | too_many_connections | 接続が多すぎます |
-6503 | なし | 2F005 | function_executed_no_return_statement | 関数に RETURN 文がありません |
-6511 | CURSOR_ALREADY_OPEN | 42P03 | duplicate_cursor | カーソルが複数回定義またはオープンされています |
-6531 | COLLECTION_IS_NULL | 2203G | collection_is_null | コレクションが空です |
-6532 | SUBSCRIPT_OUTSIDE_LIMIT | 2202E | array_subscript_error | 配列インデックスが範囲外です |
-6533 | SUBSCRIPT_BEYOND_COUNT | 2203H | subscript_beyond_count | 配列インデックスが範囲外です |
-6592 | CASE_NOT_FOUND | 20000 | case_not_found | CASE 文に一致する WHEN 句がありません |
-24381 | なし | P0005 | forall_dml_error | FOR ALL 文エラー |
-27102 | なし | 53200 | out_of_memory | メモリが不十分です |
-30110 | なし | 42601 | syntax_error | 構文エラー |
-30156 | なし | 53100 | disk_full | ディスクがいっぱいです |
-1722 | INVALID_NUMBER | - | - | TO_NUMBER 関数の引数が無効です |
-1723 | なし | - | - | 列の長さが 0 です |
-1724 | なし | - | - | FLOAT 型の精度が無効です |
-1727 | なし | - | - | NUMBER 型の精度が無効です |
-6502 | VALUE_ERROR | - | - | 数値形式が無効であるか、上限を超えています |
-6508 | なし | - | - | パッケージ関数が未定義です |
-99999 | なし | - | - | 現在のシナリオはサポートされていません |