SQLExtendedFetch() - 行の配列のフェッチ
SQLExtendedFetch() は、
SQLFetch() の機能を拡張したものであり、
バインドされた列ごとに、行セット配列を返します。 SQL_ATTR_ROWSET_SIZE ステートメント属性の値によって、SQLExtendedFetch() が
戻す行セットのサイズが決まります。
SQLExtendedFetch() の ODBC 仕様
| ODBC 仕様レベル | X/Open CLI CAE 仕様 | ISO CLI 仕様 |
|---|---|---|
| 1.0 (「使用すべきでない」) | いいえ | いいえ |
構文
31 ビット・アプリケーションの場合、次の構文を使用します。
SQLRETURN SQLExtendedFetch (SQLHSTMT hstmt,
SQLUSMALLINT fFetchType,
SQLINTEGER irow,
SQLUINTEGER FAR *pcrow,
SQLUSMALLINT FAR *rgfRowStatus);64 ビット・アプリケーションの場合、次の構文を使用します。
SQLRETURN SQLExtendedFetch (SQLHSTMT hstmt,
SQLUSMALLINT fFetchType,
SQLLEN irow,
SQLULEN FAR *pcrow,
SQLUSMALLINT FAR *rgfRowStatus); 関数引数
次の表は、この関数のそれぞれの引数ごとに、 データ・タイプ、用途、および説明を示しています。
| データ・タイプ | 引数 | 使用 | 説明 |
|---|---|---|---|
| SQLHSTMT | hstmt | input | 配列データを取り出すステートメント・ハンドルを指定します。 |
| SQLUSMALLINT | fFetchType | input | フェッチの方向とタイプを指定します。 Db2 ODBC はフェッチ方向 SQL_FETCH_NEXT (前方スクロール・カーソル方向) のみをサポートします。 常に、次のデータ配列 (行セット) が取り出されます。 |
| SQLINTEGER (31ビット) または SQLLEN (64ビット) 1 | irow | input | 将来の利用のために予約済み。 この引数には、任意の整数を使用します。 |
| SQLUINTEGER *(31ビット) または SQLULEN * (64ビット )2 | pcrow | 出力 | 実際にフェッチされた行数を戻します。 処理中にエラーが起こると、引数 pcrow は、エラーが発生した行の 前の行 (行セット内) の順序を表す位置を指します。 最初の行を取り出す際にエラーが起こった場合は、引数 pcrow は値 0 を指します。 |
| SQLUSMALLINT * | rgfRowStatus | 出力 | 状況値の配列を戻します。 このエレメント数は、行セットの行数 (SQL_ROWSET_SIZE 属性で定義) と等しくなければなりません。 フェッチされたそれぞれの行ごとに、状況値が戻されます。
フェッチされた行数が状況配列のエレメント数より少ない (すなわち、行セットのサイズより小さい) 場合、残りの状況エレメントは SQL_ROW_NOROW に設定されます。 Db2 ODBC は、フェッチの開始以降に行が更新または削除されたかどうかを検出できません。 このため、以下の ODBC 定義の状況値は報告されません。
|
注:
|
|||
使用法
SQLExtendedFetch() は、複数の行を 1 セットにして配列フェッチを行います。 アプリケーションは、SQL_ROWSET_SIZE 属性を用いて SQLSetStmtAttr() を呼び出すことによって、配列のサイズを指定します。
結果を取り出す際、SQLExtendedFetch() と SQLFetch() を一緒に使用することはできません。
最初に SQLExtendedFetch() を呼び出す前に、カーソルは最初の行の前に位置付けられます。 SQLExtendedFetch() の呼び出し後、取り出されたばかりの行セット内の最後の行エレメントに対応する、結果セット内にある行にカーソルが位置付けられます。
データ行を一度に 1 行ずつフェッチするには、SQLExtendedFetch() ではなく SQLFetch() を呼び出す
必要があります。
rgfRowStatus 配列出力バッファーのエレメント数は、行セット内の 行数 (SQL_ROWSET_SIZE ステートメント属性で定義) と等しくする必要があります。 フェッチされた行数が状況配列内のエレメント数より少ない場合、 残りの状況エレメントが設定されて SQL_ROW_NOROW になっています。
SQLBindCol() 関数を使用してバインドされた結果セット内の任意のカラムについて、 Db2 ODBC は必要に応じてバインドされたカラムのデータを変換し、それらのカラムにバインドされた場所に保存します。 結果セットは、
列方向または行方向にバインドすることができます。
列方向のバインド:
結果セットを列方向にバインドするには、アプリケーションで SQL_BIND_TYPE ステートメント属性
に SQL_BIND_BY_COLUMN を指定します。 (これはデフォルト値です。) その後、アプリケーションは SQLBindCol() 関数を呼び出します。 LOB 列値をファイルにバインドするために、アプリケーションは SQLBindFileToCol() 関数を呼び出すことができます。
アプリケーションが SQLExtendedFetch() を呼び出すと、
バッファーの先頭に最初の行のデータが保管されます。 後続の各データ行は、 cbValueMax 引数で指定したバイト数のオフセットで保存されます。 SQLBindCol() 電話。 ただし、関連する C バッファー・タイプが固定幅 (SQL_C_LONG など) の場合は、
直前の行のデータからその固定長に対応した相対位置に保管されます。
SQLBindCol() 指定します。 バインドされた列の最初の行に対応して戻すのに使用可能なバイト数は、バッファーの先頭に保管されます。 後続の各行に対応して戻すのに使用可能なバイト数は、以下に示す C 関数が戻す値に等しい
相対位置に保管されます。sizeof(SQLINTEGER)特定の行の列のデータがnullの場合、 pcbValue 引数の配列内の関連要素は SQLBindCol() 指す先は SQL_NULL_DATA に設定されます。行方向のバインド: アプリケーションはまず最初に、SQL_BIND_TYPE 属性を
指定して SQLSetStmtAttr() を呼び出す必要があります。この場合、その引数 vParam には、
取り出されたデータの単一行と、各列のデータ値ごとの関連データ長を保持可能な構造サイズ
に設定します。
各バインドされた列について、データの最初の行は rgbValue 引数で指定されたアドレスに格納されます。 SQLBindCol()。 後続の各データ行は、 vParam 引数で指定したバイト数に等しいオフセットで区切られます。 SQLSetStmtAttr() 前の行のデータから。
各バインドされた列について、最初の行に返すことができるバイト数は、 pcbValue 引数で指定されたアドレスに格納されます。 SQLBindCol()。 後続の各値は、 vParam 引数で指定したバイト数に等しいオフセットで区切られます。 SQLBindCol()。
SQLExtendedFetch() は SQLFetch() と同じ方法で以下の例外を伴ってエラーを戻します。- 行セット内の特別な行に適用する警告が起きた場合、
SQLExtendedFetch()は、行状況配列の対応する項目を SQL_ROW_SUCCESS_WITH_INFO ではなく、SQL_ROW_SUCCESS に設定します。 - 行セット内のすべての行にエラーが発生した場合、
SQLExtendedFetch()は、SQL_ERROR ではなく SQL_SUCCESS_WITH_INFO を戻します。 - 個々の行に適用する状況レコードの各グループで、
SQLExtendedFetch()によって戻される最初の状況レコードに SQLSTATE 01S01 (行内のエラー) が含まれます。SQLExtendedFetch()が追加の SQLSTATE を戻せない場合、SQLSTATE 01S01 のみが戻されます。
エンコード方式の処理: 初期化ファイルのCURRENTAPPENSCHキーワードと fCType 引数 SQLBindCol() または SQLGetData() 結果セット内の文字またはグラフィック データのエンコード スキームを決定します。
戻りコード
SQLExtendedFetch() は、呼び出された後、次のいずれかの値を戻します。- SQL_SUCCESS
- SQL_SUCCESS_WITH_INFO
- SQL_ERROR
- SQL_INVALID_HANDLE
- SQL_NO_DATA_FOUND
診断
次の表は、この関数が生成する各 SQLSTATE 値ごとに、 その記述と説明を一覧で記載してあります。
| SQLSTATE | 説明 | 説明 |
|---|---|---|
| 01 0 04 | データが切り捨てられました。 | 1つ以上のカラムに対して返されるデータは切り捨てられます。(SQLExtendedFetch() は、このSQLSTATEに対してSQL_SUCCESS_WITH_INFOを返します。) |
| 01S0 1 | 行にエラーがあります。 | 1つ以上の行の取得中にエラーが発生しました。(SQLExtendedFetch() は、このSQLSTATEに対してSQL_SUCCESS_WITH_INFOを返します。) |
| 07002 | 列数が多すぎます。 | 次の 1 つ以上の理由に該当した場合に、この SQLSTATE が戻されます。
|
| 0700 6 | 無効な変換です。 | データ値は、 fCType 引数で指定されたデータ型に意味のある方法で変換できません。 SQLBindCol() 指定します。 |
| 08S01 | 通信リンク障害が発生しました。 | 関数が完了する前に、アプリケーションとデータ・ソース間の 通信リンクで障害が発生しました。 |
| 2 20 02 | 無効な出力または標識バッファーが指定されました。 | pcbValue 引数は SQLBindCol() NULL ポインターを指定し、対応する列の値は NULL です。 この関数は、SQL_NULL_DATA を報告できません。 |
| 22008 | 無効な日付時刻形式または日付時刻フィールドがオーバーフローです。 | 次の 1 つ以上の理由に該当した場合に、この SQLSTATE が戻されます。
|
| 22012 | ゼロによる除算は無効です。 | 除数ゼロでの割り算となる算術式からの値が戻されました。 |
| 22018 | 割り当てにエラーがありました。 | 次の 1 つ以上の理由に該当した場合に、この SQLSTATE が戻されます。
|
| 24000 | カーソルの状態が無効です。 | ステートメント・ハンドルで実行された SQL ステートメントは 照会ではありません。 |
| 580 04 | 予想外のシステム障害が発生しました。 | リカバリー不能なシステム・エラーです。 |
| HY001 | メモリーの割り振りが失敗しました。 | DB2 ODBC は、関数の実行または完了をサポートするのに必要なメモリーを割り振ることができません。 |
| HY010 | 関数のシーケンス・エラーです。 | 次の 1 つ以上の理由に該当した場合に、この SQLSTATE が戻されます。
|
| HY013 | 予期しない、メモリーのハンドル・エラーです。 | DB2 ODBC は、関数の実行または完了をサポートするのに必要なメモリーにアクセスすることができません。 |
| HY019 | 数値が範囲外です。 | 次の 1 つ以上の理由に該当した場合に、この SQLSTATE が戻されます。
|
| HY106 | フェッチ・タイプが範囲外です。 | 引数 fFetchType に指定された値は認識されません。 |
| HYC0 0 | ドライバーは使用できません。 | 次の 1 つ以上の理由に該当した場合に、この SQLSTATE が戻されます。
|
例
この関数は ODBC 3.0では推奨されませんが、この関数は Db2 ODBCでは非推奨ではありません。 しかし、ODBC アプリケーションでは、SQLExtendedFetch() ではなく、SQLFetchScroll() をご使用ください。
例
SQLExtendedFetch() を使用して配列のフェッチを実行するアプリケーションを示しています。/* ... */
"SELECT deptnumb, deptname, id, name FROM staff, org \
WHERE dept=deptnumb AND job = 'Mgr'";
/* Column-wise */
SQLINTEGER deptnumb[ROWSET_SIZE];
SQLCHAR deptname[ROWSET_SIZE][15];
SQLINTEGER deptname_l[ROWSET_SIZE];
SQLSMALLINT id[ROWSET_SIZE];
SQLCHAR name[ROWSET_SIZE][10];
SQLINTEGER name_l[ROWSET_SIZE];
/* Row-wise (Includes buffer for both column data and length) */
struct {
SQLINTEGER deptnumb_l; /* length */
SQLINTEGER deptnumb; /* value */
SQLINTEGER deptname_l;
SQLCHAR deptname[15];
SQLINTEGER id_l;
SQLSMALLINT id;
SQLINTEGER name_l;
SQLCHAR name[10];
} R[ROWSET_SIZE];
SQLUSMALLINT Row_Stat[ROWSET_SIZE];
SQLUINTEGER pcrow;
int i;
/* ... */
/*********************************************/
/* Column-wise binding */
/*********************************************/
rc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt);
rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROWSET_SIZE, (void*) ROWSET_SIZE, 0);
rc = SQLExecDirect(hstmt, stmt, SQL_NTS);
rc = SQLBindCol(hstmt, 1, SQL_C_LONG, (SQLPOINTER) deptnumb, 0, NULL);
rc = SQLBindCol(hstmt, 2, SQL_C_CHAR, (SQLPOINTER) deptname,
15, deptname_l);
rc = SQLBindCol(hstmt, 3, SQL_C_SSHORT, (SQLPOINTER) id, 0, NULL);
rc = SQLBindCol(hstmt, 4, SQL_C_CHAR, (SQLPOINTER) name, 10, name_l);
/* Fetch ROWSET_SIZE rows ast a time, and display */
printf("\nDEPTNUMB DEPTNAME ID NAME\n");
printf("-------- -------------- -------- ---------\n");
while ((rc = SQLExtendedFetch(hstmt, SQL_FETCH_NEXT, 0,
&pcrow, Row_Stat)) == SQL_SUCCESS) {
for (i = 0; i < pcrow; i++) {
printf("%8ld %-14s %8ld %-9s\n", deptnumb[i], deptname[i],
id[i], name[i]);
}
if (pcrow < ROWSET_SIZE)
break;
} /* endwhile */
if (rc != SQL_NO_DATA_FOUND && rc != SQL_SUCCESS)
CHECK_HANDLE(SQL_HANDLE_STMT, hstmt, rc);
rc = SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
/*********************************************/
/* Row-wise binding */
/*********************************************/
rc = SQLAllocHandle( SQL_HANDLE_STMT, hdbc, &hstmt);
CHECK_HANDLE(SQL_HANDLE_STMT, hstmt, rc);
/* Set maximum number of rows to receive with each extended fetch */
rc = SQLSetStmtAttr(hstmt, SQL_ATTR_ROWSET_SIZE, (void*) ROWSET_SIZE, 0);
CHECK_HANDLE(SQL_HANDLE_STMT, hstmt, rc);
/*
* Set vparam to size of one row, used as offset for each bindcol
* rgbValue
*/
/* ie. &(R[0].deptnumb) + vparam = &(R[1].deptnum) */
rc = SQLSetStmtAttr(hstmt, SQL_ATTR_BIND_TYPE,
(void*) (sizeof(R) / ROWSET_SIZE), 0);
rc = SQLExecDirect(hstmt, stmt, SQL_NTS);
rc = SQLBindCol(hstmt, 1, SQL_C_LONG, (SQLPOINTER) &R[0].deptnumb, 0,
&R[0].deptnumb_l);
rc = SQLBindCol(hstmt, 2, SQL_C_CHAR, (SQLPOINTER) R[0].deptname, 15,
&R[0].deptname_l);
rc = SQLBindCol(hstmt, 3, SQL_C_SSHORT, (SQLPOINTER) &R[0].id, 0,
&R[0].id_l);
rc = SQLBindCol(hstmt, 4, SQL_C_CHAR, (SQLPOINTER) R[0].name, 10, &R[0].name_l);
/* Fetch ROWSET_SIZE rows at a time, and display */
printf("\nDEPTNUMB DEPTNAME ID NAME\n");
printf("-------- -------------- -------- ---------\n");
while ((rc = SQLExtendedFetch(hstmt, SQL_FETCH_NEXT, 0, &pcrow, Row_Stat))
== SQL_SUCCESS) {
for (i = 0; i < pcrow; i++) {
printf("%8ld %-14s %8ld %-9s\n", R[i].deptnumb, R[i].deptname,
R[i].id, R[i].name);
}
if (pcrow < ROWSET_SIZE)
break;
} /* endwhile */
if (rc != SQL_NO_DATA_FOUND && rc != SQL_SUCCESS)
CHECK_HANDLE(SQL_HANDLE_STMT, hstmt, rc);
/* Free handles, commit, exit */
/* ... */