8 エラー処理および診断
アプリケーション・プログラムでは、ランタイム・エラーを予測して、そのエラーをリカバリするように対処する必要があります。この章では、エラー・レポートおよびリカバリを詳しく説明します。具体的には、ANSI状態変数SQLCODEおよびSQLSTATE、またはOracle SQLCA (SQLコミュニケーション領域)構造を使用して警告およびエラーを処理する方法を説明します。また、WHENEVER文の使用方法と、Oracle ORACA (Oracle通信領域)構造を使用して問題を診断する方法も説明します。
次の内容について説明します。
8.1 エラー処理が必要な理由
どのようなアプリケーション・プログラムでも、その大部分をエラー処理に当てる必要があります。エラー処理の主な利点は、エラーが存在していてもプログラムの処理を続行できることです。エラーは設計ミス、コーディングの誤り、ハードウェア障害、誤ったユーザー入力をはじめ、様々な原因で発生します。
潜在的なエラーをすべて予測するのは無理ですが、プログラムにとって意味のある特定の種類のエラーについてアクションを考えることはできます。Pro*COBOLでは、エラー処理とはSQL文の実行エラーを検出してリカバリを図ることを意味します。処理を中断しないかぎり、プリコンパイラはエラーを無視して処理を続行するため、エラーは必ずトラップする必要があります。
値が切り捨てられたことを示す警告やデータの終わりなどの状態の変更も処理できます。表中の該当する行をすべて処理する前にINSERT、UPDATEまたはDELETE文が失敗する場合もあるため、各DML文の後にはエラーおよび警告の状態をチェックすることが非常に重要です。
8.2 エラー処理の代替方法
Pro*COBOLは次のような一般的なエラー処理方法をサポートしています。
-
SQLCAおよびオプションのORACAを使用したOracle固有の方法。
-
SQLSTATE状態変数を使用したSQL標準の方法。
プリコンパイラ・オプションMODEは、SQL標準に準拠するかどうかを制御します。MODE={ANSI | ANSI14}の場合、SQLSTATE状態変数をPIC X(5)として宣言します。また、ANSI SQL-89 SQLCODE状態変数も継続してサポートされていますが、これはSQL標準から除外されたため、新しいプログラムへの使用はお薦めしません。MODE={ORACLE | ANSI13}の場合は、EXEC SQL INCLUDE文を使用して必ずSQLCAを含める必要があります。1つのプログラムで2つの方法を使用することも可能ですが、通常その必要はありません。
関連項目:
方法の併用の詳細は、状態変数の組合を参照してください。8.2.1 SQLCA
SQLCAは、Oracleの警告、エラー番号およびエラーの説明を含むレコードに似たホスト言語データ構造です。Oracleは、実行SQL文またはPL/SQL文を実行するたびにSQLCAを更新します。(宣言部の後では、SQLCAの値は未定義になります。)プログラムは、SQLCAに格納されたリターン・コードをチェックして、SQL文の結果を判別できます。これには、次の2つの方法があります。
-
WHENEVER文による暗黙的なチェック
-
SQLCA変数の明示的なチェック
WHENEVER文を使用してSQL文の状態を暗黙的にチェックすると、Pro*COBOLは各実行文の後に自動的にエラー・チェック・コードを挿入します。あるいは、ユーザーが明示的にコードを記述し、SQLCA構造のSQLCODEメンバーの値をテストすることもできます。埋込みSQL INCLUDE文を使用してSQLCAを含めるには、次のようにします。
EXEC SQL INCLUDE SQLCA END-EXEC.
8.2.2 ORACA
ランタイム・エラーについてSQLCAから得られる情報が十分でない場合、ORACAを使用できます。ORACAには、カーソル統計情報、SQL文のテキスト、特定のオプション設定およびシステム統計情報が格納されます。埋込みSQL INCLUDE文を使用してORACAを含めるには、次のようにします。
EXEC SQL INCLUDE ORACA END-EXEC.
ORACAはオプションであり、MODEの設定に関係なく宣言できます。
関連項目:
ORACA状態変数の詳細は、Oracle通信領域の使用を参照してください。8.2.3 ANSI SQLSTATE変数
MODE=ANSIの場合は、宣言部にANSI SQLSTATE変数を宣言して、明示的または暗黙的なエラー・チェックを実行できます。オプションDECLARE_SECTIONをNOに設定すると、宣言部の外でも宣言できます。
8.2.4 SQLSTATEの宣言
8.2.4.1 SQLSTATEの値
SQLSTATEステータス・コードは、2文字のクラス・コードとそれに続く3文字のサブクラス・コードで構成されます。クラス・コード00は正常終了を示し、それ以外のクラス・コードは例外のカテゴリを示します。サブクラス・コード000は特定の例外を示しませんが、それ以外のサブクラス・コードはそのカテゴリの中の特定の例外を示します。たとえば、SQLSTATE値22012は、クラス・コード22 (データ例外)およびサブクラス・コード012 (ゼロによる除算)で構成されます。
SQLSTATE値の5文字は、それぞれ数字(0から9)または大文字の英文字(AからZ)で構成されます。0から4の範囲の数字、またはAからHの範囲の文字で始まるクラス・コードは、事前定義済の状態(SQL標準で定義されている)用に確保されています。他のすべてのクラス・コードは実装定義の状態用に確保されています。事前定義済のクラス内では、0から4の範囲の数字またはAからHの範囲の英文字で始まるサブクラス・コードは、事前定義済のサブコンディションを示すために確保されています。他のすべてのサブクラス・コードは実装定義のサブコンディション用に確保されています。図8-1に、コード体系を示します。
表8-1に、SQL標準によって事前定義済のクラスを示します。
表8-1 事前定義済のクラス
クラス | 条件 |
---|---|
00 |
正常終了 |
01 |
警告 |
02 |
データなし |
07 |
動的SQLエラー |
08 |
接続例外 |
09 |
トリガーされたアクションの例外 |
0A |
サポートされていない機能 |
0A |
サポートされていない機能 |
0D |
ターゲット・タイプの指定が無効 |
0E |
スキーマ名リストの指定が無効 |
0F |
ロケータの例外 |
0L |
権限付与者が無効 |
0M |
SQLが呼び出したプロシージャ参照が無効 |
0P |
ロール指定が無効 |
0S |
変換グループ名の指定が無効 |
0T |
ターゲット表がカーソル仕様と不一致 |
0U |
更新可能でない列への割当て試行 |
0V |
順序付け列への割当て試行 |
0W |
トリガー実行中の禁止された文の発生 |
0Z |
診断の例外 |
21 |
カーディナリティ違反 |
22 |
データ例外 |
23 |
整合性制約違反 |
24 |
カーソル状態が無効 |
25 |
トランザクション状態が無効 |
26 |
SQL文名が無効 |
27 |
トリガー・データの変更違反 |
28 |
認証の指定が無効 |
2A |
直接SQL構文エラーまたはアクセス規則違反 |
2B |
依存権限記述子がまだ存在しています。 |
2C |
キャラクタ・セット名が無効 |
2D |
トランザクションの終了が無効 |
2E |
接続名が無効 |
2F |
SQLルーチンの例外 |
2H |
照合名が無効 |
30 |
SQL文識別子が無効 |
33 |
SQL記述子名が無効 |
34 |
カーソル名が無効 |
35 |
状態番号が無効 |
36 |
カーソル更新検出例外 |
37 |
動的SQL構文エラーまたはアクセス規則違反 |
38 |
外部ルーチンの例外 |
39 |
外部ルーチン呼出しの例外 |
3B |
セーブポイントの例外 |
3C |
あいまいなカーソル名 |
3D |
カタログ名が無効 |
3F |
スキーマ名が無効 |
40 |
トランザクションのロールバック |
42 |
構文エラーまたはアクセス規則違反 |
44 |
WITH_CHECK_OPTION指定違反 |
HZ |
リモート・データベース・アクセス |
注意:
クラス・コードHZは、国際標準規格ISO/IEC DIS 9579-2で定義された条件であるリモート・データベース・アクセス用に確保されています。
表8-4は、OracleのエラーとSQLSTATEステータス・コードの対応を示しています。1つのステータス・コードに複数のエラーが対応する場合もあります。また、ステータス・コードに対応するエラーがない場合もあります(この場合は、表の右端の列は空白になります)。60000から99999の範囲のステータス・コードは、実装定義です。
8.3 SQLコミュニケーション領域の使用
OracleはSQLコミュニケーション領域(SQLCA)を使用して、実行時にプログラムに渡されるステータス情報を保持します。SQLCAはレコードに似たCOBOLデータ構造で、各実行SQL文の後で更新されます。そのため、常に最新のSQLの動作の結果を反映しています。そのフィールドには、SQL文を実行するたびにOracleによって更新されるエラー、警告およびステータス情報が格納されます。結果を判断するため、SQLCA内の変数を独自のCOBOLコードで明示的にチェックするか、WHENEVER文で暗黙的にチェックすることができます。
MODE={ORACLE | ANSI13}のときはSQLCAは必須です(SQLCAが宣言されていないと、コンパイル時エラーが発生します)。MODE={ANSI | ANSI14}のときはSQLCAは必須ではありませんが、SQLCAを宣言しないとWHENEVER SQLWARNING文は使用できません。マルチバイトNCHARホスト変数を使用するときにもSQLCAを含める必要があります。
注意:
アプリケーションでOracle Net Servicesを使用してローカル・データベースおよびリモート・データベースの組合せに同時にアクセスする場合、すべてのデータベースは1つのSQLCAに書き込みます。つまり、データベースごとに異なるSQLCAがあるわけではありません。詳細は、「同時ログイン」を参照してください。
8.3.1 SQLCAの内容
SQLCAには、エラー・コード、警告フラグ、イベント情報、処理済行数または診断情報など、SQL文の実行に関する実行時情報が格納されます。
図8-2に、SQLCA内のすべての変数を示します。
8.3.2 SQLCAの宣言
SQLCAを宣言するには、次に示すように、(EXEC SQL INCLUDE文を使用して) Pro*COBOLソース・ファイルの宣言部の外に組み込みます。
* Include the SQL Communications Area (SQLCA). EXEC SQL INCLUDE SQLCA END-EXEC.
SQLCAは宣言部の外で宣言する必要があります。
警告:
SQLCAが宣言されている場合は、SQLCODEを宣言しないでください。同様に、SQLCODEが宣言されている場合は、SQLCAを宣言しないでください。SQLCA構造体によって宣言される状態変数もSQLCODEという名前なので、両方のエラー・レポート・メカニズムを使用するとエラーが発生します。
プログラムをプリコンパイルすると、INCLUDE SQLCA文はいくつかの変数宣言に置き換えられます。これらの変数宣言によって、Oracleとプログラムとの間の通信が可能になります。
8.3.3 エラー・レポートの基本コンポーネント
8.3.3.4 解析エラー・オフセット
SQL文は実行前に必ず解析され、構文規則に従っているか、有効なデータベース・オブジェクトを参照しているかが検証されます。エラーが検出されると、SQLCA変数のSQLERRD(5)にオフセットが格納され、これは明示的にチェックできます。このオフセットには、解析エラーの始まりを示すSQL文中の文字位置が示されています。先頭の文字位置は0 (ゼロ)です。たとえば、オフセットが9のとき、解析エラーは10番目の文字から始まっています。
SQL文に解析エラーがない場合、SQLERRD(5)は0 (ゼロ)に設定されます。解析エラーが先頭の文字(文字位置0 (ゼロ))から始まっている場合にも、SQLERRD(5)は0 (ゼロ)に設定されます。このため、SQLERRD(5)のチェックは、SQLCODEが負の値(エラーが発生したことを示す)の場合にのみ行ってください。
8.3.3.5 エラー・メッセージ・テキスト
エラー・コードおよびメッセージは、SQLCA変数SQLERRMCに格納されます。たとえば、エラー処理ルーチンに次の文を記述します。
* Handle SQL execution errors. MOVE SQLERRMC TO ERROR-MESSAGE. DISPLAY ERROR-MESSAGE.
メッセージ・テキストの先頭から最大70文字分が格納されます。70文字を超えるメッセージについては、SQLGLMサブルーチンをコールする必要があります。SQLGLMサブルーチンの詳細は、「エラー・メッセージのテキスト全体の取得」を参照してください。
8.3.4 SQLCA構造
8.3.4.3 SQLCODE
この整数フィールドには、最後に実行されたSQL文のステータス・コードが入ります。SQLの動作の結果を示すステータス・コードは、次のいずれかの数値です。
ステータス・コード | 説明 |
---|---|
0 |
Oracleは文を実行し、エラーも例外も検出しませんでした。 |
> 0 |
Oracleは文を実行しましたが、例外を検出しました。この状態が発生するのは、WHERE句の検索条件を満たす行がない場合、あるいはSELECT INTOまたはFETCHで1行も戻されなかった場合です。 |
< 0 |
MODE={ANSI | ANSI14 | ANSI113}のときは、1行もINSERTされなかった場合にSQLCODEに+100が戻されます。副問合せで処理に行が戻されなかったときにこの状態が発生します。 データベース、システム、ネットワークまたはアプリケーションのいずれかにエラーが発生したため、Oracleは文を実行しませんでした。このようなエラーは致命的です。このようなエラーが発生すると、ほとんどの場合はカレント・トランザクションがロールバックされます。 負のリターン・コードは、『Oracle Databaseエラー・メッセージ』に記載されているエラー・コードに対応しています。 |
8.3.4.4 SQLERRM
このサブレコードには、次の2つのフィールドがあります。
SQLERRP
この文字列フィールドは、将来の使用に備えて確保されています。
8.3.4.5 SQLERRD
この2進整数の表には6つの要素があります。SQLERRDの各フィールドを説明します。
8.3.4.6 SQLWARN
この表は、それぞれ1文字からなる8つの要素で構成されています。これらの要素は警告フラグとして使用されます。Oracleでは、フラグに「W」(警告)文字値を割り当ててフラグを設定します。フラグは例外状態の発生を警告します。
たとえば、Oracleで切り捨てられた列値を出力ホスト文字変数に割り当てると、警告フラグが設定されます。
注意:
図8-2は、SQLWARN0からSQLWARN7というPIC X基本項目を持つグループ項目としてのPro*COBOLでのSQLWARN実装を示します。
SQLWARNの各フィールドを説明します。
8.3.6 エラー・メッセージのテキスト全体の取得
SQLCODEを明示的に宣言し、SQLCAを含めていない場合、MODEの設定に関係なく、SQLGLMを使用してエラー・メッセージのテキスト全体を取得できます。SQLCAには70文字までのエラー・メッセージを格納できます。これより長い(またはネストした)エラー・メッセージを取得するには、SQLGLMサブ・ルーチンが必要です。
データベースに接続すると、次の構文を使用してSQLGLMをコールできます。
CALL "SQLGLM" USING MSG-TEXT, MAX-SIZE, MSG-LENGTH
パラメータは次のとおりです。
パラメータ | データ型 | パラメータ定義 |
---|---|---|
MSG-TEXT |
PIC X(n) |
エラー・メッセージを格納するフィールド(Oracleはこのフィールドの末尾までを空白文字で埋めます。) |
MAX-SIZE |
PIC S9(9) COMP |
MSG-TEXTフィールドの最大サイズ(バイト数)を指定する整数。 |
MSG-LENGTH |
PIC S9(9) COMP |
エラー・メッセージの実際の長さを格納する整変数。 |
パラメータはすべて、参照によって渡す必要があります。通常、デフォルトでパラメータ引渡し規則は参照によって引渡されるため、特別な処置は必要ありません。
エラー・メッセージの長さは、エラー・コードおよびネストされたメッセージ、表や列の名前など、メッセージの挿入部分を入れて512文字以内です。SQLGLMによって戻されるエラー・メッセージの最大長は、MAX-SIZEに指定した値によって決まります。
次の例では、SQLGLMを使用して、エラー・メッセージの最大長を200文字に設定します。
... * Declare variables for the SQL-ERROR subroutine call. 01 MSG-TEXT PIC X(200). 01 MAX-SIZE PIC S9(9) COMP VALUE 200. 01 MSG-LENGTH PIC S9(9) COMP. ... PROCEDURE DIVISION. MAIN. EXEC SQL WHENEVER SQLERROR GOTO SQL-ERROR END-EXEC. ... SQL-ERROR. * Clear the previous message text. MOVE SPACES TO MSG-TEXT. * Get the full text of the error message. CALL "SQLGLM" USING MSG-TEXT, MAX-SIZE, MSG-LENGTH. DISPLAY MSG-TEXT.
この例では、SQLGLMはSQLエラーが発生したときのみにコールされます。SQLGLMをコールする前に、SQLCODEが負の値であることを必ず確認してください。SQLCODEが0 (ゼロ)のときにSQLGLMをコールすると、前のSQL文に対応するメッセージ・テキストが戻されます。
8.3.7 DSNTIAR
DB2には、表示可能な形式のSQLCAを取得するための、DSNTIARというアセンブラ・ルーチンがあります。DB2からOracleへ移行するユーザーのために、Pro*COBOLにもDSNTIARが用意されています。DSNTIARは、ラップを行うSQLGLMとして実装されています。DSNTIARのインタフェースは次のようになります。
CALL 'DSNTIAR' USING SQLCA MESSAGE LRECL
MESSAGEはサイズ240以上のVARCHAR形式の出力メッセージ領域で、LRECLは出力メッセージの長さ(72から240)が格納されるフル・ワードです。MESSAGE引数の最初のハーフ・ワードには、残りの領域の長さが含まれます。DSNTIARが戻すエラー・コードを次の表に示します。
表8-2 DSNTIARエラー・コードおよび説明
エラー・コード | 説明 |
---|---|
0 |
正常に実行しました |
4 |
指定されたメッセージよりも大きな領域です。 |
8 |
論理レコード長(LRECL)が72から240の範囲外です。 |
12 |
メッセージ領域の大きさが十分ではありません(240よりも大きい)。 |
8.3.8 WHENEVERディレクティブ
デフォルトでは、Pro*COBOLは可能であればエラーおよび警告状態を無視して処理を続行します。自動状態チェックおよびエラー処理を実行するにはWHENEVER文が必要です。
WHENEVER文を使用すると、Oracleがエラー、警告状態または「見つかりません」という状態を検出した場合の処置を指定できます。指定できる処置としては、次の文からの処理の続行、段落のPERFORM、段落への分岐または停止などがあります。
8.3.8.4 NOT FOUNDまたはNOTFOUND
フェッチの最後に達すると、SQLCODE値として+1403 (またはMODE={ANSI | ANSI14 | ANSI13}またはEND_OF_FETCH=100の場合は+100)が戻されます。これは、検索基準に適合するすべての行がフェッチされるか、検索基準に適合する行が1つもない場合に発生します。
END_OF_FETCHオプションを使用して、MODEマクロ・オプションで使用される値をオーバーライドできます。
END_OF_FETCH = 100 | 1403 (default 1403)
関連項目
8.3.9 WHENEVER文のコーディング
8.3.9.1 DO PERFORM
WHENEVER ... DO PERFORM文を使用するときには、段落または節に対してPERFORM文を実行する場合の通常の規則が適用されます。ただし、THRU句、TIMES句、UNTIL句またはVARYING句は使用できません。
たとえば、次のWHENEVER...DO文は無効です。
PROCEDURE DIVISION. * Invalid statement EXEC SQL WHENEVER SQLERROR DO PERFORM DISPLAY-ERROR THRU LOG-OFF END-EXEC. ... DISPLAY-ERROR. ... LOG-OFF. ...
次に示すのは、WHENEVER SQLERROR DO PERFORM文を使用して特定のエラーを処理する例です。
PROCEDURE DIVISION. MAIN SECTION. MSTART. ... EXEC SQL WHENEVER SQLERROR DO PERFORM INS-ERROR END-EXEC. EXEC SQL INSERT INTO EMP (EMPNO, ENAME, DEPTNO) VALUES (:EMP-NUMBER, :EMP-NAME, :DEPT-NUMBER) END-EXEC. EXEC SQL WHENEVER SQLERROR DO PERFORM DEL-ERROR END-EXEC. EXEC SQL DELETE FROM DEPT WHERE DEPTNO = :DEPT-NUMBER END-EXEC. ... MEXIT. STOP RUN. INS-ERROR SECTION. INSSTART. * Check for "duplicate key value" Oracle error IF SQLCA.SQLCODE = -1 ... * Check for "value too large" Oracle error ELSE IF SQLCA.SQLCODE = -1401 ... ELSE ... END-IF. ... INSEXIT. EXIT. * DEL-ERROR SECTION. DSTART. * Check for the number of rows processed. IF SQLCA.SQLERRD(3) = 0 ... ELSE ... END-IF. ... DEXIT. EXIT.
各段落でどのようにSQLCA内の変数をチェックし、実行する処理を決定しているか注意してください。
8.3.9.2 DO CALL
この句はアクション・サブプログラムをコールします。句の構文を次に示します。
EXEC SQL WHENEVER <condition> DO CALL <subprogram_name> [USING <param1> ...] END-EXEC.
次の制限または規則が適用されます。
-
USING句では、RETURNING、ON_EXCEPTIONまたはOVER_FLOW句は使用できません。
-
COBOLソース・コードのPROGRAM-ID文で、キーワードCOMMONの前にサブプログラム名を入力することが必要な場合があります。
-
アクション・サブプログラムではWHENEVER CONTINUE文を使用する必要があります。
-
WHENEVERディレクティブのDO CALL句では、アクション・サブプログラム名を二重引用符で囲むことが必要な場合があります。
次に示す例は、サブプログラムLOGONまたはMAINプログラムからエラー・サブプログラムSQL-ERRORをコールするプログラムの例です。DO PERFORM句を使用したときと同様、2つの位置でコードが繰り返されることはありません。
IDENTIFICATION DIVISION. PROGRAM-ID. MAIN. ENVIRONMENT DIVISION. ... PROCEDURE DIVISION. BEGIN-PGM. EXEC SQL WHENEVER SQLERROR DO CALL "SQL-ERROR" END-EXEC. CALL "LOGON". ... IDENTIFICATION DIVISION. PROGRAM-ID. LOGON. DATA DIVISION. WORKING-STORAGE SECTION. 01 USERNAME PIC X(15) VARYING. 01 PASSWD PIC X(15) VARYING. PROCEDURE DIVISION. MOVE "SCOTT" TO USERNAME-ARR. MOVE 5 TO USERNAME-LEN. MOVE "TIGER" TO PASSWD-ARR. MOVE 5 TO PASSWD-LEN. EXEC SQL CONNECT :USERNAME IDENTIFIED BY :PASSWD END-EXEC. DISPLAY " ". DISPLAY "CONNECTED TO ORACLE AS USER: ", USERNAME-ARR. END PROGRAM LOGON. ... IDENTIFICATION DIVISION. PROGRAM-ID. SQL-ERROR COMMON. PROCEDURE DIVISION. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. DISPLAY " ". DISPLAY SQLERRMC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. END PROGRAM SQL-ERROR. END PROGRAM MAIN.
8.3.9.3 スコープ
WHENEVER文は宣言部のため、そのスコープは論理的なものではなく位置的なものになります。テストするのは、ソース・ファイルの中でその文より後に記述されているすべての実行SQL文であり、プログラム・ロジックの流れの中でその文より後にくる実行SQL文ではありません。したがってWHENEVER文は、テストする最初の実行SQL文の前に指定する必要があります。
WHENEVER文は、同じ条件をチェックする別のWHENEVER文に置き換えられるまで有効です。
提案: SQL文を含む各プログラム・ユニットの先頭にWHENEVER文を記述してください。このようにすると、あるプログラム・ユニット内のSQL文が別のプログラム・ユニット内のWHENEVERの処置を参照して、コンパイル時や実行時に発生するエラーを回避できます。
8.3.9.4 不注意な使用: 例
WHENEVER文を不注意に使用すると、問題が発生することがあります。たとえば、次のコードは、検索条件を満たす行がないため、DELETE文でNOT FOUND状態を設定すると無限ループに陥ります。
* Improper use of WHENEVER. EXEC SQL WHENEVER NOT FOUND GOTO NO-MORE END-EXEC. PERFORM GET-ROWS UNTIL DONE = "YES". ... GET-ROWS. EXEC SQL FETCH emp_cursor INTO :EMP-NAME, :SALARY END-EXEC. ... NO-MORE. MOVE "YES" TO DONE. EXEC SQL DELETE FROM EMP WHERE EMPNO = :EMP-NUMBER END-EXEC. ...
次の例では、GOTOのターゲットを設定しなおすことによってNOT FOUND状態を適切に処理しています。
* Proper use of WHENEVER. EXEC SQL WHENEVER NOT FOUND GOTO NO-MORE END-EXEC. PERFORM GET-ROWS UNTIL DONE = "YES". ... GET-ROWS. EXEC SQL FETCH emp_cursor INTO :EMP-NAME, :SALARY END-EXEC. ... NO-MORE. MOVE "YES" TO DONE. EXEC SQL WHENEVER NOT FOUND GOTO NONE-FOUND END-EXEC. EXEC SQL DELETE FROM EMP WHERE EMPNO = :EMP-NUMBER END-EXEC. ... NONE-FOUND. ...
8.3.10 SQL文のテキストの取得
多くのPro*COBOLアプリケーションでは、処理している文のテキスト、長さおよびその文に記述されているSQLコマンド(INSERTやSELECTなど)がわかると便利です。これは、動的SQLを使用するアプリケーションでは特に重要です。
ルーチンSQLGLSを使用すると、次の情報が戻されます(このルーチンはSQLLIBランタイム・ライブラリに入っています)。
-
最後に解析されたSQL文のテキスト
-
その文の長さ
-
関数コード
SQLGLSは、静的SQL文の発行後にコールできます。動的SQL方法1では、SQL文の実行後にSQLGLSをコールできます。動的SQL方法2、3または4では、SQL文の作成後にSQLGLSをコールできます。
CALL "SQLGLS" USING SQLSTM STMLEN SQLFC.
表8-3に、SQLGLS引数リストのパラメータに使用可能なホスト言語のデータ型を示します。
表8-3 パラメータのデータ型
パラメータ | データ型 |
---|---|
SQLSTM |
PIC X(n) |
STMLEN |
PIC S9(9) COMP |
SQLFC |
PIC S9(9) COMP |
パラメータはすべて、参照によって渡す必要があります。通常、デフォルトでパラメータ引渡し規則は参照によって引渡されるため、特別な処置は必要ありません。
パラメータSQLSTMは、SQL文の戻されたテキストを保持する空白埋め(ヌル文字で終了しない)文字バッファです。プログラムでは、このバッファを静的に宣言するか、このバッファに動的にメモリーを割り当てる必要があります。
長さパラメータSTMLENは4バイトの整数です。SQLGLSをコールする前に、このパラメータをSQLSTMバッファの実際のサイズ(単位はバイト)に設定します。SQLGLSが戻すときに、SQLSTMバッファには、SQL文のテキストにバッファの長さまで空白を足したものが含まれます。STMLENは戻された文テキストの実際のバイト数を戻します。足されている空白は数えません。ただし、エラーが発生した場合、STMLENはゼロを戻します。
-
SQL文が1つも解析されませんでした。
-
無効なパラメータを渡しました(たとえば、長さとして負の値を渡した場合)。
-
SQLLIBで内部例外が発生しました。
パラメータSQLFCは、文中のSQLコマンドに対応するSQLファンクション・コードを戻す4バイトの整数です。SQLコマンドの関数コードの詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』の表を参照してください。
次の文には、対応するSQLファンクション・コードはありません。
-
CONNECT
-
COMMIT
-
FETCH
-
ROLLBACK
-
RELEASE
8.4 Oracle通信領域の使用
SQLCAは、標準SQLの通信を対象としています。Oracle通信領域(ORACA)もSQLCAと同様の構造ですが、ORACAをプログラムに組み込むとOracle固有の通信を処理できるようになります。SQLCAで提供される情報よりも詳しい実行時情報が必要な場合に、ORACAを使用してください。
ORACAは、問題の診断に役立つのみでなく、SQL文エグゼキュータやカーソル・キャッシュ(カーソル管理のために確保されているメモリー領域)などのリソースをプログラムがどのように使用しているかを監視する場合にも使用できます。
8.4.5 ORACA構造
8.4.5.3 ORACCHF
マスターDEBUGフラグ(ORADBGF)が設定されているときにこのフラグを設定すると、カーソル操作のたびにカーソル・キャッシュの一貫性をあらかじめチェックできます。
ランタイム・ライブラリでは一貫性チェックが行われ、エラー・メッセージが出力される場合もあります。エラー・メッセージのリストは、『Oracle Databaseエラー・メッセージ』を参照してください。
このフラグは次のいずれかを設定します。
設定 | 説明 |
---|---|
0 |
キャッシュ一貫性チェックを使用禁止にします(デフォルト)。 |
1 |
キャッシュ一貫性チェックを使用可能にします。 |
8.4.5.5 ORAHCHF
マスターDEBUGフラグ(ORADBGF)が設定されているときにこのフラグを設定すると、Pro*COBOLが動的にメモリーの割当てや解放を行うたびにランタイム・ライブラリを使用してヒープの一貫性をチェックできます。これはメモリー障害を起こすプログラムの不具合を検出するのに役立ちます。
このフラグはCONNECTコマンドを発行する前に設定する必要があります。また、このフラグは一度設定すると解除できなくなります。つまり、設定後にこのフラグの変更要求があっても無視されます。このフラグには次のいずれかを設定します。
設定 | 説明 |
---|---|
0 |
ヒープの一貫性チェックを使用可能にします(デフォルト)。 |
1 |
ヒープの一貫性チェックを使用禁止にします。 |
8.4.6 ORACAのサンプル・プログラム
次のプログラムは、部門番号の入力を要求し、その部門に所属している各従業員の名前と給与を2つの表のいずれかに挿入して、ORACAからの診断情報を表示します。
IDENTIFICATION DIVISION. PROGRAM-ID. ORACAEX. ENVIRONMENT DIVISION. DATA DIVISION. WORKING-STORAGE SECTION. EXEC SQL INCLUDE SQLCA END-EXEC. EXEC SQL INCLUDE ORACA END-EXEC. EXEC ORACLE OPTION (ORACA=YES) END-EXEC. EXEC SQL BEGIN DECLARE SECTION END-EXEC. 01 USERNAME PIC X(20). 01 PASSWORD PIC X(20). 01 EMP-NAME PIC X(10) VARYING. 01 DEPT-NUMBER PIC S9(4) COMP. 01 SALARY PIC S9(6)V99 DISPLAY SIGN LEADING SEPARATE. EXEC SQL END DECLARE SECTION END-EXEC. PROCEDURE DIVISION. DISPLAY "Username? " WITH NO ADVANCING. ACCEPT USERNAME. DISPLAY "Password? " WITH NO ADVANCING. ACCEPT PASSWORD. EXEC SQL WHENEVER SQLERROR GOTO SQL-ERROR END-EXEC. EXEC SQL CONNECT :USERNAME IDENTIFIED BY :PASSWORD END-EXEC. DISPLAY "Connected to Oracle". * -- set flags in the ORACA * -- enable debug operations MOVE 1 TO ORADBGF. * -- enable cursor cache consistency check MOVE 1 TO ORACCHF. * -- always save the SQL statement MOVE 3 TO ORASTXTF. DISPLAY "Department number? " WITH NO ADVANCING. ACCEPT DEPT-NUMBER. EXEC SQL DECLARE EMPCURSOR CURSOR FOR SELECT ENAME, SAL + NVL(COMM,0) FROM EMP WHERE DEPTNO = :DEPT-NUMBER END-EXEC. EXEC SQL OPEN EMPCURSOR END-EXEC. EXEC SQL WHENEVER NOT FOUND GOTO NO-MORE END-EXEC. LOOP. EXEC SQL FETCH EMPCURSOR INTO :EMP-NAME, :SALARY END-EXEC. IF SALARY < 2500 EXEC SQL INSERT INTO PAY1 VALUES (:EMP-NAME, :SALARY) END-EXEC ELSE EXEC SQL INSERT INTO PAY2 VALUES (:EMP-NAME, :SALARY) END-EXEC END-IF. GO TO LOOP. NO-MORE. EXEC SQL CLOSE EMPCURSOR END-EXEC. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. EXEC SQL COMMIT WORK RELEASE END-EXEC. DISPLAY "(NO-MORE.) Last SQL statement: ", ORASTXTC. DISPLAY "... at or near line number: ", ORASLNR. DISPLAY " ". DISPLAY " Cursor Cache Statistics". DISPLAY "-------------------------------------------". DISPLAY "Maximum value of MAXOPENCURSORS ", ORAHOC. DISPLAY "Maximum open cursors required: ", ORAMOC. DISPLAY "Current number of open cursors: ", ORACOC. DISPLAY "Number of cache reassignments: ", ORANOR. DISPLAY "Number of SQL statement parses: ", ORANPR. DISPLAY "Number of SQL statement executions: ", ORANEX. STOP RUN. SQL-ERROR. EXEC SQL WHENEVER SQLERROR CONTINUE END-EXEC. EXEC SQL ROLLBACK WORK RELEASE END-EXEC. DISPLAY "(SQL-ERROR.) Last SQL statement: ", ORASTXTC. DISPLAY "... at or near line number: ", ORASLNR. DISPLAY " ". DISPLAY " Cursor Cache Statistics". DISPLAY "-------------------------------------------". DISPLAY "MAXIMUM VALUE OF MAXOPENCURSORS ", ORAHOC. DISPLAY "Maximum open cursors required: ", ORAMOC. DISPLAY "Current number of open cursors: ", ORACOC. DISPLAY "Number of cache reassignments: ", ORANOR. DISPLAY "Number of SQL statement parses: ", ORANPR. DISPLAY "Number of SQL statement executions: ", ORANEX. STOP RUN.
8.5 エラーとSQLSTATEコードの対応関係
SQLSTATEのコード、その意味および戻されるエラーを次の表に示します。
表8-4 SQLSTATEコード
コード | 条件 | Oracleエラー |
---|---|---|
00000 |
正常終了 |
ORA-00000 |
01000 |
警告 |
|
01001 |
カーソル操作の競合 |
|
01002 |
切断エラー |
|
01003 |
集合関数でのNULL値が排除 |
|
01004 |
文字列データの右側切捨て |
|
01005 |
項目記述子領域が不十分 |
|
01006 |
権限が取り消されていません |
|
01007 |
権限が付与されていません |
|
01008 |
暗黙的ゼロビットの埋込み |
|
01009 |
情報スキーマの検索条件が長すぎます。 |
|
0100A |
情報スキーマの問合せ式が長すぎます。 |
|
02000 |
データなし |
ORA-01095 ORA-01403 |
07000 |
動的SQLエラー |
|
07001 |
USING句がパラメータ指定と一致しません。 |
|
07002 |
USING句が相手指定と一致しません。 |
|
07003 |
カーソル仕様を実行できません。 |
|
07004 |
動的パラメータにはUSING句が必要です。 |
|
07005 |
プリコンパイルされたSQL文がカーソル仕様ではありません。 |
|
07006 |
制限付きのデータ型属性違反 |
|
07007 |
結果フィールドにはUSING句が必要です。 |
|
07008 |
記述子の数が無効 |
SQL-02126 |
07009 |
記述子の索引が無効 |
|
08000 |
接続例外 |
|
08001 |
SQLのクライアントがSQL接続を確立できません。 |
|
08002 |
接続名の重複 |
|
08003 |
接続が存在しません。 |
SQL-02121 |
08004 |
SQLサーバーによるSQL接続の拒絶 |
|
08006 |
接続の失敗 |
|
08007 |
トランザクション解決が不明 |
|
0A000 |
サポートされていない機能 |
ORA-03000から03099 |
0A001 |
複数のサーバー・トランザクション |
|
21000 |
カーディナリティ違反 |
ORA-01427 SQL-02112 |
22000 |
データ例外 |
|
22001 |
文字列データの右側切捨て |
ORA-01401 ORA-01406 |
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-1400、ORA-00001 ORA-02290から02299 |
24000 |
カーソル状態が無効 |
ORA-01001から01003 ORA-01410 ORA-08006 SQL-02114 SQL-02117 SQL-02118 SQL-02122 |
25000 |
トランザクション状態が無効 |
|
26000 |
SQL文名が無効 |
|
27000 |
トリガー・データの変更違反 |
|
28000 |
認証の指定が無効 |
|
2A000 |
直接SQL構文エラーまたはアクセス規則違反 |
|
2B000 |
依存権限記述子がまだ存在しています。 |
|
2C000 |
キャラクタ・セット名が無効 |
|
2D000 |
トランザクションの終了が無効 |
|
2E000 |
接続名が無効 |
|
33000 |
SQL記述子名が無効 |
|
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_OPTION指定違反 |
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-00100から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 |
Oracle Net Servicesドライバのエラー |
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-01401から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 |
無効なカーソル・キャッシュです。カーソル番号が無効です。 |
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が無効です。 |
SQL-02122 |
82118 |
アプリケーション・コンテキストが見つかりません。 |
SQL-02123 |
82119 |
接続エラーでメッセージを取り出せません。 |
SQL-02125 |
82120 |
プリコンパイラとSQLLIBのバージョンが一致しません。 |
SQL-02127 |
82121 |
FETCHされたバイト数が奇数です。 |
SQL-02129 |
82122 |
EXEC TOOLSインタフェースが使用できません。 |
SQL-02130 |
82123 |
ランタイム・コンテキストは使用中です。 |
SQL-02131 |
82124 |
ランタイム・コンテキストを割り当てできません。 |
SQL-02131 |
82125 |
スレッドで使用するプロセスを初期化できません。 |
SQL-02133 |
82126 |
ランタイム・コンテキストが無効 |
SQL-02134 |
90000 |
デバッグ・イベント |
ORA-10000から10999 |
99999 |
すべて捕捉 |
その他すべて |
HZ000 |
リモート・データベース・アクセス |
8.5.1 状態変数の組合せ
MODE={ANSI | ANSI14}のときは、状態変数の動作は次の設定によって変わります。
-
宣言されている変数。
-
宣言の配置(宣言部の内部または外部)。
-
ASSUME_SQLCODEの設定。
表8-5および表8-6に、ASSUME_SQLCODE=NOおよびASSUME_SQLCODE=YESのときの各状態変数の組合せの動作結果をそれぞれ示します。
両方の表には次のことが適用されます。DECLARE_SECTION=NOの場合は、状態変数の宣言はすべて(宣言部の)内部にあるものとして扱われます。
ASSUME_SQLCODE=YESは、DECLARE_SECTION=NOと併用しないでください。
表8-5 ASSUME_SQLCODE=NO、MODE=ANSI | ANSI1、DECLARE_SECTION=YESのときの状態変数の動作
SQLCODE | SQLSTATE | SQLCA | 動作 |
---|---|---|---|
外 |
— |
— |
SQLCODEが宣言され、状態変数であるとみなされます。 |
外 |
— |
外 |
この状態変数の構成はサポートされていません。 |
外 |
— |
内 |
この状態変数の構成はサポートされていません。 |
外 |
外 |
— |
SQLCODEが宣言され、状態変数とみなされます。SQLSTATEは宣言されますが、状態変数とは認識されません。 |
外 |
外 |
外 |
この状態変数の構成はサポートされていません。 |
外 |
外 |
内 |
この状態変数の構成はサポートされていません。 |
外 |
内 |
— |
SQLSTATEが状態変数として宣言されます。SQLCODEは宣言されますが、状態変数とは認識されません。 |
外 |
内 |
外 |
この状態変数の構成はサポートされていません。 |
外 |
内 |
内 |
この状態変数の構成はサポートされていません。 |
内 |
— |
— |
SQLCODEが状態変数として宣言されます。 |
内 |
— |
外 |
この状態変数の構成はサポートされていません。 |
内 |
— |
内 |
この状態変数の構成はサポートされていません。 |
内 |
外 |
— |
SQLCODEが状態変数として宣言されます。SQLSTATEは宣言されますが、状態変数とは認識されません。 |
内 |
外 |
外 |
この状態変数の構成はサポートされていません。 |
内 |
外 |
内 |
この状態変数の構成はサポートされていません。 |
内 |
内 |
— |
SQLCODEおよびSQLSTATEが状態変数として宣言されます。 |
内 |
内 |
外 |
この状態変数の構成はサポートされていません。 |
内 |
内 |
内 |
この状態変数の構成はサポートされていません。 |
— |
— |
— |
この状態変数の構成はサポートされていません。 |
— |
— |
外 |
SQLCAが状態変数として宣言されます。 |
— |
— |
内 |
SQLCAが状態ホスト変数として宣言されます。 |
— |
外 |
— |
この状態変数の構成はサポートされていません。 |
— |
外 |
外 |
SQLCAが状態変数として宣言されます。SQLSTATEは宣言されますが、状態変数とは認識されません。 |
— |
外 |
内 |
SQLCAが状態ホスト変数として宣言されます。SQLSTATEは宣言されますが、状態変数とは認識されません。 |
— |
内 |
— |
SQLSTATEが状態変数として宣言されます。 |
— |
内 |
外 |
SQLSTATEおよびSQLCAが状態変数として宣言されます。 |
— |
内 |
内 |
SQLSTATEおよびSQLCAが状態ホスト変数として宣言されます。 |
表8-6 ASSUME_SQLCODE=YES、MODE=ANSI | ANSI14、DECLARE_SECTION=YESのときの状態変数の動作
SQLCODE | SQLSTATE | SQLCA | 動作 |
---|---|---|---|
外 |
— |
— |
SQLCODEが宣言され、状態変数であるとみなされます。 |
外 |
— |
外 |
この状態変数の構成はサポートされていません。 |
外 |
— |
内 |
この状態変数の構成はサポートされていません。 |
外 |
外 |
— |
SQLCODEが宣言され、状態変数とみなされます。SQLSTATEは宣言されますが、状態変数とは認識されません。 |
外 |
外 |
外 |
この状態変数の構成はサポートされていません。 |
外 |
外 |
内 |
この状態変数の構成はサポートされていません。 |
外 |
内 |
— |
SQLSTATEが状態変数として宣言されます。SQLCODEは宣言されますが、状態変数とはみなされません。 |
外 |
内 |
外 |
この状態変数の構成はサポートされていません。 |
外 |
内 |
内 |
この状態変数の構成はサポートされていません。 |
内 |
— |
— |
SQLCODEが状態変数として宣言されます。 |
内 |
— |
外 |
この状態変数の構成はサポートされていません。 |
内 |
— |
内 |
この状態変数の構成はサポートされていません。 |
内 |
外 |
— |
SQLCODEが状態変数として宣言されます。SQLSTATEは宣言されますが、状態変数とは認識されません。 |
内 |
外 |
外 |
この状態変数の構成はサポートされていません。 |
内 |
外 |
内 |
この状態変数の構成はサポートされていません。 |
内 |
内 |
— |
SQLCODEおよびSQLSTATEが状態変数として宣言されます。 |
内 |
内 |
外 |
この状態変数の構成はサポートされていません。 |
内 |
内 |
内 |
この状態変数の構成はサポートされていません。 |
— — — — — — — — — |
— — — 外 外 外 内 内 内 |
— 外 内 — 外 内 — 外 内 |
これらの状態変数の構成はサポートされていません。ASSUME_SQLCODE=YESのときは、SQLCODEを宣言する必要があります。 |