DECLARE CURSOR ステートメント

DECLARE CURSOR ステートメントは、カーソルを定義します。

呼び出し

対話式 SQL 機能には外見上対話式の実行に見えるインターフェースが用意されている場合がありますが、 このステートメントはアプリケーション・プログラムに組み込むことだけが可能です。 このステートメントは実行可能ステートメントではなく、動的に準備することはできません。

コマンド行プロセッサーを使用して呼び出した場合は、追加オプションを指定できます。

詳しくは、 コマンド行 SQL ステートメントおよび XQuery ステートメントの使用 を参照してください。

許可

カーソルの SELECT ステートメント」 という用語は、以下の許可規則を示すために使用されます。 カーソルの SELECT ステートメントは、次のステートメントのいずれかです。
  • statement-name (ステートメント名) によって識別され、準備される選択ステートメント。
  • 指定された 選択ステートメント

このステートメントの許可 ID が持つ特権には、選択ステートメント を実行するために必要な特権が含まれている必要があります。 『SQL 照会』の許可セクションを参照してください。

statement-name を指定した場合:
  • ステートメントの許可 ID は、ランタイム許可 ID になります。
  • 許可検査は、選択ステートメントが準備される時点で行われます。
  • SELECT ステートメントが準備済み状態でない限り、カーソルはオープンできません。
select-statement を指定した場合:
  • GROUP 特権は検査されません。
  • ステートメントの許可 ID は、プログラム作成時に指定される許可 ID になります。

構文

Read syntax diagramSkip visual syntax diagramDECLAREcursor-name ASENSITIVEINSENSITIVE1CURSOR holdabilityreturnabilityFOR select-statementstatement-name
holdability
Read syntax diagramSkip visual syntax diagramWITHOUT HOLDWITH HOLD
returnability
Read syntax diagramSkip visual syntax diagramWITHOUT RETURNWITH RETURNTO CALLERTO CLIENT
Notes:
  • 1 This option can be used only in the context of a compound SQL (compiled) statement

説明

cursor-name
ソース・プログラムの実行時に作成されるカーソルの名前を指定します。 この名前は、ソース・プログラムに宣言されている他のカーソルの名前と同じであってはなりません。 カーソルは、その使用に先立ってオープンする必要があります。
ASENSITIVE または INSENSITIVE
カーソルが変更に対してアセンシティブかインセンシティブか指定します。
ASENSITIVE
カーソルが、結果表の元になっている行に対する挿入、アップデート、削除操作に可能な限りセンシティブになるよう指定します。これは、select-statement がどれほど最適化されるかによって異なります。 このオプションはデフォルトです。
INSENSITIVE
カーソルが、結果表の元になっている行に対する挿入、アップデート、削除操作に影響されないように指定します。 INSENSITIVE が指定された場合、カーソルは読み取り専用で結果表はカーソルがオープンされる時にマテリアライズされます。 結果として、結果表のサイズ、行の順序、および各行の値は、カーソルがオープンされた後は変更されません。 SELECT ステートメントに FOR UPDATE 節を含めることはできませんし、カーソルを位置指定更新または削除に使用することもできません。
WITHOUT HOLD または WITH HOLD
コミット操作の結果としてカーソルをクローズすることを回避するかどうかを指定します。
WITHOUT HOLD
コミット操作の結果としてカーソルをクローズすることを回避しません。 これがデフォルトです。
WITH HOLD
複数の作業単位を通してリソースを維持します。 WITH HOLD カーソル属性の効果は次のとおりです。
  • COMMIT で終了する作業単位の場合:
    • WITH HOLD として定義されたオープン・カーソルはオープンされたままです。 カーソルは、結果表の次の論理行の前に位置づけられます。

      WITH HOLD カーソルとの接続に対して、 COMMIT ステートメントの後で DISCONNECT ステートメントが出された場合、 保留されたカーソルを明示的にクローズする必要があります。そうしない場合、 (SQL ステートメントが全く発行されていない場合でも 単に WITH HOLD カーソルをオープンしたままにすることによって) その接続が作業を行っていると想定され、 その DISCONNECT ステートメントはエラーになります。

    • オープンされている WITH HOLD カーソルの現行カーソル位置を保護するロック以外のすべてのロックが解放されます。 保留されるロックには、表に対するロックと、 並列環境の場合はカーソルが現在位置している行に対するロックがあります。 パッケージと動的 SQL セクション (存在する場合) に対するロックは保留されます。
    • WITH HOLD の定義されたカーソルに対して、COMMIT 要求の直後に有効な操作は、 次のとおりです。
      • FETCH: カーソルの次の行を取り出します。
      • CLOSE: カーソルをクローズします。
    • UPDATE および DELETE CURRENT OF CURSOR は、 同一作業単位内で取り出された行に対してのみ有効です。
    • LOB ロケーターは解放されます。
    • 以下によって変更された行のセットがコミットされます。
      • データ変更ステートメント
      • オープン WITH HOLD カーソルに組み込まれている、SQL データを変更するルーチン
      コミットされます。
  • ROLLBACK で終了する作業単位の場合:
    • オープン・カーソルはすべてクローズされます。
    • その作業単位の過程で獲得したロックはすべて解除されます。
    • LOB ロケーターは解放されます。
  • 特殊な COMMIT の場合:
    • パッケージは、パッケージをバインドすることによって明示的に再作成されるか、 または無効になった後、 それが初めて参照されるときに動的に再作成されることにより暗黙のうちに再作成されます。 保留されたカーソルはすべて、パッケージの再バインド時にはクローズされます。 そのような場合、それ以後の実行時にエラーになる場合があります。
WITHOUT RETURN または WITH RETURN
カーソルの結果表を、プロシージャーから戻される結果セットとして使用するかどうかを指定します。
WITHOUT RETURN
カーソルの結果表を、プロシージャーから戻される結果セットとして使用しないことを指定します。
WITH RETURN
カーソルの結果表を、プロシージャーから戻される結果セットとして使用することを指定します。 WITH RETURN が使用されるのは、DECLARE CURSOR ステートメントにプロシージャーのソース・コードが含まれている場合だけです。 これ以外の場合は、プリコンパイラーがこの節を受け入れても、この節は効力を持ちません。

SQL プロシージャー内では、SQL プロシージャーの終了時にオープンしたままの、WITH RETURN 節を使用して宣言されたカーソルは、SQL プロシージャーからの結果セットを定義します。 そして、その他のオープン・カーソルは、SQL プロシージャーが終了するときにすべてクローズされます。 外部プロシージャー (LANGUAGE SQL を使用して定義されていないもの) では、すべてのカーソルのデフォルトは WITH RETURN TO CALLER です。 したがって、 外部プロシージャーの終了時に残っているオープン・カーソルがすべて結果セットと見なされます。 プロシージャーから戻されるカーソルを両方向スクロール・カーソルとして宣言することはできません。

TO CALLER
カーソルが呼び出し側に結果セットを返すよう指定します。 例えば、他のプロシージャーから呼び出しが行われた場合は、そのプロシージャーに結果セットが返されます。 また、呼び出し側がクライアント・アプリケーションであるなら、 そのクライアント・アプリケーションに結果セットが返されます。
TO CLIENT
カーソルがクライアント・アプリケーションに結果セットを返すよう指定します。 このカーソルは、中間にネストされたプロシージャーからは認識されません。 関数、メソッド、またはトリガーがプロシージャーを直接または間接的に呼び出した場合は、結果セットをクライアントに返すことができず、プロシージャーの終了後にカーソルがクローズされます。
選択ステートメント
カーソルの SELECT ステートメントを指定します。 その select-statement には、 パラメーター・マーカーを含めることはできませんが、 ホスト変数への参照は含めることができます。 参照されるホスト変数の宣言は、 ソース・プログラムにおいて DECLARE CURSOR ステートメントよりも前になければなりません。
ステートメント名
カーソルの SELECT ステートメントは、 カーソルのオープン時に statement-name によって指定される 準備済み SELECT ステートメントです。 statement-name は、ソース・プログラムの他の DECLARE CURSOR ステートメントに 指定されている statement-name と同じであってはなりません。

準備済み SELECT ステートメントの説明については、『PREPARE』を参照してください。

  • 他のプログラムから呼び出されたプログラム、 または同じプログラムの別のソース・ファイルから呼び出されたプログラムで、 呼び出し側プログラムによってオープンされたカーソルを使用することはできません。
  • SQL 以外の LANGUAGE を使用する、ネストされていないプロシージャーには、WITH RETURN 節を使用せずに DECLARE CURSOR が指定されるとデフォルトで WITH RETURN TO CALLER を使用し、カーソルをクローズせずにプロシージャーに残すという性質があります。 このようにすることによって、適当なクライアント・アプリケーションに結果セットを返すことができる以前のバージョンのプロシージャーにも対応することができます。 この性質を無効にするには、 プロシージャーでオープンされているカーソルをすべてクローズしてください。
  • カーソルの SELECT ステートメントが CURRENT DATE、CURRENT TIME、 または CURRENT TIMESTAMP を含む場合、これらの特殊レジスターを参照すると、 それぞれの FETCH でそれぞれの同一の日時値が与えられます。 この値は、カーソルがオープンされた時点で決まります。 この値は、カーソルのオープン時に決まります。
  • データをより効率的に処理するために、データベース・マネージャーでは、 リモート・サーバーからデータを検索するときに、 読み取り専用カーソルに対してはデータ変更を禁止することができます。 FOR UPDATE 節を使用するなら、データベース・マネージャーで、 カーソルが更新可能かどうかを決めることができます。 更新可能性は、アクセス・パス選択を決めるためにも使用されます。 カーソルを位置指定 UPDATE または DELETE ステートメントで使用しない場合は、 FOR READ ONLY として宣言してください。
  • オープン状態のカーソルは、結果表と、その表の行に対する相対位置を示します。 表は、カーソルの SELECT ステートメントによって指定される結果表です。
  • カーソルは、以下の各条件が真となる場合に削除可能 です。
    • 外部全選択の各 FROM 節に、OUTER 節を使用しないで、 基本表または削除可能ビュー (ネストした表式や共通表式またはニックネームを指定できない) が指定されている
    • 外部全選択に VALUES 節が含まれない
    • 外部全選択に GROUP BY 節も HAVING 節も含まれない
    • 外部全選択の選択リストに列関数が含まれない
    • 外部全選択に、UNION ALL を除くセット演算 (UNION、EXCEPT、または INTERSECT) が含まれない
    • 外部全選択に FOR SYSTEM_TIME 期間指定が含まれない
    • 外部全選択の選択リストに DISTINCT が含まれない
    • 外部全選択に ORDER BY 節が含まれておらず (ORDER BY 節がビューにネストされていてもよい)、 FOR UPDATE 節が指定されていない
    • 選択ステートメントに FOR READ ONLY 節が含まれない
    • 最外部の全選択の FROM 節に data-change-table-reference が含まれない
    • 次の条件の 1 つまたは複数が真である
      • FOR UPDATE 節が指定されている
      • カーソルが静的に定義されており、STATICREADONLY BIND オプションが YES になっていない
      • LANGLEVEL BIND オプションが MIA または SQL92E である
    カーソルに関連する外部全選択の選択リスト内の列は、 以下の各条件が真となる場合に、更新可能 です。
    • カーソルが削除可能である
    • 列の解決結果が基本表の列となる
    • LANGLEVEL BIND オプションが MIA の場合、 SQL92E または select-statement が FOR UPDATE 節を含んでいる (列が FOR UPDATE 節で明示的または暗黙的に指定されている必要があります)

    カーソルが読み取り専用 であるのは、削除可能でない場合です。

    カーソルは、以下の各条件が真となる場合に未確定 です。
    • 選択ステートメントが動的に準備される
    • 選択ステートメントに FOR READ ONLY 節も FOR UPDATE 節も含まれていない
    • LANGLEVEL BIND オプションが SAA1 である
    • それ以外の点では、カーソルは削除可能カーソルの条件を満たしている

    未確定カーソルは、BLOCKING BIND オプションが ALL の場合には読み取り専用と見なされます。 そうでない場合は、更新可能と見なされます。

  • CLI を使用して作成されたアプリケーション・プログラムによって呼び出されるプロシージャーの中のカーソルは、クライアント・アプリケーションに直接返される結果セットを定義するために使用することができます。 また、SQL プロシージャーが WITH RETURN 節を使用して定義される場合に限り、 そのプロシージャーの中のカーソルを呼び出し側の SQL プロシージャーに返すこともできます。
  • WITH HOLD を宣言したカーソルから直接または間接的に呼び出されるルーチン内で宣言されるカーソルは、 WITH HOLD オプションを継承しません。 したがって、ルーチン内のカーソルが明示的に WITH HOLD と定義されない限り、 カーソルはアプリケーションの COMMIT によってクローズされます。
    次のようなアプリケーションと 2 つの UDF について考慮します。
    Application:
    
       DECLARE APPCUR CURSOR WITH HOLD FOR SELECT UDF1() ...
       OPEN APPCUR
       FETCH APPCUR ...
       COMMIT
    
    UDF1:
    
       DECLARE UDF1CUR CURSOR FOR SELECT UDF2() ...
       OPEN UDF1CUR
       FETCH UDF1CUR ...
    
    UDF2:
    
       DECLARE UDF2CUR CURSOR WITH HOLD FOR SELECT UDF2() ...
       OPEN UDF2CUR
       FETCH UDF2CUR ...
    アプリケーションがカーソル APPCUR を取り出した後は、3 つのカーソルすべてがオープンになります。 アプリケーションが COMMIT ステートメントを発行すると、 APPCUR は、WITH HOLD と宣言されているのでオープンのままになります。 しかし、UDF1 では、カーソル UDF1CUR は、 WITH HOLD オプションを指定して定義されていないのでクローズされます。 カーソル UDF1CUR がクローズされると、 対応する選択ステートメント内のすべてのルーチン呼び出しが完了します (最終呼び出しを受け取るように定義されている場合は、 それを受け取ります)。 UDF2 が完了し、UDF2CUR がクローズされます。

例 1: DECLARE CURSOR ステートメントは、SELECT の結果にカーソル名 C1 を関連付けます。
   EXEC SQL DECLARE C1 CURSOR FOR
     SELECT DEPTNO, DEPTNAME, MGRNO
     FROM DEPARTMENT
     WHERE ADMRDEPT = 'A00';
例 2: EMPLOYEE 表が、 生成列 WEEKLYPAY (年間の給与に基づいて週ごとの支払いを計算する) を追加するように調整されていると想定します。 カーソルを宣言して、挿入される行からシステムが生成した列の値を取り出します。
   EXEC SQL DECLARE C2 CURSOR FOR
     SELECT E.WEEKLYPAY
     FROM NEW TABLE
       (INSERT INTO EMPLOYEE
        (EMPNO, FIRSTNME, MIDINIT, LASTNAME, EDLEVEL, SALARY)
        VALUES('000420', 'Peter', 'U', 'Bender', 16, 31842) AS E;