DB2 CLI はスクロール可能カーソルをサポートしています。カーソル間で次のようなスクロール能力があります。
次の 2 つのタイプのスクロール可能カーソルが DB2 CLI にサポートされています。
個々のカーソルのタイプに関する説明の後に、使用するカーソル・タイプの決定があります。
このタイプのスクロール可能カーソルは静的です。一度作成されたなら、行は加えられたりまたは削除されることはありません。さらに、どの行の値も変更されません。カーソルは同一のデータにアクセスしている他のアプリケーションに影響されません。
このカーソルは読み取り専用でもあります。アプリケーションはどの値も変更することができません。カーソル行がどのようにロックされるかは、カーソルを作成するのに使用するステートメントの分離レベルで判別されます。分離レベルとその影響の完全な説明については、SQL 解説書 を参照してください。
このタイプのスクロール可能カーソルには、静的カーソルにはない機能が 2 つ追加されています。その機能とは、基礎となるデータに加えられた変更を検出する機能と、カーソルを使用して基礎となるデータに変更を加える機能です。
キーセット主導カーソルを初めてオープンする際には、結果セット全体が存続している間だけキーがキーセットに保管されます。このキーは、カーソルに含まれている行の順序とセットを判別するのに使用されます。結果セット全体をカーソル・スクロールする際に、このキーセット中のキーを使用して個々の行の現行データ値が検索されます。カーソルで行の再取り出しが行われるたびに、カーソルを初めてオープンした際にあった値ではなく、最新の値がデータベース中で検索されます。したがって、アプリケーションによるスクロールの際に行を通過するまで変更内容はその行に反映されません。
基礎となるデータに対する変更には、キーセット主導カーソルに反映されるものもされないものも含めて、さまざまなタイプがあります。
キーセット主導カーソルは、SQLBulkOperations() または SQLSetPos() を呼び出して結果セット中の行を修正する際にも使用されます。
SQLBulkOperations() をキーセット主導カーソルと共に使用する
SQLBulkOperations() を使用して、行セットの追加、更新、削除、または取り出しを行えます。行を更新する方法を指定するには、Operation 引き数を使用します。詳しくは、SQLBulkOperations - 行のセットの追加、更新、削除、または取り出しの次の箇所を参照してください。
SQLSetPos() をキーセット主導カーソルと共に使用する
SQLSetPos() を使用して、行セットを更新したり削除したりできます。行を更新する方法を指定するには、Operation 引き数を使用します。詳しくは、SQLSetPos - 行セット (Rowset) でカーソル位置を設定するの次の箇所を参照してください。
まず最初に、静的カーソルとスクロール可能カーソルのどちらを使うかを決める必要があります。アプリケーションにスクロール可能カーソルの追加機構を付加する必要がなければ、静的カーソルを使用する必要があります。
スクロール可能カーソルが必要な場合は、静的カーソルかキーセット主導カーソルのどちらかに決める必要があります。静的カーソルを使用すると、オーバーヘッドを最小に抑えられます。アプリケーションにキーセット主導カーソルの追加機構を付加する必要がなければ、静的カーソルを使用する必要があります。
アプリケーションが、基礎となるデータに対する変更を検出したり、カーソルからデータの追加、更新、または削除を行うようにする必要がある場合は、キーセット主導カーソルを使用する必要があります。
ドライバーと DBMS でサポートされているカーソルのタイプを判別するには、アプリケーションが次の InfoType の SQLGetInfo() を呼び出すようにする必要があります。
次の用語を理解するのは重要です。
結果セット内の行セットの位置は、 SQLFetchScroll() への呼び出しで指定されます。たとえば、次の呼び出しでは、結果セット内の 11 番目の行を開始する行セットを生成することになります (図 7 のステップ 5)。
SQLFetchScroll(hstmt, /* Statement handle */ SQL_FETCH_ABSOLUTE, /* FetchOrientation value */ 11); /* Offset value */
画面ベースのアプリケーションのスクロール・バー操作は、行セットの位置に直接対応付けることが可能です。画面に表示される行幅に対する行セット・サイズを設定することで、スクロール・バーの移動を SQLFetchScroll() への呼び出しに対応づけることができます。
取り出す行セット | FetchOrientation 値 | スクロール・バー |
---|---|---|
最初の行セット | SQL_FETCH_FIRST | Home: スクロール・バーを先頭に |
最後の行セット | SQL_FETCH_LAST | End: スクロール・バーを末尾に |
次の行セット | SQL_FETCH_NEXT (SQLFetch() の呼び出しと同じ) | Page Down |
直前の行セット | SQL_FETCH_PRIOR | Page Up |
次の行で開始する行セット | SQL_FETCH_RELATIVE (FetchOffset を 1 にセット) | Line Down |
直前の行で開始する行セット | SQL_FETCH_RELATIVE (FetchOffset を -1 にセット) | Line Up |
特定行で開始する行セット | SQL_FETCH_ABSOLUTE (FetchOffset を、結果セットの開始 (正の値) または終了 (負の値) からの相対位置にセット) | アプリケーションにより生成 |
直前にブック・マークされた行で開始する行セット | SQL_FETCH_BOOKMARK (FetchOffset を、ブックマーク行 (詳細は、 スクロール可能カーソルでのブックマークの使用を参照) の正または負の相対位置にセット) | アプリケーションにより生成 |
以下の図では、いろいろな FetchOrientation 値を使用して SQLFetchScroll() へのいくつかの呼び出しを例示しています。結果セットにはすべての行 (1 〜 n) が含まれ、行セットのサイズは 3 です。呼び出しの順序は図の左側に、FetchOrientation 値は右側に表示しています。
![]() |
詳細については、 SQLFetchScroll() の 『カーソル位置の規則』 を参照してください。
ステートメント属性 SQL_ATTR_ROW_ARRAY_SIZE を使用して、行セット内の行数を指定することができます。たとえば、35 行の行セットを宣言するには、以下の呼び出しを使用します。
/*...*/ #define ROWSET_SIZE 35 /*...*/ rc = SQLSetStmtAttr( hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) ROWSET_SIZE, 0);
アプリケーションは、全部の行セットにデータがあると決め付けないでください。それぞれの行セットが作成された後、行セットのサイズを検査する必要があります。それは行セットが行の完全セットを含んでいないという実例があるからです。たとえば、行セット・サイズが 10 にセットされているケースを考えてください。それから、SQL_FETCH_ABSOLUTE および -3 にセットされた FetchOffset を使用して SQLFetchScroll() が呼び出されます。これによって、結果セットの終了行から 3 行を起点として 10 行を返そうとします。しかし、行セットの最初の 3 行だけが、意味のあるデータです。アプリケーションは残りの行を無視する必要があります。
![]() |
ステートメント属性 SQL_ATTR_ROW_ARRAY_SIZE の使用の詳細については、 行セット・サイズの設定を参照してください。
行状況の配列は、行セットにある各行についての追加情報を提供します。 SQLFetchScroll() への各呼び出し後に、配列は更新されます。アプリケーションは行セットのサイズとして同じ行数を指定して、配列 (SQLUSMALLINT タイプ) を宣言する必要があります (ステートメント属性 SQL_ATTR_ROW_ARRAY_SIZE)。それから、この配列のアドレスはステートメント属性 SQL_ATTR_ROW_STATUS_PTR により指定されます。
/* ... */ SQLUSMALLINT row_statusオROWSET_SIZEコ; /* ... */ /* Set a pointer to the array to use for the row status */ rc = SQLSetStmtAttr( hstmt, SQL_ATTR_ROW_STATUS_PTR, (SQLPOINTER) row_status, 0); /* ... */
SQLFetchScroll() への呼び出しで、SQL_SUCCESS または SQL_SUCCESS_WITH_INFO を返さない場合は、行状況のバッファー内容が未定義です。定義されている場合には、次の値が返されます。
SQLFetch() や SQLFetchScroll() にはこの値はセットされません。
図 8 において、行状況配列の最初の 3 行には、 SQL_ROW_SUCCESS の値が含まれることになります。そして、残りの 7 行には SQL_ROW_NOROW が含まれます。
スクロール可能カーソルを使用する各アプリケーションは、次のステップを指示通りの順序に行う必要があります。
以下の追加のステートメント属性は、 DB2 CLI アプリケーションのスクロール可能カーソルを使用する場合に必要とされるものです。詳細な説明については、SQLSetStmtAttr - ステートメントに関連したオプションの設定を参照してください。
省略時値は 1 です。
この値を自分で設定するか、または SQL_CURSOR_FORWARD_ONLY の省略時値が使用されます。
SQL_ATTR_ROWS_FETCHED_PTR ステートメント属性をポインターとして、 SQLUINTEGER 変数に設定します。そして、この変数には SQLFetchScroll() への各呼び出し後に行セットに返される行数が入ります。
詳細については、行状況の配列を参照してください。
以下の例は、SQLSetStmtAttr() に対する必要な呼び出しを例示しています。
/* ... */ /* Set the number of rows in the rowset */ rc = SQLSetStmtAttr( hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) ROWSET_SIZE, 0); CHECK_STMT(hstmt, rc); /* Set the SQL_ATTR_ROWS_FETCHED_PTR statement attribute to */ /* point to the variable numrowsfetched: */ rc = SQLSetStmtAttr( hstmt, SQL_ATTR_ROWS_FETCHED_PTR, &numrowsfetched, 0); CHECK_STMT(hstmt, rc); /* Set a pointer to the array to use for the row status */ rc = SQLSetStmtAttr( hstmt, SQL_ATTR_ROW_STATUS_PTR, (SQLPOINTER) row_status, 0); CHECK_STMT(hstmt, rc); /* Set the cursor type */ rc = SQLSetStmtAttr( hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_STATIC, 0); CHECK_STMT(hstmt, rc); /* Indicate that we will use bookmarks by setting the */ /* SQL_ATTR_USE_BOOKMARKS statement attribute to SQL_UB_VARIABLE: */ rc = SQLSetStmtAttr( hstmt, SQL_ATTR_USE_BOOKMARKS, (SQLPOINTER) SQL_UB_VARIABLE, 0); CHECK_STMT(hstmt, rc); /* ... */
SQL ステートメントの実行および結果セットのバインド用の通常の DB2 CLI プロセスに従ってください。アプリケーションは SQLRowCount() を呼び出し、全体の結果セットの行数を判別することができます。スクロール可能カーソルは、列方向および行方向のバインドの両方をサポートします。 CLI のサンプル・プログラム sfetch.c は、両方の方式を示しています。
この時点で、アプリケーションは以下のステップを使用して、結果セットに入っている情報を読み取ることができます。
データの最初の行セットを検索するための SQLFetchScroll() への典型的な呼び出しは、次のようなものです。
SQLFetchScroll(hstmt, SQL_FETCH_FIRST, 0);
SQL_ATTR_ROW_STATUS_PTR ステートメント属性をすでにセットしている場合には、行状況の配列も行セットのそれぞれ可能な行に応じて更新されます。詳細については、行状況の配列を参照してください。
一度アプリケーションが情報の検索を終了したなら、ステートメント・ハンドル解放用の通常の DB2 CLI プロセスに従ってください。
結果セットにある任意の行へのポインター (ブックマーク) を保管することができます。アプリケーションは、そのブックマークを相対位置として使用して、情報の行セットを検索します。ブックマークの付いた行を起点として (つまり、正または負の相対位置を指定して) 行セットを検索できます。
SQLSetPos() を使用して、行セット内の行へカーソルをいったん位置決めすれば、 SQLGetData() を使用して列 0 からブックマーク値を得ることができます。多くの場合、列 0 をバインドして行ごとのブックマーク値を検索する必要はありませんが、 SQLGetData() を使用すると必要な特定行のブックマーク値を検索することができます。
ブックマークはそれが作成された結果セット内でのみ有効です。 2 つの異なるカーソルで、同じ結果セットから同一行を選択した場合、そのブックマーク値は異なるものとなります。
唯一有効な比較は、同一の結果セットから得られる 2 つのブックマーク値の間のバイト対バイトの比較です。その比較が同じ場合には、その両方は同一行を指します。その他の数値計算またはブックマーク間の比較では、役立つ情報を提供できません。これには、結果セット内のブックマーク値の比較および結果セット間の比較が含まれます。
ブックマークを使用するには、典型的なスクロール可能カーソルのアプリケーションで説明されているステップに加えて、下記のステップに従う必要があります。
ブックマークを使用するには、 SQL_ATTR_USE_BOOKMARKS ステートメント属性を SQL_UB_VARIABLE に設定する必要があります。これは、スクロール可能カーソルに必要なその他のステートメント属性に加えるものです。
ODBC は可変長および固定長のブックマークの両方を定義します。 DB2 CLI は、より新しい、可変長のブックマークだけをサポートします。
アプリケーションは SQL SELECT ステートメントを実行し、 SQLFetchScroll() を使用して、希望する行で行セットを検索する必要があります。そして、SQLSetPos() を使用して、行セット内のカーソルの位置を指定します。最後に、SQLGetData() を用いて列 0 からブックマーク値が得られ、変数に保管されます。
ステートメント属性 SQL_ATTR_FETCH_BOOKMARK_PTR を使用して、ブックマークを用いる SQLFetchScroll() への次の呼び出しの場所を保管します。
SQLGetData() (変数 abookmark は下記を参照) を使用して、一度ブックマーク値を得たなら、次のようにして SQLSetStmtAttr() を呼び出します。
rc = SQLSetStmtAttr( hstmt, SQL_ATTR_FETCH_BOOKMARK_PTR, (SQLPOINTER) abookmark, 0);
ブックマーク値が一度保管されたなら、アプリケーションは SQLFetchScroll() を使用して、結果セットからデータの検索を続けることができます。
そして、アプリケーションは結果セット全体を移動できますが、カーソルをクローズする前であればいつでも、ブックマークの付いた行の位置に基づいて行セットを検索できます。
SQLFetchScroll() に対する以下の呼び出しは、ブックマークの付いた行を起点として行セットを検索します。
rc = SQLFetchScroll(hstmt, SQL_FETCH_BOOKMARK, 0);
0 の値は相対位置を指定するものです。 -3 を指定すると、ブックマークの付いた行の 3 行前の行セットから始まり、 4 を指定すると 4 行後で始まります。
ブックマーク値を保管するのに使用する変数が、 SQLFetchScroll() 呼び出しでは指定されない点に注意してください。その変数は、ステートメント属性 SQL_ATTR_FETCH_BOOKMARK_PTR を使用して、 前のステップでセットされています。