問合せで複数行を戻す場合、明示的にカーソルを定義して次の処理を行うことができます。
問合せによって戻された最初の行以後の処理
現在どの行が処理されているかの追跡および記録
ホスト配列を使用することもできます。
関連項目:
カーソルは、問合せによって戻された行の集合内におけるカレント行を示します。これによって、プログラムは一度に1行ずつ処理できます。次の文を使用してカーソルを定義および操作します。
DECLARE CURSOR
OPEN
FETCH
CLOSE
まず、DECLARE CURSOR文を使用して、カーソルに名前を付け、問合せに関連付けます。
OPEN文によって問合せが実行され、この問合せの検索条件を満たす行がすべて判別されます。これらの行は、カーソルのアクティブ・セットと呼ばれる集合を形成します。カーソルをOPENした後、対応する問合せによって戻された行を取り出すことができます。
アクティブ・セットの行は1行ずつ取り出されます(ホスト配列を使用していない場合)。FETCH文を使用してアクティブ・セット内のカレント行を取り出します。FETCHは、すべての行が取り出されるまで繰返し実行できます。
アクティブ・セットからの行のFETCHが終了した後、CLOSE文によってカーソルを使用禁止にします(アクティブ・セットは未定義になります)。
以降の項では、アプリケーション・プログラム内でのこれらのカーソル制御文の使用方法について説明します。
次の例のように、DECLARE CURSOR文を使用して、カーソルに名前を付け、問合せに関連付けることで、カーソルを定義できます。
EXEC SQL DECLARE emp_cursor CURSOR FOR SELECT ename, empno, sal FROM emp WHERE deptno = :dept_number;
カーソル名は、ホスト変数やプログラム変数ではなく、プリコンパイラで使用される識別子であるため、宣言部では定義しないでください。したがって、あるプリコンパイル単位から別のプリコンパイル・ユニットにカーソル名を渡すことはできません。カーソル名にハイフンは使用できません。長さは任意ですが、重要な意味があるのは先頭の31文字までです。ANSI互換性を維持するため、カーソル名は18文字までにしてください。
コマンドラインまたは構成ファイルでプリコンパイラ・オプションCLOSE_ON_COMMITが使用できます。CLOSE_ON_COMMIT=YESに設定すると、WITH HOLD句なしで宣言されたカーソルはすべてCOMMITまたはROLLBACKの後でクローズされます。詳細は、DECLARE CURSOR文でのWITH HOLD句の使用およびCLOSE_ON_COMMITを参照してください。
CLOSE_ON_COMMITより高いレベルでMODEが指定されていると、MODEが優先されます。デフォルトはMODE=ORACLEおよびCLOSE_ON_COMMIT=NOです。MODE=ANSIと指定した場合は、WITH HOLD句を使用していないカーソルはCOMMIT時にクローズされます。カーソルのクローズおよび再オープンの回数が多くなるため、アプリケーションの動作は遅くなります。MODE=ANSIのときは、CLOSE_ON_COMMIT=NOと設定するとパフォーマンスが向上します。MODEなどのマクロ・オプションがCLOSE_ON_COMMITなどのマイクロ・オプションに与える影響は、オプション値の優先順位を参照してください。
カーソルに関連付けられたSELECT文にINTO句を含めることはできません。INTO句および出力ホスト変数のリストはFETCH文の一部として指定します。
DECLARE CURSOR文は宣言部なので、そのカーソルを参照する他のすべてのSQL文よりも物理的に(論理的にというだけでなく)前にあることが必要です。つまり、カーソルの前方参照は許可されていません。次の例では、OPEN文の位置が誤っています。
... EXEC SQL OPEN emp_cursor; * -- MISPLACED OPEN STATEMENT EXEC SQL DECLARE emp_cursor CURSOR FOR SELECT ename, empno, sal FROM emp WHERE ename = :emp_name;
カーソル制御文(DECLARE、OPEN、FETCH、CLOSE)はすべて同一のプリコンパイル・ユニット内で指定する必要があります。たとえば、ファイルAの中でカーソルをDECLAREしてファイルBでOPENすることはできません。
ホスト・プログラムでは、カーソルを必要な数だけDECLAREできます。ただし、指定されたファイル内ではそれぞれのDECLARE文は一意であることが必要です。つまり、カーソルの適用範囲は1つのファイル全体に及ぶため、1つのプリコンパイル・ユニット内には、たとえ別のブロックやプロシージャ内であっても、同じ名前のカーソルを2つDECLAREすることはできません。
MODE=ANSIまたはCLOSE_ON_COMMIT=YESを使用する場合は、DECLAREセクションにWITH HOLD句を使用して、2つのオプションで定義される動作をオーバーライドできます。これらのオプションを設定すると、COMMITが発行されたときにすべてのカーソルがクローズされます。この場合、処理を続行するのにカーソルを再びオープンする必要があるため、オーバーヘッドが生じてパフォーマンスが低下します。WITH HOLD句を適切に使用して処理を高速化するには、プリコンパイラがANSI規格に適合しているプログラムであることが必要です。
多数のカーソルを使用する場合は、MAXOPENCURSORSオプションの指定が必要になることがあります。
関連項目:
OPEN文を使用すると、問合せを実行してアクティブ・セットを決定できます。次の例では、emp_cursorという名前のカーソル変数をOPENします。
EXEC SQL OPEN emp_cursor;
OPENでは、SQLCA内のSQLERRDの第3要素に保存されている処理済行数が0(ゼロ)に設定されます。ただし、この時点ではアプリケーションから参照できる行はありません。これはFETCH文で処理されます。
OPENによって、カーソルはアクティブ・セットの最初の行の直前に位置付けられます。また、SQLCA内のSQLERRDの第3要素に保存されている処理済行数が0(ゼロ)に設定されます。ただし、この時点では実際に取り出される行はありません。行の取出しはFETCH文によって行われます。
カーソルをOPENすると、問合せの入力ホスト変数はカーソルを再度OPENするまで再検査されません。つまり、アクティブ・セットは変更されません。アクティブ・セットを変更するには、カーソルを再OPENします。
通常、カーソルは再OPENする前にCLOSEする必要があります。ただし、MODE=ORACLE(デフォルト)を指定すると、カーソルを再度OPENする前にCLOSEする必要はありません。これによりパフォーマンスが向上する場合があります。
OPENによって行われる作業量は、HOLD_CURSOR、RELEASE_CURSORおよびMAXOPENCURSORSの3つのプリコンパイラ・オプションの値によって決まります。
FETCH文を使用すると、アクティブ・セットから行を取り出し、結果を格納する出力ホスト変数を指定できます。カーソルに関連付けられたSELECT文にはINTO句を組み込めないことを思い出してください。INTO句および出力ホスト変数のリストはFETCH文の一部として指定します。次の例では、フェッチした行を3つのホスト変数に対してFETCH INTOを実行します。
EXEC SQL FETCH emp_cursor INTO :emp_name, :emp_number, :salary;
カーソルは、あらかじめDECLAREおよびOPENしておく必要があります。最初にFETCH文を実行すると、アクティブ・セットの最初の行より前にあるカーソルが最初の行に移動します。この行がカレント行になります。その後FETCHを実行するたびに、カレント行を変更しながら、カーソルをアクティブ・セットの次の行に進めます。カーソルはアクティブ・セット内を順方向にしか進みません。すでにFETCHを完了した行に戻るには、このカーソルを再OPENして、その後このアクティブ・セットの最初の行からもう一度始めます。
アクティブ・セットを変更する場合は、カーソルに対応する問合せの入力ホスト変数に新しい値を割り当て、カーソルを再OPENしてください。MODE=ANSIに設定されている場合は、再OPENする前にカーソルをCLOSEする必要があります。
次の例のように、異なるホスト変数のセットを使用して、同じカーソルからFETCHできます。しかし、各FETCH文のINTO句内の対応するホスト変数は、同じデータ型であることが必要です。
EXEC SQL DECLARE emp_cursor CURSOR FOR SELECT ename, sal FROM emp WHERE deptno = 20; ... EXEC SQL OPEN emp_cursor; EXEC SQL WHENEVER NOT FOUND GOTO ... for (;;) { EXEC SQL FETCH emp_cursor INTO :emp_name1, :salary1; EXEC SQL FETCH emp_cursor INTO :emp_name2, :salary2; EXEC SQL FETCH emp_cursor INTO :emp_name3, :salary3; ... }
アクティブ・セットが空か、それ以上の行を含んでいない場合、FETCHによって「データが見つかりません。」というエラー・コードがSQLCAのsqlcode、またはSQLCODEまたはSQLSTATE状態変数に戻されます。出力ホスト変数のステータスは不確定です。(通常のプログラムでは、WHENEVER NOT FOUND文でこのエラーが検出されます。)カーソルを再利用するには、カーソルを再OPENします。
次の場合、カーソル上でのFETCHはエラーになります。
カーソルをOPENする前
「データが見つかりません。」条件の後
それをCLOSEした後
アクティブ・セットからの行のFETCHが終了したら、カーソルをCLOSEし、カーソルのOPENによって確保していたリソース(記憶域など)を解放します。カーソルがクローズされると、解析ロックが解放されます。どのリソースが解放されるかは、HOLD_CURSORオプションおよびRELEASE_CURSORオプションの指定によって異なります。次の例では、emp_cursorという名前のカーソルをCLOSEします。
EXEC SQL CLOSE emp_cursor;
クローズしたカーソルのアクティブ・セットは未定義になるため、クローズしたカーソルからはFETCHできません。必要であれば、(たとえば、入力ホスト変数に新しい値を指定して)カーソルを再OPENできます。
MODE=ORACLEの場合、COMMITまたはROLLBACKを発行すると、CURRENT OF句で参照されているカーソルがクローズされます。他のカーソルには、COMMITまたはROLLBACKによる影響はなく、オープンの場合は、オープンのままです。ただし、MODE=ANSIの場合は、COMMITまたはROLLBACKを発行すると、すべての明示カーソルがクローズされます。
関連項目:
COMMITとROLLBACKの詳細は、データベースの概要を参照してください。