カーソル

ここでは、カーソルの使用方法について説明します。

概要

SELECT 文によって返される結果集合に複数行のデータが含まれるコードを作成する場合は、カーソルを宣言して使用する必要があります。カーソルは、結果集合内の現在の位置を、画面上のカーソルが現在の位置を示すのと同じように示します。

カーソルを使用すると、次の処理が行えます。

次に示すコード例は、次の一連のイベントを示しています。

  1. DECLARE CURSOR 文で、SELECT 文をカーソル Cursor1 に関連付けます。
  2. OPEN 文で、カーソルをオープンします。カーソルをオープンする場合は、関連付けた SELECT 文が実行されます。
  3. FETCH 文で、カラム au_fname と au_lname の現在行のデータを検索し、ホスト変数 first_name と last_name にそのデータを格納します。
  4. FETCH 文がループされ、取り込むデータがなくなるまで繰り返し実行されます。
  5. CLOSE 文でカーソルをクローズします。
 EXEC SQL DECLARE Cursor1 CURSOR FOR
     SELECT au_fname, au_lname FROM authors
 END-EXEC
  . . .
     EXEC SQL
         OPEN Cursor1
     END-EXEC
       . . .
     perform until sqlcode not = zero
         EXEC SQL
             FETCH Cursor1 INTO :first_name,:last_name
         END-EXEC
         display first_name, last_name
     end-perform
      . . .
     EXEC SQL
         CLOSE Cursor1
     END-EXEC

カーソルの宣言

カーソルを使用する前に、カーソルを宣言する必要があります。カーソルを宣言するには、DECLARE CURSOR 文を使用し、この文で、カーソル名と、SELECT 文または PREPARE 文で定義した SQL 文の名前を指定します。

カーソル名は、接続するデータベースの識別子に対する規則に準拠する必要があります。たとえば、識別子にハイフンを使用できないデータベースでは、カーソル名にもハイフンは使用できません。

 EXEC SQL
     DECLARE Cur1 CURSOR FOR
      SELECT first_name FROM employee 
       WHERE last_name = :last-name
 END-EXEC

この例では、入力ホスト変数 (:last-name) を使用して SELECT 文を指定しています。カーソルの OPEN 文が実行されると、入力ホスト変数の値が読み取られ、SELECT 文が実行されます。

 EXEC SQL
     DECLARE Cur2 CURSOR FOR stmt1
 END-EXEC
      . . .
     move "SELECT first_name FROM emp " &
          "WHERE last_name=?" to prep.
     EXEC SQL
        PREPARE stmt1 FROM :prep
     END-EXEC
      . . .
     EXEC SQL
        OPEN Cur2 USING :last-name
     END-EXEC

この例では、DECLARE CURSOR 文が PREPARE 文で定義した文 (stmt1) を参照しています。PREPARE 文で定義した SELECT 文には、パラメータマーカーとして疑問符 (?) を使用できます。パラメータマーカーは、カーソルをオープンするとデータに置き換えられます。カーソルは、SELECT 文を PREPARE 文で定義する前に宣言してください。

COBSQL

カーソルは、プログラムのデータ部または手続き部のどちらかで宣言できます。DECLARE CURSOR 文はコードを生成しませんが、カーソルが手続き部で宣言された場合には、COBSQL は DECLARE CURSOR 文に対してアニメーションブレークポイントを生成します。

オブジェクト指向構文

オブジェクト指向 (OO) プログラム内では、データ項目を宣言するために有効な場所であればどこでもカーソルを宣言できます。カーソルは、カーソルが開かれたオブジェクト内でローカルです。つまり、それぞれ「同じ」カーソルを開いているオブジェクトの 2 つのインスタンスは、独自のカーソルインスタンスを取得します。

カーソルをあるメソッドでオープンし、第 2 のメソッドで取り込み、第 3 のメソッドでクローズできますが、その場合には、カーソルをオブジェクト場所節で宣言する必要があります。

注:

  • オブジェクト指向 COBOL 構文は、COBSQL ではサポートされていません。
  • Informix プリコンパイラの一部のバージョンでは、カーソルが作業場所節内で宣言されると、不正なコードが生成されることがあります。このため、INFORMIX を使用する場合には、カーソルは手続き部のみで宣言することをお奨めします。

カーソルのオープン

宣言したカーソルを使用する前に、カーソルをオープンする必要があります。カーソルをオープンするには、OPEN 文を使用します。次に例を示します。

     EXEC SQL
         OPEN Cur1
     END-EXEC

DECLARE CURSOR 文が PREPARE 文で定義した文を参照しており、この参照文にパラメータマーカーが含まれる場合には、パラメータマーカーの値を提供するホスト変数または SQLDA 構造体の名前を OPEN 文で指定する必要があります。次に例を示します。

     EXEC SQL
         OPEN Cur2 USING :last-name
     END-EXEC

SQLDA データ構造体を使用するには、OPEN 文の実行時にデータ型、データ長、およびアドレスの各フィールドに、有効値が設定済みであることが必要です。

COBSQL

カーソルでのデータ取り出し方法

カーソルをオープンすると、データベースからデータを取り出すことができます。データの取り込みには、FETCH 文を使用します。FETCH 文は、OPEN 文によって生成された結果集合から次の行を取り出し、指定されたホスト変数 (または SQLDA 構造体で指定されたアドレス) にそのデータを書き込みます。次に使用例を示します。

     perform until sqlcode not = 0  
         EXEC SQL
            FETCH Cur1 INTO :first_name
         END-EXEC
         display '姓 : ' fname
         display '名 : ' lname
         display spaces
     end-perform

カーソルが結果集合の末尾に達する場合は、SQLCA データ構造体の SQLCODE の値として 100 が戻され、SQLSTATE の値が「02000」に設定されます。

データがカーソルから取り出されると、データが選択されているテーブルにロックを置くことができます。カーソルの異なるタイプ、ロックされたデータの読み込み、およびデータに置くロックの詳細は、『カーソルオプション - OpenESQL』を参照してください。

COBSQL

ORACLE プリコンパイラ指令 MODE は、データが見つからない場合に SQLCODE に格納される値に影響を与えます。MODE プリコンパイラ指令の使用方法の詳細は、『ORACLE プリコンパイラ・プログラマーズ・ガイド』を参照してください。

カーソルのクローズ

カーソルの使用の終了後、使用したカーソルを CLOSE 文でクローズします。次に使用例を示します。

     EXEC SQL
         CLOSE Cur1
     END-EXEC

通常は、カーソルがクローズされると、データおよびテーブルへのロックがすべて解放されます。ただし、トランザクション内でカーソルがクローズされると、ロックが解放されない場合があります。

COBSQL

カーソルオプション

OpenESQL

ここで述べるカーソルオプションの説明は、OpenESQL のみに適用されます。

カーソルの動作やパフォーマンスは、次の埋め込み SQL 文を使用して調整できます。

SET SCROLLOPTION と SET CONCURRENCY は、どちらも拡張 SQL 文の一部であるため、使用する ODBC ドライバによってはサポートされないことがあります。

位置づけ UPDATE 文と DELETE 文

位置づけ UPDATE 文と DELTE 文はカーソルと併用して使用し、検索条件句のかわりに WHERE CURRENT OF 句を記述します。WHERE CURRENT OF 句によって、併用するカーソルを指定します。

     EXEC SQL
         UPDATE emp SET last_name = :last-name
          WHERE CURRENT OF Cur1
     END-EXEC

この例では、カーソル Cur1 を使用して、データベースから前回取り込んだ行に含まれる last_name の値を更新します。

     EXEC SQL
         DELETE emp WHERE CURRENT OF Cur1
     END-EXEC

この例では、カーソル Cur1 を使用して、データベースから前回取り込んだ行を削除します。

OpenESQL

ODBC ドライバによっては、位置づけ更新や位置づけ削除に使用するカーソルに FOR UPDATE 句を記述する必要があります。位置づけ UPDATE や位置づけ DELETE は拡張 ODBC 構文の一部です。そのため、使用する ODBC ドライバによってはサポートされない場合もあります。

COBSQL

COBSQL では、位置づけ更新や位置づけ削除に使用するカーソルには FOR UPDATE 句を記述する必要があります。

カーソルの使用

カーソルは大量のデータを扱う場合に便利ですが、カーソルを使用する際には、データ並行性、データ整合性、およびデータ一貫性に留意する必要があります。

データの整合性を確保するために、データベースサーバはいくつかのロック方法を実装できます。ロックを取得しないデータアクセスのタイプ、共有ロックを取得するタイプ、および排他ロックがあります。共有ロックでは、他のプロセスがデータにアクセスできますが、更新はできません。排他ロックでは、他のプロセスはデータにアクセスできません。

カーソルを使用する際には、次のように 3 つの分離レベルがあり、カーソルが読み込んでロックできるデータを制御します。

2 つのプロセスが同じデータで競合する状態「デッドロック」または「膠着状態」の問題が発生することがあります。代表的な例を説明します。あるプロセスがデータ A をロックしてデータ B にロックを要求します。ただし、別のプロセスがデータ B をロックしており、データ A にロックを要求します。このように両方のプロセスが、相手プロセスが要求しているデータをロックしている場合です。このような場合には、データベースサーバが問題を発見し、どちらか片方、または両方のプロセスにエラーを送ります。

COBSQL

Oracle、Sybase、および Informix では、アプリケーションでカーソルの分離レベルを設定することができます。適用可能なロックタイプと動作については、マニュアルで説明しています。マニュアルでは、データがロックされる物理レベルについても説明しています。物理レベルには、単一行、行セット (ページレベル)、またはテーブル全体があります。複数のテーブルや、多数のプロセスに使用されているテーブルを走査するカーソルを使用する場合は、ロックされたデータのアクセス可能性が減少するので、注意が必要です。

注:

COBSQL

Oracle、Sybase、および Informix では、FOR READ ONLY や FOR UPDATE などの多くの異なる句で定義されたカーソルを使用できます。これらの句は、カーソルの分離レベルに影響し、トランザクション処理に影響を及ぼします。これらの各句の影響の詳細は、使用しているデータベースに付属の SQL リファレンスマニュアルを参照してください。