アプリケーション・プログラムでは、ランタイム・エラーを予想し、エラーからのリカバリを試みる必要があります。この章では、エラーのレポートおよびリカバリについて詳しく説明します。状態変数のSQLCODEl、SQLSTATE、SQLCA(SQL通信領域)およびWHENEVER
文を使用して、警告およびエラーを処理する方法を学習します。内容は次のとおりです。
エラー処理の必要性
エラー処理の代替方法
MODE={ANSI|ANSI14}の場合の状態変数の使用方法
SQL通信領域の使用方法
Oracle通信領域の使用方法
どのようなアプリケーション・プログラムでも、その大部分をエラー処理に充てる必要があります。エラー処理の主な利点は、エラーが発生しても、プログラムの処理を続行できることです。エラーは、設計ミス、コーディングの誤り、ハードウェアの障害、無効なユーザー入力、その他様々な原因で発生します。
潜在的なエラーをすべて予想することは無理ですが、プログラムにとって重要なある種のエラーについては、処理方法を計画することはできます。Oracleプリコンパイラにとって、エラー処理とはSQL文の実行エラーの検出およびリカバリのことです。
「値が切り捨てられました」などの警告や「データの終わり」などの状態変化も、処理の準備を整えておくことができます。INSERT
文、UPDATE
文またはDELETE
文は、表内の処理対象行すべてを処理する前に失敗することがあるため、データ操作文を実行するたびにエラー状態および警告状態がないか調べることが特に重要です。
Oracleプリコンパイラには、エラー処理の手段として役立つ4種類の状態変数が用意されています。
MODEオプションは、ANSI/ISOの準拠を制御します。SQLCODE変数、SQLSTATE変数およびSQLCA変数の可用性は、MODE設定によって異なります。ORACA変数は、MODE設定に関係なく宣言して使用できます。詳細は、「Oracle通信領域の使用方法」を参照してください。
MODE={ORACLE|ANSI13}
の場合、SQLCA状態変数を宣言する必要があります。SQLCODE宣言およびSQLSTATE宣言も指定できますが(お薦めはできません)、状態変数としては認識されません。詳細は、「SQL通信領域の使用方法」を参照してください。
MODE={ANSI|ANSI14}
の場合、SQLCODE変数、SQLSTATE変数およびSQLCA変数のうちの任意の1つ、2つあるいは3つすべてを使用できます。アプリケーションに最適な変数(または変数の組合せ)を確認するには、「MODE={ANSI|ANSI14}の場合の状態変数の使用方法」を参照してください。
Oracleプリコンパイラのリリース1.5では、SQLCODE状態変数が、SQL89標準ANSI/ISOエラー・レポート・メカニズムとして導入されました。SQL92標準では、SQLCODEが非推奨機能として挙げられ、新しい状態変数SQLSTATE(Oracleプリコンパイラのリリース1.6で導入)が推奨ANSI/ISOエラー・レポート・メカニズムとして定義されました。
SQLCODEには、エラー・コードおよび見つからない状態が格納されています。SQLCODEは、SQL89との互換性のためのみに保持されており、標準の将来のバージョンからは削除される見込みです。
SQLCODEとは異なり、SQLSTATEにはエラーおよび警告のコードが格納され、標準化されたコード体系を使用します。SQL文を実行すると、Oracleサーバーからは、現在有効範囲内にあるSQLSTATE変数にステータス・コードが戻されます。ステータス・コードは、SQL文が正常に実行されたか、あるいは例外(エラーまたは警戒の状態)が発生したかを示します。相互運用性(システムが情報を容易に交換する能力)を高めるために、SQL92では、すべての一般的なSQL例外が事前に定義されています。
SQLCAは、レコードに似たホスト言語データ構造です。Oracleでは、実行SQL文が実行されるたびに、SQLCAが更新されます(宣言部の後ではSQLCA値は未定義になります)。プログラムは、SQLCAに格納されているOracleリターン・コードをチェックして、SQL文の結果を確認できます。これには次の2つの方法があります。
WHENEVER文による暗黙的チェック
SQLCA変数の明示的チェック
WHENEVER
文、SQLCA変数に対するコードの明示的チェックを使用するか、あるいは両方を使用できます。一般的に、WHENEVER
文を使用する方が簡単で、移植性も高く、ANSI準拠であるためお薦めします。
ランタイム・エラーについてSQLCAから得られる情報が十分でない場合、カーソル統計、SQL文データ、オプション設定およびシステム統計が格納されているORACAを使用できます。
ORACAはオプションであり、MODE設定に関係なく宣言できます。ORACA状態変数の詳細は、「Oracle通信領域の使用方法」を参照してください。
MODE={ANSI|ANSI14}
の場合、次の状態変数の少なくとも1つを宣言する必要があります(2つあるいは3つ全部を宣言してもかまいません)。
Pro*COBOLでは、SQLCAが宣言されていれば、SQLCODEは宣言できません。同様に、SQLCODEが宣言されていれば、SQLCAは宣言できません。SQLCAデータ構造のフィールドにはPro*COBOL用のエラー・コードが格納されており、SQLCODEとも呼ばれ、そのためこれら2つの状態変数を宣言するとエラーが発生します。
プログラムでは、実行SQL文およびPL/SQL文の後で、独自のコードを使用して明示的にSQLCODEおよびSQLSTATE、SQLCODEまたはSQLSTATEをチェックすることで、最新の実行SQL文の結果を取得できます。また、SQLCAを暗黙的にチェックすることも(WHENEVER
SQLERROR文およびWHENEVER
SQLWARNING文を使用)、SQLCA変数を明示的にチェックすることもできます。
Oracleプリコンパイラ・リリース1.5では、宣言部で宣言されているかどうかに関係なく、状態変数SQLCODEはあると仮定しました。実際、プリコンパイラでは、SQLCODEの宣言があるかどうかをわざわざ通知することはなく、単に宣言は存在すると仮定しました。SQLCAのINCLUDE
がある場合にのみ、SQLCAが状態変数として使用されました。
Oracleプリコンパイラ・リリース1.6から、プリコンパイラでは、SQLCODE状態変数があると仮定しなくなり、SQLCODE状態変数は必須ではありません。SQLCA、SQLCODEまたはSQLSTATEのうち少なくとも1つを宣言する必要があります。
SQLCODEは、少なくとも次の基準の1つが満たされたときにかぎり、状態変数として認識されます。
宣言部で完全に正しいデータ型で宣言されている場合。
プリコンパイラで他の状態変数が見つからない場合。
プリコンパイラが宣言部で(完全に正しい型の)SQLSTATE宣言を検出した場合、またはSQLCAのINCLUDE
を検出した場合には、SQLCODEが宣言されているとはみなしません。
Oracleプリコンパイラのリリース1.5では、SQLCODE変数を宣言部の外部で宣言できたのに対し、リリース1.6以降のプリコンパイラでは、同時にSQLCAを宣言すると、互換性の問題が生じます。これを修正するために、リリース1.6.7では新しいオプションASSUME_SQLCODE={YES|NO}
(デフォルトはNO)が追加され、リリース1.7で新機能として文書化されました。
ASSUME_SQLCODE=YES
と指定した場合、SQLSTATEまたはSQLCA(Pro*FORTRANのみ)が状態変数として宣言されると、宣言部で宣言されているかどうか、あるいは正しい型かどうかに関係なく、プリコンパイラではSQLCODEが宣言されているものとみなします。このため、リリース1.6.7以降は、この点でリリース1.5と同様の動作をします。プリコンパイラ・オプションASSUME_SQLCODEの詳細は、「ASSUME_SQLCODE」を参照してください。
SQLCODE(Pro*FORTRANではSQLCOD)は、表8-1に示すように、宣言部の内側または外側のいずれかで、4バイト整数変数として宣言する必要があります。
宣言部の外部で宣言すると、SQLCODEは、ASSUME_SQLCODE=YESの場合にのみ状態変数として認識されます。MODE={ORACLE|ANSI13}
の場合、SQLCODEの宣言は無視されます。
警告: Pro*COBOLソース・ファイルでは、SQLCAが宣言されている場合は、SQLCODEを宣言しないでください。同様に、SQLCODEが宣言されている場合は、SQLCAを宣言しないでください。SQLCA構造体で宣言された状態変数はSQLCODEとも呼ばれ、両方のエラー・レポート・メカニズムを使用すると、エラーが発生します。 |
ローカルとグローバルの両方の宣言が可能なホスト言語を使用することにより、複数のSQLCODE変数を宣言できます。ローカルSQLCODEへのアクセスは、プログラム内の有効範囲により制限されます。SQLの動作が終わるごとに、Oracleから現在有効範囲にあるSQLCODEにステータス・コードが戻されます。したがって、プログラムでは、SQLCODEを明示的にチェックするか、WHENEVER
文で暗黙的にチェックして、最近のSQL動作の結果を確認できます。
特定のコンパイル・ユニットのSQLCAのかわりにSQLCODEを宣言すると、プリコンパイラでは、そのユニット用に内部SQLCAを1つ割り当てます。ホスト・プログラムでは、その内部SQLCAにアクセスできません。SQLCAとSQLCODE(Pro*COBOLでは非対応)を宣言すると、OracleからはSQLの動作が終わるごとに、両方に同じステータス・コードが戻されます。
SQLSTATE(Pro*FORTRANではSQLSTA)は、表8-2に示すように、宣言部内5文字の英数字文字列として宣言する必要があります。SQLCAの宣言はオプションです。
MODE={ANSI|ANSI14}
の場合、状態変数の動作は、次の条件によって決まります。
宣言されている変数
宣言の配置(宣言部の内側か外側か)
ASSUME_SQLCODE設定
表8-3および表8-4では、ASSUME_SQLCODE=NOおよびASSUME_SQLCODE=YESのそれぞれの場合、各状態変数の組合せがどのような動作になるかを説明しています。
表8-3 状態変数の組合せ - SQLCODE = NO
宣言部(内/外/ --) | 動作 | ||
---|---|---|---|
SQLCODE |
SQLSTATE |
SQLCA |
|
外 |
-- |
-- |
SQLCODEが宣言され、状態変数とみなされます。 |
外 |
-- |
外 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、SQLCAが状態変数として宣言され、SQLCODEは宣言されますが、状態変数とは認識されません。 |
外 |
-- |
内 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、この状態変数の構成はサポートされていません。 |
外 |
外 |
-- |
SQLCODEが宣言されて状態変数とみなされ、SQLSTATEは宣言されますが、状態変数とは認識されません。 |
外 |
外 |
外 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、SQLCAが状態変数として宣言され、SQLCODEおよびSQLSTATEは宣言されますが、状態変数とは認識されません。 |
外 |
外 |
内 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、この状態変数の構成はサポートされていません。 |
外 |
内 |
-- |
SQLSTATEが状態変数として宣言され、SQLCODEは宣言されますが、状態変数とは認識されません。 |
外 |
内 |
外 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、SQLSTATEおよびSQLCAが状態変数として宣言され、SQLCODEは宣言されますが、状態変数とは認識されません。 |
外 |
内 |
内 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、この状態変数の構成はサポートされていません。 |
内 |
-- |
-- |
SQLCODEが状態変数として宣言されます。 |
内 |
-- |
外 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、SQLCODEおよびSQLCAが状態変数として宣言されます。 |
内 |
-- |
内 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、この状態変数の構成はサポートされていません。 |
内 |
外 |
-- |
SQLCODEが状態変数として宣言され、SQLSTATEは宣言されますが、状態変数としてではありません。 |
内 |
外 |
外 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、SQLCODEおよびSQLCAが状態変数として宣言され、SQLSTATEは宣言されますが、状態変数とは認識されません。 |
内 |
外 |
内 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、この状態変数の構成はサポートされていません。 |
内 |
内 |
-- |
SQLCODEおよびSQLSTATEが状態変数として宣言されます。 |
内 |
内 |
外 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、SQLCODE、SQLSTATEおよびSQLCAが状態変数として宣言されます。 |
内 |
内 |
内 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、この状態変数の構成はサポートされていません。 |
-- |
-- |
-- |
この状態変数の構成はサポートされていません。 |
-- |
-- |
外 |
SQLCAが状態変数として宣言されます。 |
-- |
-- |
内 |
Pro*COBOLでは、SQLCAが状態ホスト変数として宣言されます。Pro*FORTRANでは、この状態変数の構成はサポートされていません。 |
-- |
外 |
-- |
この状態変数の構成はサポートされていません。 |
-- |
外 |
外 |
SQLCAが状態変数として宣言され、SQLSTATEは宣言されますが、状態変数とは認識されません。 |
-- |
外 |
内 |
Pro*COBOLでは、SQLCAが状態ホスト変数として宣言され、SQLSTATEは宣言されますが、状態変数とは認識されません。Pro*FORTRANでは、この状態変数の構成はサポートされていません。 |
-- |
内 |
-- |
SQLSTATEが状態変数として宣言されます。 |
-- |
内 |
外 |
SQLSTATEおよびSQLCAが状態変数として宣言されます。 |
-- |
内 |
内 |
Pro*COBOLでは、SQLSTATEおよびSQLCAが状態ホスト変数として宣言されます。Pro*FORTRANでは、この状態変数の構成はサポートされていません。 |
表8-4 状態変数の組合せ - SQLCODE = YES
宣言部(内/外/ --) | 動作 | ||
---|---|---|---|
SQLCODE |
SQLSTATE |
SQLCA |
|
外 |
-- |
-- |
SQLCODEが宣言され、状態変数とみなされます。 |
外 |
-- |
外 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、SQLCAが状態変数として宣言され、SQLCODEは宣言されますが、状態変数とはみなされません。 |
外 |
-- |
内 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、この状態変数の構成はサポートされていません。 |
外 |
外 |
-- |
SQLCODEが宣言されて状態変数とみなされ、SQLSTATEは宣言されますが、状態変数とは認識されません。 |
外 |
外 |
外 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、SQLCAが状態変数として宣言され、SQLCODEは宣言されて状態変数とみなされ、SQLSTATEは宣言されますが、状態変数とは認識されません。 |
外 |
外 |
内 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、この状態変数の構成はサポートされていません。 |
外 |
内 |
-- |
SQLSTATEが状態変数として宣言され、SQLCODEは宣言されて状態変数とみなされます。 |
外 |
内 |
外 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、SQLSTATEおよびSQLCAが状態変数として宣言され、SQLCODEは宣言されて状態変数とみなされます。 |
外 |
内 |
内 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、この状態変数の構成はサポートされていません。 |
内 |
-- |
-- |
SQLCODEが状態変数として宣言されます。 |
内 |
-- |
外 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、SQLCODEおよびSQLCAが状態変数として宣言されます。 |
内 |
-- |
内 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、この状態変数の構成はサポートされていません。 |
内 |
外 |
-- |
SQLCODEが状態変数として宣言され、SQLSTATEは宣言されますが、状態変数としてではありません。 |
内 |
外 |
外 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、SQLCODEおよびSQLCAが状態変数として宣言され、SQLSTATEは宣言されますが、状態変数とは認識されません。 |
内 |
外 |
内 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、この状態変数の構成はサポートされていません。 |
内 |
内 |
-- |
SQLCODEおよびSQLSTATEが状態変数として宣言されます。 |
内 |
内 |
外 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、SQLCODE、SQLSTATEおよびSQLCAが状態変数として宣言されます。 |
内 |
内 |
内 |
Pro*COBOLでは、この状態変数の構成はサポートされていません。Pro*FORTRANでは、この状態変数の構成はサポートされていません。 |
-- -- -- -- -- -- -- -- -- |
-- -- -- 外 外 外 内 内 内 |
-- 外 内 -- 外 内 -- 外 内 |
これらの状態変数の構成はサポートされていません。SQLCODEは、ASSUME_SQLCODE=YESの場合、宣言部の内側または外側のいずれかで宣言する必要があります。 |
SQLの動作が終わるたびに、Oracleから現在有効範囲にあるSQLCODE変数にステータス・コードが戻されます。SQLの動作の結果を示すステータス・コードは、次のいずれかの数値です。
0
OracleではSQL文が実行され、エラーも例外も検出されませんでした。
> 0
Oracleでは文は実行されましたが、例外が検出されました。これは、WHERE
句の条件を満たす行が見つからなかった場合、あるいはSELECT
INTO
またはFETCH
で行が戻されなかった場合に発生します。
MODE={ANSI|ANSI14|ANSI13}
の場合、行のINSERT
がなかったときに+100がSQLCODEに戻されます。これは、副問合せで処理する行が戻されなかった場合に発生します。
< 0
データベース、システム、ネットワークまたはアプリケーションのエラーのため、Oracleでは文が実行されませんでした。このようなエラーはリカバリ不能です。これらのエラーが発生した場合、現行のトランザクションは、ほとんどの場合、ロールバックする必要があります。エラー・コードに対応する負数のリターン・コードは、『Oracle Databaseエラー・メッセージ』に記載されています。
最近のSQLの動作の結果は、SQLCODEを独自のコードで明示的にチェックするか、WHENEVER
文で暗黙的にチェックすることで確認できます。
特定のプリコンパイル・ユニットのSQLCAのかわりにSQLCODEを宣言すると、プリコンパイラでは、そのユニット用に内部SQLCAを1つ割り当てます。ホスト・プログラムでは、その内部SQLCAにアクセスできません。SQLCAとSQLCODE(Pro*FORTRANのみ)を宣言すると、OracleからはSQLの動作が終わるたびに、両方に同じステータス・コードが戻されます。
注意: MODE={ORACLE|ANSI13} の場合、SQLCODEの宣言は無視されます。 |
SQLSTATE状態コードは、2文字のクラス・コードおよびその後に続く3文字のサブクラス・コードで構成されます。クラス・コード00(正常終了)以外では、クラス・コードは例外のカテゴリを示します。サブクラス・コード000(適用外)以外では、サブクラス・コードはそのカテゴリ内の特定の例外を示します。たとえば、SQLSTATE値22012は、クラス・コード22(データ例外)とサブクラス・コード012(ゼロ除算)で構成されています。
SQLSTATE値の5文字はそれぞれ、数字(0~9)または大文字の英字(A~Z)です。0~4の数字、あるいはA~Hの文字で始まるクラス・コードは、事前定義の条件(SQL92で定義されている条件)用に予約されています。他のすべてのクラス・コードは、実装時に定義される条件用に予約されています。事前定義クラスのうち、0~4の数字またはA~Hの文字で始まるサブクラス・コードは、事前定義の副条件用に予約されています。他のすべてのサブクラス・コードは、実装時に定義される副条件用に予約されています。図8-1は、コード体系を示しています。
表8-5は、SQL92で事前に定義されているクラスを示しています。
表8-5 事前に定義されたSQL92のクラス
クラス | 条件 |
---|---|
00 |
正常終了 |
01 |
警告 |
02 |
データなし |
07 |
動的SQLエラー |
08 |
接続の例外 |
0A |
サポートされていない機能 |
21 |
カーディナリティ違反 |
22 |
データ例外 |
23 |
整合性制約違反 |
24 |
無効なカーソル状態 |
25 |
無効なトランザクション状態 |
26 |
無効なSQL文名 |
27 |
トリガー・データの変更違反 |
28 |
無効な認証指定 |
2A |
直接SQL構文エラーまたはアクセス規則違反 |
2B |
まだ存在する依存権限記述子 |
2C |
無効なキャラクタ・セット名 |
2D |
無効なトランザクション終了 |
2E |
無効な接続名 |
33 |
無効なSQL記述子名 |
34 |
無効なカーソル名 |
35 |
無効な条件番号 |
37 |
動的SQL構文エラーまたはアクセス規則違反 |
3C |
あいまいなカーソル名 |
3D |
無効なカタログ名 |
3F |
無効なスキーマ名 |
40 |
トランザクション・ロールバック |
42 |
構文エラーまたはアクセス規則違反 |
44 |
WITH_CHECKオプション違反 |
HZ |
リモート・データベース・アクセス |
注意: クラス・コードHZは、国際標準規格ISO/IEC DIS 9579-2で定義された条件であるリモート・データベース・アクセス用に予約されています。 |
表8-6は、SQLSTATEステータス・コードとOracleエラーの対応を示しています。一部のOracleエラーではステータス・コードと対応する場合がありますが、それ以外の場合は、ステータス・コードと対応するOracleエラーがありません(その場合は、最後の列が空になっています)。60000~99999の範囲のステータス・コードは、実装時に定義されています。
表8-6 OracleエラーとSQLSTATEステータス・コードの対応
コード | 条件 | Oracleエラー |
---|---|---|
00000 |
正常終了 |
ORA-00000 |
01000 |
警告 |
|
01001 |
カーソル操作の競合 |
|
01002 |
切断エラー |
|
01003 |
集合関数でのNULL値の削除 |
|
01004 |
文字列データの右側切捨て |
|
01005 |
不十分な項目記述子領域 |
SQL-02142 |
01006 |
取り消されていない権限 |
|
01007 |
付与されていない権限 |
|
01008 |
暗黙的なゼロビットの埋込み |
|
01009 |
情報スキーマには長すぎる検索条件 |
|
0100A |
情報スキーマには長すぎる問合せ式 |
|
02000 |
データなし |
ORA-01095 ORA-01403 ORA-0100 |
07000 |
動的SQLエラー |
SQL-02137 SQL-02139 |
07001 |
パラメータの指定と一致しないUSING句 |
|
07002 |
ターゲットの指定と一致しないUSING句 |
|
07003 |
実行できないカーソル仕様 |
|
07004 |
動的パラメータに必要なUSING句 |
|
07005 |
カーソル仕様ではないプリコンパイル文 |
|
07006 |
制限付きデータ型属性違反 |
|
07007 |
結果フィールドに必要なUSING句 |
|
07008 |
無効な記述子の数 |
SQL-02126 SQL-02141 |
07009 |
無効な記述子の索引 |
SQL-02140 |
08000 |
接続の例外 |
|
08001 |
SQL接続を確立できないSQLクライアント |
|
08002 |
使用中の接続名 |
|
08003 |
存在しない接続 |
SQL-02121 |
08004 |
SQLサーバーによるSQL接続の拒否 |
|
08006 |
接続の失敗 |
|
08007 |
トランザクション解決が不明 |
|
0A000 |
サポートされていない機能 |
ORA-03000~03099 |
0A001 |
複数のサーバー・トランザクション |
|
21000 |
カーディナリティ違反 |
ORA-01427 SQL-02112 ORA-01422 |
22000 |
データ例外 |
|
22001 |
文字列データの右側切捨て |
ORA-01401 ORA-01406 ORA-12899 |
22002 |
NULL値 - インジケータ・パラメータなし |
ORA-01405 SQL-02124 |
22003 |
範囲外の数値 |
ORA-01426 ORA-01438 ORA-01455 ORA-01457 |
22005 |
割当てエラー |
|
22007 |
無効な日時書式 |
|
22008 |
日時フィールドのオーバーフロー |
ORA-01800~01899 |
22009 |
無効なタイムゾーンの時差値 |
|
22011 |
部分文字列エラー |
|
22012 |
ゼロによる除算 |
ORA-01476 |
22015 |
間隔フィールドのオーバーフロー |
|
22018 |
無効なキャスト用文字値 |
|
22019 |
無効なエスケープ文字 |
ORA-00911 ORA-01425 |
22021 |
レパートリにない文字 |
|
22022 |
インジケータのオーバーフロー |
ORA-01411 |
22023 |
無効なパラメータ値 |
ORA-01025 ORA-01488 ORA-04000~04019 |
22024 |
未終了のC文字列 |
ORA-01479~01480 |
22025 |
無効のエスケープ・シーケンス |
ORA-01424 |
22026 |
文字列データ - 長さの不一致 |
|
22027 |
切捨てエラー |
|
23000 |
整合性制約違反 |
ORA-00001 ORA-01400 ORA-02290~02299 |
24000 |
無効なカーソル状態 |
ORA-01001~01003 ORA-01410 ORA-06511 ORA-08006 SQL-02114 SQL-02117 SQL-02118 SQL-02122 |
25000 |
無効なトランザクション状態 |
|
26000 |
無効なSQL文名 |
|
27000 |
トリガー・データの変更違反 |
|
28000 |
無効な認証指定 |
|
2A000 |
直接SQL構文エラーまたはアクセス規則違反 |
|
2B000 |
まだ存在する依存権限記述子 |
|
2C000 |
無効なキャラクタ・セット名 |
|
2D000 |
無効なトランザクション終了 |
|
2E000 |
無効な接続名 |
|
33000 |
無効なSQL記述子名 |
SQL-02138 |
34000 |
無効なカーソル名 |
|
35000 |
無効な条件番号 |
|
37000 |
動的SQL構文エラーまたはアクセス規則違反 |
|
3C000 |
あいまいなカーソル名 |
|
3D000 |
無効なカタログ名 |
|
3F000 |
無効なスキーマ名 |
|
40000 |
トランザクション・ロールバック |
ORA-02091~02092 |
40001 |
シリアライズの失敗 |
|
40002 |
整合性制約違反 |
|
40003 |
文の完了が不明 |
|
42000 |
構文エラーまたはアクセス規則違反 |
ORA-00022 ORA-00251 ORA-00900~00999 ORA-01031 ORA-01490~01493 ORA-01700~01799 ORA-01900~02099 ORA-02140~02289 ORA-02420~02424 ORA-02450~02499 ORA-03276~03299 ORA-04040~04059 ORA-04070~04099 |
44000 |
WITH_CHECKオプション違反 |
ORA-01402 |
60000 |
システム・エラー |
ORA-00370~00429 ORA-00600~00899 ORA-06430~06449 ORA-07200~07999 ORA-09700~09999 |
61000 |
リソース・エラー |
ORA-00018~00035 ORA-00050~00068 ORA-02376~02399 ORA-04020~04039 |
62000 |
共有サーバーおよび分離プロセスのエラー |
ORA-00101~00120 ORA-00440~00569 |
63000 |
Oracle*XAおよび2タスク・インタフェースのエラー |
ORA-00150~00159 SQL-02128 ORA-02700~02899 ORA-03100~03199 ORA-06200~06249 SQL-02128 |
64000 |
制御ファイル、データベース・ファイルおよびREDOファイルのエラー、アーカイブおよびメディア・リカバリのエラー |
ORA-00200~00369 ORA-01100~01250 |
65000 |
PL/SQLのエラー |
ORA-06500~06599 |
66000 |
SQL*Netドライバのエラー |
ORA-06000~06149 ORA-06250~06429 ORA-06600~06999 ORA-12100~12299 ORA-12500~12599 |
67000 |
ライセンス許可エラー |
ORA-00430~00439 |
69000 |
SQL*Connectのエラー |
ORA-00570~00599 ORA-07000~07199 |
72000 |
SQL実行フェーズのエラー |
ORA-01000~01099 ORA-01400~01489 ORA-01495~01499 ORA-01500~01699 ORA-02400~02419 ORA-02425~02449 ORA-04060~04069 ORA-08000~08190 ORA-12000~12019 ORA-12300~12499 ORA-12700~21999 |
82100 |
メモリー不足(割当て不能) |
SQL-02100 |
82101 |
無効なカーソル・キャッシュ(ユニット・カーソルとグローバル・カーソルの不一致) |
SQL-02101 |
82102 |
無効なカーソル・キャッシュ(グローバル・カーソル・エントリなし) |
SQL-02102 |
82103 |
無効なカーソル・キャッシュ(範囲外のカーソル・キャッシュ参照) |
SQL-02103 |
82104 |
無効なホスト・キャッシュ(使用可能なカーソル・キャッシュなし) |
SQL-02104 |
82105 |
無効なカーソル・キャッシュ(グローバル・カーソルなし) |
SQL-02105 |
82106 |
無効なカーソル・キャッシュ(無効なOracleカーソル番号) |
SQL-02106 |
82107 |
ランタイム・ライブラリに対して古すぎるプログラム |
SQL-02107 |
82108 |
ランタイム・ライブラリに渡された無効な記述子 |
SQL-02108 |
82109 |
無効なホスト・キャッシュ(範囲外のホスト参照) |
SQL-02109 |
82110 |
無効なホスト・キャッシュ(無効なホスト・キャッシュ・エントリの型) |
SQL-02110 |
82111 |
ヒープ一貫性エラー |
SQL-02111 |
82112 |
メッセージ・ファイルのオープン不能 |
SQL-02113 |
82113 |
コード生成の内部整合性の障害 |
SQL-02115 |
82114 |
再入可能コード・ジェネレータが与えた無効コンテキスト |
SQL-02116 |
82115 |
無効なhstdef引数 |
SQL-02119 |
82116 |
sqlrcnの第1引数および第2引数が両方NULL |
SQL-02120 |
82117 |
この接続で無効なOPENまたはPREPARE |
|
82118 |
見つからないアプリケーション・コンテキスト |
SQL-02123 |
82119 |
接続エラー(エラー・メッセージ取得不能) |
SQL-02125 |
82120 |
プリコンパイラとSQLLIBのバージョンの不一致 |
SQL-02127 |
82121 |
フェッチされたバイト数が奇数 |
SQL-02129 |
82122 |
EXEC TOOLSインタフェースが使用不可 |
SQL-02130 |
82123 |
使用中のランタイム・コンテキスト |
SQL-02131 |
82124 |
ランタイム・コンテキストの割当て不能 |
ORA-01422 SQL-02132 |
82125 |
スレッドで使用するためのプロセスの初期化不能 |
SQL-02133 |
82126 |
無効なランタイム・コンテキスト |
SQL-02134 |
90000 |
デバッグ・イベント |
ORA-10000~10999 |
99999 |
すべて補足 |
その他すべて |
HZ000 |
リモート・データベース・アクセス |
SQL通信領域(SQLCA)は、レコードに似たデータ構造体です。そのフィールドには、SQL文を実行するたびにOracleによって更新されるエラー、警告およびステータス情報が格納されます。したがって、SQLCAには常に最新のSQLの動作結果が反映されます。結果を確認するには、SQLCA内の変数をチェックします。
ローカルおよびグローバルの両方の宣言ができるホスト言語では、プログラムで複数のローカルSQLCAを使用できます。たとえば、1つのグローバルSQLCAと複数のローカルSQLCAを設定できます。ローカルSQLCAへのアクセスは、プログラム内の有効範囲により制限されます。Oracleからは、アクティブなSQLCAにのみ情報が戻されます。
また、アプリケーションでSQL*Netを使用してローカルとリモートのデータベースに同時にアクセスしている場合、すべてのデータベースが1つのSQLCAに書込みを行います。つまり、データベースごとに異なるSQLCAがあるわけではありません。詳細は、「同時接続」を参照してください。
MODE={ORACLE|ANSI13}
の場合、SQLCAは必須です。SQLCAが宣言されていないと、コンパイル時のエラーが発生します。MODE={ANSI|ANSI14}
の場合、SQLCAはオプションですが、SQLCAを宣言しないと、WHENEVER
SQLWARNING文を使用できません。そのため、WHENEVER
SQLWARNING文を使用する場合は、SQLCAを宣言する必要があります。
特定のコンパイル・ユニットでSQLCAのかわりにSQLCODEを宣言すると、プリコンパイラでは、そのユニット用に内部SQLCAを1つ割り当てます。ホスト・プログラムでは、その内部SQLCAにアクセスできません。SQLCAとSQLCODE(Pro*FORTRANのみ)を宣言すると、OracleからはSQLの動作が終わるたびに、両方に同じステータス・コードが戻されます。
MODE={ANSI|ANSI14}
の場合、SQLSTATE、SQLCODE、SQLCAのいずれかを宣言する必要があります(「SQLCODEおよびSQLSTATE」を参照)。SQLSTATE状態変数は、SQL92標準で指定されたSQLSTATE状態変数をサポートしています。SQLSTATE状態変数は、SQLCODEを指定してもしなくても使用できます。詳細は、表8-3および表8-4を参照してください。
SQLCAを宣言するには、次のようにホスト言語のソース・ファイルにEXEC SQL INCLUDE
文を使用してSQLCAを含めます。
* Include the Oracle Communications Area (ORACA). EXEC SQL INCLUDE ORACA EXEC SQL INCLUDE SQLCA;
SQLCAは、SQLCAのINCLUDE
がある場合にかぎり使用されます。
プログラムをプリコンパイルすると、INCLUDE
SQLCA文は複数の変数宣言に置換されます。この変数宣言により、Oracleはそのプログラムと通信できます。
Pro*COBOLでは、INCLUDE
が宣言部の内側であろうが外側であろうが違いはありません。Pro*COBOLでのSQLCAの宣言の詳細は、『Pro*COBOLプログラマーズ・ガイド』を参照してください。
Pro*FORTRANでは、SQLCAはCOMMONブロックなので宣言部の外側で宣言する必要があります。さらに、SQLCAはCONNECT
文と最初の実行可能なFORTRAN文の前に置く必要があります。
SQLCAは、SQL文を含むサブルーチンやファンクションごとに宣言します。サブルーチンやファンクションの1つでSQL文が実行されるたびに、OracleによりCOMMONブロック内に保存されているSQLCAが更新されます。
通常、重要なのはCOMMONリストにある変数の順序とデータ型のみで、名前ではありません。ただし、プリコンパイラではそれらの名前を参照するコードが生成されるため、SQLCA変数の名前を変更することはできません。したがって、SQLCAの宣言はすべて同一であることが必要です。Pro*FORTRANでのSQLCAの宣言の詳細は、Oracleプリコンパイラ・ガイドのPro*FORTRAN用補足資料を参照してください。
SQLCAにはSQL文の実行結果に関する次のランタイム情報が格納されます。
Oracleエラー・コード
警告フラグ
イベント情報
処理済行数
診断情報
図8-2は、SQLCA内のすべての変数を示しています。特定のホスト言語におけるSQLCA構造体および変数の名前を調べるには、このマニュアルに対するその言語用の補足資料を参照してください。
エラー・レポートは、SQLCA内の変数によって異なります。この項では、エラー・レポートの主要コンポーネントについて説明します。次の項では、SQLCAについて詳しく説明します。
すべての実行SQL文は、SQLCA変数のSQLCODEにステータス・コードを戻し、このステータス・コードは、WHENEVER
文によって暗黙的にチェックすることも、独自のコードによって明示的にチェックすることもできます。
ステータス・コードは、ゼロ、負数、正数のいずれかです。SQLCODEの詳細は、「SQLCODEの宣言」を参照してください。
警告フラグは、SQLCA変数のSQLWARN(0)からSQLWARN(7)に戻され、これらは暗黙的にも明示的にもチェックできます。警告フラグは、Oracleでエラーとみなされない実行時の状態のチェックに便利です。たとえば、DBMS=V6のとき、インジケータ変数が使用可能な場合、Oracleでは切り捨てた列値をホスト変数に割り当てると警告を通知します。(インジケータ変数が使用できない場合は、エラー・メッセージが発行されます。)
最後に実行したSQL文で処理された行数は、SQLCA変数のSQLERRD(3)に戻され、これは明示的にチェックできます。
厳密には、この変数はエラー・レポート用ではなく、誤りの防止に役立ちます。たとえば、表から約10行を削除するとします。削除後に、SQLERRD(3)をチェックすると、75行が処理されたことが判明します。念のために、削除処理をロールバックしてWHERE
句の検索条件を確認します。
SQL文は実行前に必ず解析され、構文規則に従っているか、有効なデータベース・オブジェクトを参照しているかが検証されます。エラーが検出されると、SQLCA変数のSQLERRD(5)にオフセットが格納され、これは明示的にチェックできます。このオフセットには、解析エラーの始まりを示すSQL文中の文字位置が示されています。先頭の文字の位置はゼロです。たとえば、オフセットが9のとき、解析エラーは10番目の文字から始まっています。
デフォルトでは、静的SQL文は、プリコンパイル時に構文エラーがないかチェックされます。そのため、SQLERRD(5)は、プログラムの実行時に受け入れたり作成したりする動的SQL文のデバックには最も便利です。
解析エラーは、キーワードの欠落、位置指定の誤りまたはスペルミス、無効なオプション、存在しない表などが原因で発生します。たとえば、次のような動的SQL文があるとします。
UPDATE EMP SET JIB = :job_title WHERE EMPNO = :emp_number
これは解析エラーになります。
ORA-00904: invalid column name
原因は、列名JOBのスペルミスです。SQLERRD(5)の値は15になりますが、これは誤った列名JIBが16番目の文字で始まっているためです。
SQL文に解析エラーがなければ、OracleではSQLERRD(5)がゼロに設定されます。解析エラーが先頭の文字(文字位置はゼロ)で始まっているときも、SQLERRD(5)はゼロに設定されます。したがって、SQLCODEがエラーの発生したことを意味する負数の場合のみ、SQLERRD(5)をチェックしてください。
Oracleエラーのエラー・コードおよびメッセージは、SQLCA変数のSQLERRMCに格納されています。テキストの最初の最大70文字が格納されます。70文字を超えるメッセージの全文を取得するには、SQLGLMファンクションを使用します。「エラー・メッセージの全文の取得」を参照してください。
この整数フィールドには、最後に実行されたSQL文のステータス・コードが入ります。SQLの動作結果を示すステータス・コードは、次のいずれかの数になります。
0
文が実行され、エラーも例外も検出されませんでした。
> 0
文は実行されましたが、例外が検出されました。これは、WHERE
句の検索条件を満たす行が見つからなかった場合、あるいはSELECT
INTO
またはFETCH
で行が戻されなかった場合に発生します。
< 0
MODE={ANSI|ANSI14|ANSI13}
の場合、行のINSERTがなかったときに+100がSQLCODEに戻されます。これは、副問合せで処理する行が戻されなかった場合に発生します。
データベース、システム、ネットワークまたはアプリケーションのエラーのため、Oracleでは文が実行されませんでした。このようなエラーはリカバリ不能です。これらが発生した場合、現行のトランザクションは、ほとんどの場合、ロールバックする必要があります。
負のリターン・コードに対応するエラー・コードについては、『Oracle Databaseエラー・メッセージ』を参照してください。
このサブレコードには、次の2つのフィールドがあります。
この整数フィールドには、SQLERRMCに格納されるメッセージ・テキストの長さが入ります。
この文字列フィールドには、SQLCODEに格納されているエラー・コードのメッセージ・テキストが入ります。70文字まで格納できます。70文字を超えるメッセージの全文は、SQLGLM関数を使用して取得します。
SQLERRMCを参照する前に、
SQLCODEが負数であることを確認します。SQLCODEがゼロのときにSQLERRMCを参照すると、前のSQL文に関連付けられたメッセージ・テキストを取得することになります。
この2進整数の配列には6つの要素があります。SQLERRD(FORTRANではSQLERDと呼ぶ)内のフィールドの説明は、次のとおりです。
SQLERRD(1)
このフィールドは、将来使用するために予約されています。
SQLERRD(2)
このフィールドは、将来使用するために予約されています。
SQLERRD(3)
このフィールドには、最後に実行したSQL文によって処理された行数が入ります。ただし、SQL文が失敗すると、1つの例外を除き、SQLERRD(3)の値は未定義となります。配列の動作中にエラーが発生すると、エラーの原因となった行で処理が停止し、SQLERRD(3)は正常に処理された行数を示します。
処理済行数はOPEN
文の後にゼロに設定され、FETCH
文の後で増加します。EXECUTE
、INSERT
、UPDATE
、DELETE
およびSELECT
INTO
の各文では、数は正常に処理された行数が反映されます。この数には、UPDATEやDELETE_CASCADEで処理された行は含まれません。たとえば、WHERE句の条件を満たす20行が削除され、この削除の後に列制約に違反する5行がさらに削除される場合、行数は25ではなく20です。
SQLERRD(4)
このフィールドは、将来使用するために予約されています。
このフィールドには、最後に実行されたSQL文で解析エラーが始まった文字位置を示すオフセットが入ります。先頭の文字の位置はゼロです。
SQLERRD(6)
このフィールドは、将来使用するために予約されています。
この1文字の配列には8つの要素があります。これらは警告フラグとして使用されます。Oracleではそれに文字値W(警告)を割り当てることでフラグを設定します。フラグは例外的な状況の発生を警告します。
たとえば、切り捨てられた列値が出力ホスト変数に割り当てられると、警告フラグが設定されます。
また、図8-2ではSQLWARNを配列として示していますが、Pro*COBOLでは、SQLWARN0からSQLWARN7までの基本のPIC X項目を持つグループ・アイテムとして実装されることにも注意してください。Pro*FORTRANの実装は、SQLWN0からSQLWN7までのLOGICAL変数で構成されます。
SQLWARN(0)
このフラグは、別の警告フラグが設定されている場合に設定されます。
SQLWARN(1)
このフラグは、切り捨てられた列値が出力ホスト変数に割り当てられた場合に設定されます。これは文字データに対してのみ適用されます。Oracleでは、警告を設定することも、負のSQLCODE値を戻すこともなく、特定の数値データが切り捨てられます。
列値が切り捨てられたかどうか、またどのくらい切り捨てられたかを調べるには、出力ホスト変数に関連付けられたインジケータ変数をチェックします。インジケータ変数で戻された正の整数は、列値の元の長さです。その値に応じて、ホスト変数の長さを増やすことができます。
SQLWARN(2)
このフラグは、AVG、COUNTまたはMAXなどのSQLグループ関数の評価で、1つ以上のNULLが無視された場合に設定されます。COUNT(*)を除き、すべてのグループ関数ではNULLが無視されるため、この動作になります。必要な場合は、SQL関数のNVLを使用して、NULLの列エントリに一時的に値(たとえばゼロ)を割り当てることができます。
SQLWARN(3)
このフラグは、問合せ選択リスト内の列数が、SELECT
文またはFETCH
文のINTO
句内のホスト変数の数と一致しない場合に設定されます。戻される項目の数は、両者のうち少ない方です。
SQLWARN(4)
このフラグは、表内のすべての行がWHERE句のないUPDATE
文またはDELETE
文で処理された場合に設定されます。処理される行数を制限する検索条件がない場合、更新または削除は無条件と呼ばれます。このような更新や削除は例外的であるため、この警告フラグが設定されます。必要に応じて、トランザクションはロールバックできます。
SQLWARN(5)
このフラグは、EXEC SQL CREATE {PROCEDURE|FUNCTION|PACKAGE|PACKAGE BODY}文が、PL/SQLコンパイル・エラーのために失敗したときに設定されます。
SQLWARN(6)
このフラグは現在使用されていません。
SQLWARN(7)
このフラグは現在使用されていません。
プリコンパイラ・プログラムで埋込みPL/SQLブロックを実行するときに、SQLCAのフィールドがすべて設定されるわけではありません。たとえば、ブロックで複数の行がフェッチされる場合、処理済行数SQLERRD(3)は1に設定され、実際のフェッチ行数には設定されません。したがって、PL/SQLブロックの実行後は、SQLCAのSQLCODEフィールドおよびSQLERRMフィールドのみを信頼してください。
SQLCAには最大70文字のエラー・メッセージを格納できます。それより長い(またはネストされた)エラー・メッセージの全文を取得するには、SQLGLMファンクションが必要です。Oracleに接続している場合、次の構文を使用してSQLGLMをコールできます。
SQLGLM(message_buffer, buffer_size, message_length);
パラメータは次のとおりです。
message_buffer
エラー・メッセージを格納するためのテキスト・バッファです(Oracleではこのバッファの最後まで空白文字で埋め込みます)。
buffer_size
バッファの最大サイズをバイト単位で示した整数変数です。
エラー・メッセージの実際の長さが格納される整数変数です。
Oracleエラー・メッセージの最大長は、エラー・コード、ネストされたメッセージ、表や列の名前など、メッセージの挿入部分を含めて512文字です。SQLGLMによって戻されるエラー・メッセージの最大長は、buffer_sizeに指定した値によって決まります。
次の例では、SQLGLMをコールして、100文字以内の長さのエラー・メッセージを取得します。
-- declare variables for function call msg_buffer CHARACTER(100); buf_size INTEGER; msg_length INTEGER; set buf_size = 100; EXEC SQL WHENEVER SQLERROR DO sql_error; -- other statements ROUTINE sql_error BEGIN -- get full text of error message SQLGLM(msg_buffer, buf_size, msg_length); display contents of msg_buffer; exit program with an error END sql_error;
SQLGLMは、SQLエラーが発生した場合にのみコールされます。SQLGLMをコールする前に、SQLCODEが負数であることを必ず確認してください。SQLCODEがゼロのときにSQLGLMをコールすると、前の文に関連付けられたメッセージ・テキストを取得することになります。
デフォルトでは、プリコンパイルされたプログラムはOracleエラーおよび警告の状態を無視し、可能であれば処理を続行します。自動状態チェックおよびエラー処理を実行するには、WHENEVER
文を使用します。
WHENEVER
文を使用すると、Oracleでエラー、警告または「見つかりません」の状態が検出されたときのアクションを指定できます。これらのアクションには、次の文の継続実行、ルーチンのコール、ラベル付きの文への分岐、停止などがあります。
WHENEVER
文は次の構文を使用して記述します。
EXEC SQL WHENEVER <condition> <action>;
SQLWARN(0)は、Oracleから警告(SQLWARN(1)からSQLWARN(7)までのいずれか1つも設定されます)が戻されたか、SQLCODEが+1403以外の正の値になっているために設定されます。たとえば、SQLWARN(1)は、Oraclにより切り捨てられた列値が出力ホスト変数に割り当てられた場合に設定されます。
MODE={ANSI|ANSI14}の場合、SQLCAの宣言はオプションです。ただし、WHENEVER SQLWARNINGを使用するには、SQLCAを宣言する必要があります。
OracleでWHERE
句の検索条件を満たす行を検出できなかったか、SELECT INTO
またはFETCH
で行が戻されなかったため、SQLCODEには+1403が設定されています(MODE={ANSI|ANSI14| ANSI13}
のときは+100)。MODE={ANSI|ANSI14|ANSI13}
の場合、行がINSERT
されなければ、+100がSQLCODEに戻されます。
Oracleで前述の状態のいずれかが検出されたときは、プログラムに次のいずれかのアクションを実行させることができます。
プログラムでは、制御を内部ルーチンに移します。ルーチンの最後に達すると、制御は失敗したSQL文の次の文に移ります。
ルーチンとは、COBOLパラグラフまたはFORTRAN
サブルーチンなど、起動可能な関数プログラム・ユニットです。ここでは、COBOL
のサブルーチンなど、別にコンパイルされたプログラムは、ルーチンではありません。
ルーチンの開始と終了の通常の規則が適用されます。ただし、ルーチンにパラーメータを渡すことはできません。さらに、ルーチンでは値を戻すことはできません。
パラーメータroutine_callは、次の例のように、ホスト言語を起動します。
EXEC SQL -- COBOL WHENEVER <condition> DO PERFORM <paragraph_name> -- COBOL END-EXEC. -- COBOL
または
EXEC SQL -- FORTRAN WHENEVER <condition> DO CALL <subroutine_name> -- FORTRAN
プログラムは実行を停止し、コミットされていない作業がロールバックされます。
ここでは注意が必要です。STOP
アクションでは、Oracleとの接続を切断する前に何もメッセージが表示されません。Pascalでは、同等のコマンドがないため、STOP
アクションは無効です。
たとえば、プログラムで次のアクションが必要だとします。
「データが見つかりません」という状態が発生した場合、close_cursorに進みます。
警告が発生した場合、次の文の処理を続行します。
エラーが発生した場合、error_handlerに進みます。
最初の実行SQL文の前に、次のWHENEVER
文を記述します。
EXEC SQL WHENEVER NOT FOUND GOTO close_cursor; EXEC SQL WHENEVER SQLWARNING CONTINUE; EXEC SQL WHENEVER SQLERROR GOTO error_handler;
次のPro*Cの例では、WHENEVER
...DO
文を使用して特定のエラーを処理します。
EXEC SQL WHENEVER SQLERROR DO handle_insert_error; EXEC SQL INSERT INTO EMP (EMPNO, ENAME, DEPTNO) VALUES (:emp_number, :emp_name, :dept_number); EXEC SQL WHENEVER SQLERROR DO handle_delete_error; EXEC SQL DELETE FROM DEPT WHERE DEPTNO = :dept_number; ... ROUTINE handle_insert_error; BEGIN IF sqlca.sqlcode = -1 THEN -- duplicate key value ... ELSEIF sqlca.sqlcode = -1401 THEN -- value too large ... ENDIF; ... END; ROUTINE handle_delete_error; BEGIN IF sqlca.sqlerrd(3) = 0 THEN -- no rows deleted ... ELSE ... ENDIF; ... END; ...
SQLCAの変数をチェックしてアクションの過程を決定する手順に注意してください。
WHENEVER
は宣言文であるため、その有効範囲は論理的なものではなく、位置的なものになります。それは、プログラム・ロジックの流れではなく、ソース・ファイル内で後に続くすべての実行SQL文をテストします。したがって、WHENEVER
文は、テストする最初の実行SQL文の前に記述する必要があります。
WHENEVER
文は、同じ状況をチェックする別のWHENEVER
文に置き換えられるまで有効です。
次の例では、最初のWHENEVER
SQLERROR文は2番目の文に置き換えられるため、CONNECT
文に対してのみ適用されます。2番目のWHENEVER
SQLERROR文は、step1からstep3への制御の流れに関係なく、UPDATE文とDROP文の両方に適用されます。
step1: EXEC SQL WHENEVER SQLERROR STOP; EXEC SQL CONNECT :username IDENTIFIED BY :password; ... GOTO step3; step2: EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL UPDATE EMP SET SAL = SAL * 1.10; ... step3: EXEC SQL DROP INDEX EMP_INDEX; ...
次のガイドラインは、一般的な問題を回避するために役立ちます。
文の位置。通常、WHENEVER
文はプログラムの最初の実行SQL文の前に記述してください。そうすればWHENEVER文はファイルの最後まで有効なので、発生するすべてのエラーを確実に捕捉できます。
データの終了条件の処理。カーソルを使用して行をフェッチするときは、プログラムでデータの終了条件を処理できるようにしておく必要があります。FETCH
によりデータが戻されない場合、プログラムでは次のようにCLOSE
コマンドが発行されるコードのラベル付きセクションに分岐します。
SQL WHENEVER NOT FOUND GOTO no_more; ... no_more: ... EXEC SQL CLOSE my_cursor; ...
無限ループの回避。WHENEVER
SQLERROR GOTO
文が、実行SQL文を含むエラー処理ルーチンに分岐する場合、そのSQL文にエラーが発生すると、プログラムは無限ループに陥る恐れがあります。これを回避するには、次の例のように、そのSQL文の前にWHENEVER
SQLERROR CONTINUE
を記述します。
EXEC SQL WHENEVER SQLERROR GOTO sql_error; ... sql_error: EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL ROLLBACK WORK RELEASE; ...
WHENEVER
SQLERROR CONTINUE
文を指定しなければ、ROLLBACK
エラーが発生したときにこのルーチンが再び起動され、無限ルーチンに陥ります。
WHENEVER
を不注意に使用すると、問題が発生する可能性があります。たとえば、DELETE
文で検索条件を満たす行がないためNOT
FOUND
を設定すると、次のコードは無限ループに陥ります。
-- improper use of WHENEVER ... EXEC SQL WHENEVER NOT FOUND GOTO no_more; LOOP EXEC SQL FETCH emp_cursor INTO :emp_name, :salary; ... ENDLOOP; no_more: EXEC SQL DELETE FROM EMP WHERE EMPNO = :emp_number; ...
次の例では、GOTO
のターゲットを再設定することで、NOT FOUND
の状態を適切に処理します。
-- proper use of WHENEVER ... EXEC SQL WHENEVER NOT FOUND GOTO no_more; LOOP EXEC SQL FETCH emp_cursor INTO :emp_name, :salary; ... ENDLOOP; no_more: EXEC SQL WHENEVER NOT FOUND GOTO no_match; EXEC SQL DELETE FROM EMP WHERE EMPNO = :emp_number; ... no_match: ...
アドレス指定能力の維持。ローカルおよびグローバルの識別子を使用できるホスト言語により、WHENEVER
GOTO
文に支配されるすべてのSQL文が必ずGOTO
ラベルに分岐できるようにします。次のコードでは、FUNC1内のlabelAがFUNC2内のINSERT文の有効範囲内にないため、コンパイル時エラーが発生します。
FUNC1 BEGIN EXEC SQL WHENEVER SQLERROR GOTO labelA; EXEC SQL DELETE FROM EMP WHERE DEPTNO = :dept_number; ... labelA: ... END; FUNC2 BEGIN EXEC SQL INSERT INTO EMP (JOB) VALUES (:job_title); ... END;
WHENEVER GOTO
文の分岐先のラベルは、この文と同じプリコンパイル・ファイル内にする必要があります。
エラー後の戻り。エラーの処理後にプログラムに戻る必要がある場合、DO
routine_callアクションを使用します。または、次の例のように、SQLCODEの値をテストしてもかまいません。
EXEC SQL UPDATE EMP SET SAL = SAL * 1.10; IF sqlca.sqlcode < 0 THEN -- handle error EXEC SQL DROP INDEX EMP_INDEX; ...
アクティブなWHENEVER
GOTO
文またはWHENEVER
STOP
文がないことを確認してください。
多くのプリコンパイラ・アプリケーションでは、処理中のテキスト文、その長さ、そこで指定されているSQLコマンド(INSERT
またはSELECT
など)を把握すると便利です。これは、動的SQLを使用するアプリケーションについて特に当てはまります。
ルーチンSQLGLSは、SQLLIBランタイム・ライブラリの一部で、次の情報を戻します。
最後に解析されたSQL文のテキスト
文の長さ
文で使用されているSQLコマンドの機能コード(表8-8を参照)
静的SQL文の発行後にSQLGLSをコールできます。動的SQL方法1の場合は、SQL文の実行後にSQLGLSをコールできます。動的SQL方法2、3または4の場合は、文の準備がてきたらSQLGLSをコールできます。
SQLGLS(SQLSTM, STMLEN, SQLFC)
表8-7は、SQLGLS引数リストでパラメータに使用可能なホスト言語のデータ型を示しています。
表8-7 SQLGLSパラメータのデータ型
パラメータ | Language | データ型 |
---|---|---|
COBOL |
PIC X(n) |
|
FORTRAN |
CHARACTER*n |
|
STMLEN、SQLFC |
COBOL |
PIC S9(9) COMP |
FORTRAN |
INTEGER*4 |
パラメータはすべて、参照により渡す必要があります。通常はデフォルトのパラメータを渡すのが便利です。特別なアクションは不要です。
SQLSTMパラメータは、空白埋込み(NULLで終了しない)文字バッファで、SQL文の戻されたテキストが格納されます。プログラムでは、静的にバッファを宣言するか、動的にバッファのメモリーを割り当てる必要があります。
長さのパラメータSTMLENは、4バイトの整数です。SQLGLSをコールする前に、このパラメータをSQLSTMバッファの実際のサイズ(バイト単位)に設定してください。SQLGLSが戻ると、SQLSTMバッファにはバッファ長まで空白文字が埋められたSQL文テキストが入ります。STMLENは、戻された文のテキストの実際のバイト数を戻します。これには埋め込まれた空白文字のバイト数は含まれません。ただし、STMLENは、エラーが発生した場合にはゼロを1つ戻します。
次のエラーが考えられます。
SQL文が解析されませんでした。
無効なパラメータを渡しました(たとえば、負の長さの値)。
SQLLIBで内部例外が発生しました。
SQLFCパラメータは、文のSQLコマンドのSQL機能コードを戻す4バイトの整数です。表8-8は、各SQLコマンドの機能コードを示しています。
CONNECT
COMMIT
ROLLBACK
RELEASE
FETCH
これらの文にはSQLファンクション・コードがありません。
表8-8 SQLコマンドの機能コード
コード | SQL機能 | コード | SQL機能 |
---|---|---|---|
01 |
CREATE TABLE |
39 |
AUDIT |
02 |
SET ROLE |
40 |
NOAUDIT |
03 |
INSERT |
41 |
ALTER INDEX |
04 |
SELECT |
42 |
CREATE EXTERNAL DATABASE |
05 |
UPDATE |
43 |
DROP EXTERNAL DATABASE |
06 |
DROP ROLE |
44 |
CREATE DATABASE |
07 |
DROP VIEW |
45 |
ALTER DATABASE |
08 |
DROP TABLE |
46 |
CREATE ROLLBACK SEGMENT |
09 |
DELETE |
47 |
ALTER ROLLBACK SEGMENT |
10 |
CREATE VIEW |
48 |
DROP ROLLBACK SEGMENT |
11 |
DROP USER |
49 |
CREATE TABLESPACE |
12 |
CREATE ROLE |
50 |
ALTER TABLESPACE |
13 |
CREATE SEQUENCE |
51 |
DROP TABLESPACE |
14 |
ALTER SEQUENCE |
52 |
ALTER SESSION |
15 |
(使用されていない) |
53 |
ALTER USER |
16 |
DROP SEQUENCE |
54 |
COMMIT |
17 |
CREATE SCHEMA |
55 |
ROLLBACK |
18 |
CREATE CLUSTER |
56 |
SAVEPOINT |
19 |
CREATE USER |
57 |
CREATE CONTROL FILE |
20 |
CREATE INDEX |
58 |
ALTER TRACING |
21 |
DROP INDEX |
59 |
CREATE TRIGGER |
22 |
DROP CLUSTER |
60 |
ALTER TRIGGER |
23 |
VALIDATE INDEX |
61 |
DROP TRIGGER |
24 |
CREATE PROCEDURE |
62 |
ANALYZE TABLE |
25 |
ALTER PROCEDURE |
63 |
ANALYZE INDEX |
26 |
ALTER TABLE |
64 |
ANALYZE CLUSTER |
27 |
EXPLAIN |
65 |
CREATE PROFILE |
28 |
GRANT |
66 |
DROP PROFILE |
29 |
REVOKE |
67 |
ALTER PROFILE |
30 |
CREATE SYNONYM |
68 |
DROP PROCEDURE |
31 |
DROP SYNONYM |
69 |
(使用されていない) |
32 |
ALTER SYSTEM SWITCH LOG |
70 |
ALTER RESOURCE COST |
33 |
SET TRANSACTION |
71 |
CREATE SNAPSHOT LOG |
34 |
PL/SQL EXECUTE |
72 |
ALTER SNAPSHOT LOG |
35 |
LOCK TABLE |
73 |
DROP SNAPSHOT LOG |
36 |
(使用されていない) |
74 |
CREATE SNAPSHOT |
37 |
RENAME |
75 |
ALTER SNAPSHOT |
38 |
COMMENT |
76 |
DROP SNAPSHOT |
SQLCAで標準的なSQL通信が処理されるのと同様に、Oracle通信領域(ORACA)ではOracle通信が処理されます。ランタイム・エラーおよび状態の変化について、SQLCAで提供されるより詳しい情報が必要な場合は、ORACAを使用してください。これには、豊富な診断ツールが用意されています。ただし、ORACAの使用はランタイム・オーバーヘッドを増加させるため、あくまでもオプションです。
ORACAは問題の診断に役立つ上に、プログラムによるOracleリソース(SQL文エグゼキュータやカーソル・キャッシュなど)の利用を監視できます。
ローカルおよびグローバルな宣言が可能なホスト言語では、プログラムで複数のORACAを使用できます。たとえば、1つのグローバルORACAと複数のローカルORACAを設定できます。ローカルORACAへのアクセスは、プログラム内のその有効範囲によって制限されます。Oracleでは、アクティブなORACAに対してのみ情報が戻されます。情報はコミットまたはロールバック後でなければ使用できません。
ORACAを宣言するには、次のようにホスト言語のソース・ファイルにEXEC SQL INCLUDE
文を使用してORACA含めます。
* Include the Oracle Communications Area (ORACA). EXEC SQL INCLUDE ORACA
ORACAは宣言部の外側で宣言する必要があります。
プログラムをプリコンパイルすると、INCLUDE
ORACA文は複数の変数宣言に置換されます。この変数宣言により、Oracleはそのプログラムと通信できます。
ORACAを有効にするには、コマンドラインに次のようにORACAオプションをを指定する必要があります。
ORACA=YES
またはインラインで次のように指定します。
EXEC ORACLE OPTION (ORACA=YES);
その後、ORACA内にフラグを設定することで、適切なランタイム・オプションを選択する必要があります。
ORACAには、次のように、オプションの設定、システムの統計および高度な診断情報が保存されています。
SQL文のテキスト(テキストの保存時に指定できます)
エラーが発生したファイルの名前
ファイル内のエラーの位置
カーソル・キャッシュのエラーおよび統計情報
図8-3は、ORACA内のすべての変数を示しています。特定のホスト言語におけるORACA構造体および変数の名前を調べるには、このマニュアルのその言語用の補足資料を参照してください。
ORACAにはいくつかのオプション・フラグがあります。これらのフラグにゼロ以外の値を割り当てて設定すると、次のことが可能になります。
SQL文のテキストの保存
DEBUG処理の有効化
カーソル・キャッシュの一貫性チェック(カーソル・キャッシュとは、カーソル管理に使用されるメモリーで継続的に更新される領域です)
カーソル統計情報の収集
次の説明は、必要なオプションを選択するときの参考になります。
マスターDEBUGフラグ(ORADBGF)が設定されている場合、このフラグによって、各カーソルの動作の前にカーソ・キャッシュの一貫性をチェックできます。
Oracleランタイム・ライブラリでは一貫性チェックが行われ、エラー・メッセージが発行されることがあります(エラー・メッセージについては、『Oracle Databaseエラー・メッセージ』を参照してください)。これらは、Oracleエラー・メッセージと同様にSQLCAに戻されます。
このフラグは次のいずれかの設定になります。
0
キャッシュ一貫性チェックを無効にします(デフォルト)。
1
キャッシュ一貫性チェックを有効にします。
このマスター・フラグを使用すると、DEBUGオプションをすべて選択できます。これには次の設定があります。
0
すべてのDEBUG処理を無効にします(デフォルト)。
1
すべてのDEBUG処理を有効にします。
マスターDEBUGフラグ(ORADBGF)が設定されている場合、プリコンパイラにより動的にメモリーが割り当てられたり解放されたりするたびに、このフラグがOracleランタイム・ライブラリにヒープの一貫性チェックを指示します。これは、メモリーを混乱させるプログラムの不具合を検出するのに役立ちます。
このフラグは、CONNECT
コマンドが発行される前に設定する必要があります。一度設定すると解除できなくなります。つまり、設定後の変更要求は無視されます。これには、次の設定があります。
0
ヒープ一貫性チェックを無効にします(デフォルト)。
1
ヒープ一貫性チェックを有効にします。
このフラグを使用すると、現行のSQL文のテキストをいつ保存するかを指定できます。これには、次の設定があります。
0
SQL文のテキストを保存しません(デフォルト)。
1
SQLERRORのSQL文のテキストのみを保存します。
2
SQLERRORまたはSQLWARNINGのSQL文のテキストのみを保存します。
3
常にSQL文のテキストを保存します。
SQL文のテキストは、ORASTXTという名前のORACAサブレコードに保存されます。
このサブレコードは、問題のあるSQL文を見つけるのに役立ちます。これにより、Oracleで最後に解析されたSQL文のテキストを保存できます。これには次の2つのフィールドがあります。
この整数フィールドには、現行SQL文の長さが入ります。
この文字列フィールドには、現行SQL文のテキストが入ります。先頭から最大70文字までのテキストが保存されます。
プリコンパイラによって解析された文(CONNECT
、FETCH
およびCOMMIT
など)は、ORACAには保存されません。
このサブレコードは、現行SQL文を含むファイルを識別し、1つのアプリケーションのために複数のファイルがプリコンパイルされるときのエラー検出に役立ちます。これには次の2つのフィールドがあります。
この整数フィールドには、ORASFNMCに格納されているファイル名の長さが入ります。
この文字列フィールドには、ファイル名が入ります。先頭から最大70文字が格納されます。
次の変数により、カーソル・キャッシュ統計情報を収集できます。これらは、プログラムでCOMMIT
文またはROLLBACK
文が発行されるたびに自動的に設定されます。内部的には、CONNECT
されたデータベースごとにこれらの変数のセットがあります。ORACA内の現行値は、最後にコミットまたはロールバックが実行されたデータベースに関するものです。
この整数フィールドには、プログラムの要求によってオープンされたOracleカーソルの最大数が記録されます。MAXOPENCURSORS
に設定されている値が小さすぎて、その結果プリコンパイラによってカーソル・キャッシュが拡張されると、この数はORAHOCより大きくなることがあります。
この整数フィールドには、プログラムの要求によって再度割り当てられたカーソル・キャッシュの数が記録されます。この数値は、カーソル・キャッシュのスラッシングの程度を示すもので、できるだけ小さく保つ必要があります。
この整数フィールドには、プログラムの要求によって実行されたSQL文の数が記録されます。この数値のORANPR
の数値に対する割合は、できるかぎり大きく保つ必要があります。つまり、不要な再解析は回避します。詳細は、付録C「パフォーマンス・チューニング」を参照してください。
次のプログラムでは、部門番号の入力を要求し、その部門内の各従業員の名前および給与を2つの表のいずれかに挿入してから、ORACAからの診断情報を表示します。
EXEC SQL BEGIN DECLARE SECTION; username CHARACTER(20); password CHARACTER(20); emp_name INTEGER; dept_number INTEGER; salary REAL; EXEC SQL END DECLARE SECTION; EXEC SQL INCLUDE SQLCA; EXEC SQL INCLUDE ORACA; display 'Username? '; read username; display 'Password? '; read password; EXEC SQL WHENEVER SQLERROR DO sql_error; EXEC SQL CONNECT :username IDENTIFIED BY :password; display 'Connected to Oracle'; EXEC ORACLE OPTION (ORACA=YES); -- set flags in the ORACA set oraca.oradbgf = 1; -- enable debug operations set oraca.oracchf = 1; -- enable cursor cache consistency check set oraca.orastxtf = 3; -- always save the SQL statement display 'Department number? '; read dept_number; EXEC SQL DECLARE emp_cursor CURSOR FOR SELECT ENAME, SAL + NVL(COMM,0) FROM EMP WHERE DEPTNO = :dept_number; EXEC SQL OPEN emp_cursor; EXEC SQL WHENEVER NOT FOUND DO no_more; rLOOP EXEC SQL FETCH emp_cursor INTO :emp_name, :salary; IF salary < 2500 THEN EXEC SQL INSERT INTO PAY1 VALUES (:emp_name, :salary); ELSE EXEC SQL INSERT INTO PAY2 VALUES (:emp_name, :salary); ENDIF; ENDLOOP; ROUTINE no_more BEGIN EXEC SQL CLOSE emp_cursor; EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL COMMIT WORK RELEASE; display 'Last SQL statement: ', oraca.orastxt.orastxtc; display '... at or near line number: ', oraca.oraslnr; display display ' Cursor Cache Statistics'; display '-------------------------------------------'; display 'Maximum value of MAXOPENCURSORS ', oraca.orahoc; display 'Maximum open cursors required: ', oraca.oramoc; display 'Current number of open cursors: ', oraca.oracoc; display 'Number of cache reassignments: ', oraca.oranor; display 'Number of SQL statement parses: ', oraca.oranpr; display 'Number of SQL statement executions: ', oraca.oranex; exit program; END no_more; ROUTINE sql_error BEGIN EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL ROLLBACK WORK RELEASE; display 'Last SQL statement: ', oraca.orastxt.orastxtc; display '... at or near line number: ', oraca.oraslnr; display display ' Cursor Cache Statistics'; display '-------------------------------------------'; display 'Maximum value of MAXOPENCURSORS ', oraca.orahoc; display 'Maximum open cursors required: ', oraca.oramoc; display 'Current number of open cursors: ', oraca.oracoc; display 'Number of cache reassignments: ', oraca.oranor; display 'Number of SQL statement parses: ', oraca.oranpr; display 'Number of SQL statement executions: ', oraca.oranex; exit program with an error; END sql_error;