ここでは、カーソルの使用方法について説明します。
SELECT 文によって返される結果集合に複数行のデータが含まれるコードを作成する場合は、カーソルを宣言して使用する必要があります。カーソルは、結果集合内の現在の位置を、画面上のカーソルが現在の位置を示すのと同じように示します。
カーソルを使用すると、次の処理が行えます。
次に示すコード例は、次の一連のイベントを示しています。
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 のメソッドでクローズできますが、その場合には、カーソルをオブジェクト記憶節で宣言する必要があります。
注:
宣言したカーソルを使用する前に、カーソルをオープンする必要があります。カーソルをオープンするには、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 文を使用します。
SET SCROLLOPTION と SET CONCURRENCY は、どちらも拡張 SQL 文の一部であるため、使用する ODBC ドライバによってはサポートされないことがあります。
位置づけ 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 つの分離レベルがあり、カーソルが読み込んでロックできるデータを制御します。
レベル 0 は、読み取り専用カーソルのみで使用できます。レベル 0 では、カーソルは行をロックしませんが、コミットされていないデータを読み込む可能性があります。コミットされていないデータを読み込むのは危険です (ロールバック操作でデータが元の状態に戻るため)。これは通常「ダーティリード」と呼ばれます。データベースによっては、ダーティリードは行えません。
レベル 1 は、読み取り専用カーソルまたは更新可能カーソルに使用できます。レベル 1 では、FOR UPDATE 句を使用している場合を除き、共有ロックがデータに置かれます。FOR UPDATE 句を使用している場合には、排他ロックがデータに置かれます。カーソルをクローズする場合は、ロックが解放されます。通常、FOR UPDATE 句なしの標準カーソルは、分離レベル 1 にあり、共有ロックを使用します。
レベル 3 カーソルは、トランザクションに使用されます。カーソルをクローズしたときにロックが解放されるのではなく、トランザクションが終了したときにロックが解放されます。通常、レベル 3 では、データを排他ロックします。
2 つのプロセスが同じデータで競合する状態「デッドロック」または「膠着状態」の問題が発生することがあります。代表的な例を説明します。あるプロセスがデータ A をロックしてデータ B にロックを要求します。ただし、別のプロセスがデータ B をロックしており、データ A にロックを要求します。このように両方のプロセスが、相手プロセスが要求しているデータをロックしている場合です。このような場合には、データベースサーバーが問題を発見し、どちらか片方、または両方のプロセスにエラーを送ります。
COBSQL
Oracle、Sybase、および Informix では、アプリケーションでカーソルの分離レベルを設定することができます。適用可能なロックタイプと動作については、マニュアルで説明しています。マニュアルでは、データがロックされる物理レベルについても説明しています。物理レベルには、単一行、行セット (ページレベル)、またはテーブル全体があります。複数のテーブルや、多数のプロセスに使用されているテーブルを走査するカーソルを使用する場合は、ロックされたデータのアクセス可能性が減少するので、注意が必要です。
注:
COBSQL
Oracle、Sybase、および Informix では、FOR READ ONLY や FOR UPDATE などの多くの異なる句で定義されたカーソルを使用できます。これらの句は、カーソルの分離レベルに影響し、トランザクション処理に影響を及ぼします。これらの各句の影響の詳細は、使用しているデータベースに付属の SQL リファレンスマニュアルを参照してください。