CLI の手引きおよび解説書

スクロール可能カーソル

DB2 CLI はスクロール可能カーソルをサポートしています。カーソル間で次のようなスクロール能力があります。

次の 2 つのタイプのスクロール可能カーソルが DB2 CLI にサポートされています。

個々のカーソルのタイプに関する説明の後に、使用するカーソル・タイプの決定があります。

静的な読み取り専用カーソル

このタイプのスクロール可能カーソルは静的です。一度作成されたなら、行は加えられたりまたは削除されることはありません。さらに、どの行の値も変更されません。カーソルは同一のデータにアクセスしている他のアプリケーションに影響されません。

このカーソルは読み取り専用でもあります。アプリケーションはどの値も変更することができません。カーソル行がどのようにロックされるかは、カーソルを作成するのに使用するステートメントの分離レベルで判別されます。分離レベルとその影響の完全な説明については、SQL 解説書 を参照してください。

キーセット主導カーソル

このタイプのスクロール可能カーソルには、静的カーソルにはない機能が 2 つ追加されています。その機能とは、基礎となるデータに加えられた変更を検出する機能と、カーソルを使用して基礎となるデータに変更を加える機能です。

キーセット主導カーソルを初めてオープンする際には、結果セット全体が存続している間だけキーがキーセットに保管されます。このキーは、カーソルに含まれている行の順序とセットを判別するのに使用されます。結果セット全体をカーソル・スクロールする際に、このキーセット中のキーを使用して個々の行の現行データ値が検索されます。カーソルで行の再取り出しが行われるたびに、カーソルを初めてオープンした際にあった値ではなく、最新の値がデータベース中で検索されます。したがって、アプリケーションによるスクロールの際に行を通過するまで変更内容はその行に反映されません。

基礎となるデータに対する変更には、キーセット主導カーソルに反映されるものもされないものも含めて、さまざまなタイプがあります。

既存の行の値に対する変更
カーソルはこのタイプの変更内容を反映します。カーソルは必要になるたびにデータベースから行を再取り出しするので、キーセット主導カーソルはそのカーソル自体や他のカーソルによって加えられた変更を検出します。

行の削除
カーソルはこのタイプの変更内容も反映します。キーセットの生成後に行セット中の行が削除されると、カーソルには"穴"として示されます。カーソルがデータベースから行を再取り出ししようとする際に、その行がないと認識します。

行の追加
カーソルはこれらのタイプの変更を反映しません。行セットは、カーソルが初めてオープンする際に一度だけ判別されます。 SELECT ステートメントを再発行して、新しい行が追加されているはずなのでその真偽を調べるということはありません。

キーセット主導カーソルは、SQLBulkOperations() または SQLSetPos() を呼び出して結果セット中の行を修正する際にも使用されます。

SQLBulkOperations() をキーセット主導カーソルと共に使用する

SQLBulkOperations() を使用して、行セットの追加、更新、削除、または取り出しを行えます。行を更新する方法を指定するには、Operation 引き数を使用します。詳しくは、SQLBulkOperations - 行のセットの追加、更新、削除、または取り出しの次の箇所を参照してください。

SQLSetPos() をキーセット主導カーソルと共に使用する

SQLSetPos() を使用して、行セットを更新したり削除したりできます。行を更新する方法を指定するには、Operation 引き数を使用します。詳しくは、SQLSetPos - 行セット (Rowset) でカーソル位置を設定するの次の箇所を参照してください。

使用するカーソル・タイプの決定

まず最初に、静的カーソルとスクロール可能カーソルのどちらを使うかを決める必要があります。アプリケーションにスクロール可能カーソルの追加機構を付加する必要がなければ、静的カーソルを使用する必要があります。

スクロール可能カーソルが必要な場合は、静的カーソルかキーセット主導カーソルのどちらかに決める必要があります。静的カーソルを使用すると、オーバーヘッドを最小に抑えられます。アプリケーションにキーセット主導カーソルの追加機構を付加する必要がなければ、静的カーソルを使用する必要があります。

アプリケーションが、基礎となるデータに対する変更を検出したり、カーソルからデータの追加、更新、または削除を行うようにする必要がある場合は、キーセット主導カーソルを使用する必要があります。

ドライバーと DBMS でサポートされているカーソルのタイプを判別するには、アプリケーションが次の InfoTypeSQLGetInfo() を呼び出すようにする必要があります。

結果セットから返される行セットの指定

次の用語を理解するのは重要です。

結果セット
SQL SELECT ステートメントにより生成される行の完全セット。一度作成されたなら、その結果セットは変更されません。

行セット
取り出し後に返される結果セットに入っている行のサブセット。アプリケーションは、初めてデータの取り出しが行われる前に行セットのサイズを指示し、 2 回目以降の取り出しが行われる前にそのサイズを修正できます。 SQLFetchScroll() への各呼び出しで、結果セットから該当する行を指定して行セットに移植します。

ブックマーク
結果セットにある特定の行へのポインター (ブックマーク) を保管することができます。一度保管したなら、アプリケーションは結果セットのどこにでも移動し続けることができ、そして行セットを生成するためブック・マークされた行に戻ります。詳細な説明については、スクロール可能カーソルでのブックマークの使用を参照してください。

結果セット内の行セットの位置は、 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 値は右側に表示しています。

図 7. 行セットの取り出しの例


行セットの取り出しの例

詳細については、 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 行だけが、意味のあるデータです。アプリケーションは残りの行を無視する必要があります。

図 8. 一部の行セットの例


一部の行セットの例

ステートメント属性 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 を返さない場合は、行状況のバッファー内容が未定義です。定義されている場合には、次の値が返されます。

行状況配列の値
説明

SQL_ROW_SUCCESS
行が正常に取り出されました。

SQL_ROW_SUCCESS_WITH_INFO
行が正常に取り出されました。しかし、行に関する警告が返されました。

SQL_ROW_ERROR
行を取り出し中にエラーが発生しました。

SQL_ROW_NOROW
行セットが結果セットの終了行と重なり合いました。行状況配列のこの要素に対応した行が返されていません。

SQL_ROW_ADDED
SQLBulkOperations() によって行が挿入されました。その行がもう一度フェッチされるか、または SQLSetPos() により最新表示されると、状況は SQL_ROW_SUCCESS となります。

SQLFetch()SQLFetchScroll() にはこの値はセットされません。

SQL_ROW_UPDATED
行は正常にフェッチされ、この結果セットからの最後のフェッチ以降に変更が加えられています。この結果セットからその行がもう一度フェッチされるか、または SQLSetPos() により最新表示されると、状況はその行の新しい状況に変更されます。

SQL_ROW_DELETED
この結果セットからの最後のフェッチ以降にその行は削除されています。

図 8 において、行状況配列の最初の 3 行には、 SQL_ROW_SUCCESS の値が含まれることになります。そして、残りの 7 行には SQL_ROW_NOROW が含まれます。

典型的なスクロール可能カーソルのアプリケーション

スクロール可能カーソルを使用する各アプリケーションは、次のステップを指示通りの順序に行う必要があります。

1. 環境のセットアップ

以下の追加のステートメント属性は、 DB2 CLI アプリケーションのスクロール可能カーソルを使用する場合に必要とされるものです。詳細な説明については、SQLSetStmtAttr - ステートメントに関連したオプションの設定を参照してください。

行セット・サイズの設定
SQL_ATTR_ROW_ARRAY_SIZE ステートメント属性を、 SQLFetchScroll() への各呼び出しから返したい行数に設定します。

省略時値は 1 です。

スクロール可能カーソルのタイプ
DB2 CLI は静的な読み取り専用カーソルか、またはキーセット主導カーソルをサポートしています。 SQLSetStmtAttr() を使用して、 SQL_ATTR_CURSOR_TYPE ステートメント属性を SQL_CURSOR_STATIC または SQL_CURSOR_KEYSET_DRIVEN に設定します。 ODBC はその他のスクロール可能カーソルを定義しますが、DB2 CLI では使用できません。

この値を自分で設定するか、または SQL_CURSOR_FORWARD_ONLY の省略時値が使用されます。

返される行数を保管する場所
アプリケーションには、SQLFetchScroll() への各呼び出しから行セットに返された行数を判別する手段が必要です。行セットに返される行数は、SQL_ATTR_ROW_ARRAY_SIZE を使用してセットされた行セットの最大サイズより小さいこともあります。

SQL_ATTR_ROWS_FETCHED_PTR ステートメント属性をポインターとして、 SQLUINTEGER 変数に設定します。そして、この変数には SQLFetchScroll() への各呼び出し後に行セットに返される行数が入ります。

行状況で使用する配列
SQL_ATTR_ROW_STATUS_PTR ステートメント属性をポインターとして、行状況を保管するのに使用する SQLUSMALLINT 配列に設定します。そして、SQLFetchScroll() への各呼び出し後に、この配列は更新されます。

詳細については、行状況の配列を参照してください。

ブックマークを使用しますか
スクロール可能カーソルにブックマークを使用する予定がある場合は、 SQL_ATTR_USE_BOOKMARKS ステートメント属性を SQL_UB_VARIABLE に設定してください。

以下の例は、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);
/* ... */

2. SQL SELECT ステートメントの実行および結果のバインド

SQL ステートメントの実行および結果セットのバインド用の通常の DB2 CLI プロセスに従ってください。アプリケーションは SQLRowCount() を呼び出し、全体の結果セットの行数を判別することができます。スクロール可能カーソルは、列方向および行方向のバインドの両方をサポートします。 CLI のサンプル・プログラム sfetch.c は、両方の方式を示しています。

3. 結果セットから一度に複数行の行セットを取り出す

この時点で、アプリケーションは以下のステップを使用して、結果セットに入っている情報を読み取ることができます。

  1. SQLFetchScroll() を使用して、結果セットからデータの行セットを取り出す。 FetchOrientation 引き数を使用すると、結果セットにある行セットの場所を示すことができます。詳細については、結果セットから返される行セットの指定を参照してください。

    データの最初の行セットを検索するための SQLFetchScroll() への典型的な呼び出しは、次のようなものです。

       SQLFetchScroll(hstmt, SQL_FETCH_FIRST, 0);
    
  2. 結果セット内に返される行数を計算する。この値は、SQLFetchScroll() への各呼び出し後に自動的にセットされます。上記の例において、ステートメント属性 SQL_ATTR_ROWS_FETCHED_PTR を変数 numrowsfetched にセットしています。これにより、この変数にはそれぞれの SQLFetchScroll() 呼び出しの後に取り出される行数が含まれます。

    SQL_ATTR_ROW_STATUS_PTR ステートメント属性をすでにセットしている場合には、行状況の配列も行セットのそれぞれ可能な行に応じて更新されます。詳細については、行状況の配列を参照してください。

  3. 返される行のデータを表示または操作する。

4. 結果セットをクローズするステートメントの解放

一度アプリケーションが情報の検索を終了したなら、ステートメント・ハンドル解放用の通常の 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 を使用して、 前のステップでセットされています。


[ ページのトップ | 前ページ | 次ページ | 目次 | 索引 ]