適合 性
導入されたバージョン: ODBC 1.0 標準コンプライアンス: ISO 92
Summary
SQLBindCol はアプリケーションデータバッファを結果セット内の列にバインドします。
構文
SQLRETURN SQLBindCol(
SQLHSTMT StatementHandle,
SQLUSMALLINT ColumnNumber,
SQLSMALLINT TargetType,
SQLPOINTER TargetValuePtr,
SQLLEN BufferLength,
SQLLEN * StrLen_or_IndPtr);
引数
StatementHandle
[入力]ステートメント ハンドル。
列番号
[入力]バインドする結果セットの列の数。 列は0から列の順に番号付けされ、列0はブックマーク列です。 ブックマークが使われていない場合(つまりSQL_ATTR_USE_BOOKMARKSステートメント属性がSQL_UB_OFFに設定されている場合)、列番号は1から始まります。
ターゲットタイプ
[入力]*TargetValuePtr バッファのCデータ型の識別子です。
SQLFetch、SQLFetchScroll、SQLBulkOperations、またはSQLSetPosでデータソースからデータを取得する場合、ドライバはデータをこのタイプに変換します。SQLBulkOperationsやSQLSetPosでデータソースにデータを送信する際、ドライバはこのタイプのデータを変換します。 有効なCデータ型および型識別子の一覧については、付録D:データ型の C 型セクションを参照してください。
TargetType引数が区間データ型の場合、ARDのSQL_DESC_PRECISION SQL_DESC_DATETIME_INTERVAL_PRECISIONフィールドに設定されているデフォルトの区間先導精度(2)と秒精度(6)がデータに使われます。 TargetType引数がSQL_C_NUMERICされている場合、ARDのSQL_DESC_PRECISIONフィールドとSQL_DESC_SCALEフィールドで設定されたデフォルトの精度(ドライバー定義)とデフォルトのスケール(0)がデータに使用されます。 デフォルトの精度やスケールが適切でない場合は、 アプリケーションがSQLSetDescField または SQLSetDescRecを呼び出して適切なディスクリプタフィールドを明示的に設定すべきです。
拡張 C データ型を指定することもできます。 詳細については、「ODBC の C データ型」を参照してください。
ターゲットバリューPtr
[延期入力/出力]データバッファにポインタを割り当ててカラムにバインドします。
SQLFetch と SQLFetchScroll はこのバッファ内のデータを返します。
SQLBulkOperations は 、Operation がSQL_FETCH_BY_BOOKMARKされたときにこのバッファ内のデータを返します。 操作 がSQL_ADDまたはSQL_UPDATE_BY_BOOKMARKされたときにこのバッファからデータを取得します。
SQLSetPos は Operation がSQL_REFRESHされるとこのバッファにデータを返します。 Operation SQL_UPDATE 時にこのバッファからデータを取得します。
TargetValuePtr がnullポインタの場合、ドライバーはその列のデータバッファをアンバインドします。 アプリケーションはSQL_UNBINDオプションで SQLFreeStmt を呼び出してすべての列を解除できます。 アプリケーションは、SQLBindColへの呼び出し中のTargetValuePtr引数がnullポインタで、StrLen_or_IndPtr引数が有効な場合、カラムのデータバッファをアンバインドしても、そのカラムの長さやインジケートバッファはバウンドされることがあります。
BufferLength
[入力]*TargetValuePtr バッファの長さ(バイト単位)。
ドライバは、文字やバイナリデータなどの可変長データを返す際に、*TargetValuePtrバッファの終わりを超えて書き込むのを避けるためにBufferLengthを使用します。 ドライバーが文字データを*TargetValuePtrに返す際にヌル終端文字をカウントしていることに注目してください。 *したがって、TargetValuePtr にはヌル終端文字の空白が含まれなければならず、そうでなければドライバがデータを切り詰めてしまいます。
ドライバが整数や日付構造などの固定長データを返す場合、 BufferLength を無視し、バッファがデータを保持するのに十分な大きさとみなします。 したがって、アプリケーションは固定長データ用に十分な大きさのバッファを割り当てることが重要です。そうでなければ、ドライバはバッファの終わりを超えて書き込みしてしまいます。
SQLBindCol は BufferLength が0未満のときにSQLSTATE HY090(無効な文字列またはバッファ長)を返しますが、 BufferLength が0の場合は返しません。 しかし、 TargetType が文字タイプを指定する場合、アプリケーションは BufferLength を0に設定すべきではありません。なぜなら、ISO CLI準配のドライバーがその場合SQLSTATE HY090(無効な文字列またはバッファ長)を返すからです。
StrLen_or_IndPtr
[延期入力/出力]長さ/インジケーターバッファにポインタを割り当ててカラムに割り当てます。
SQLFetch と SQLFetchScroll はこのバッファ内の値を返します。
SQLBulkOperations は、 Operation がSQL_ADD、SQL_UPDATE_BY_BOOKMARK、またはSQL_DELETE_BY_BOOKMARKのときにこのバッファから値を取得します。
SQLBulkOperations は 、Operation がSQL_FETCH_BY_BOOKMARKされるとこのバッファに値を返します。
SQLSetPos は Operation がSQL_REFRESHされるとこのバッファに値を返します。 Operation がSQL_UPDATEされたときにこのバッファから値を取得します。
SQLFetch、 SQLFetchScroll、 SQLBulkOperations、 SQLSetPos は、length/indicator buffer 内で以下の値を返すことができます:
返すデータの長さ
SQL_NO_TOTAL
SQL_NULL_DATA
アプリケーションは SQLBulkOperations または SQLSetPosで使用するために、長さ/インジケーターバッファに以下の値を配置できます:
送信されるデータの長さ
SQL_NTS
SQL_NULL_DATA
SQL_DATA_AT_EXEC
SQL_LEN_DATA_AT_EXECマクロの結果
SQL_COLUMN_IGNORE
インジケートバッファと長さバッファが別々の場合、インジケートバッファはSQL_NULL_DATAしか返せませんが、長さバッファはそれ以外のすべての値を返すことができます。
詳細については、 SQLBulkOperations Function、 SQLFetch Function、 SQLSetPos 関数、および Length/Indicator Values の使用を参照してください。
StrLen_or_IndPtrがヌルポインタの場合は、長さや指示値は使用されません。 これはデータ取得時に発生し、データがNULLである場合のエラーです。
アプリケーションが 64 ビット オペレーティング システムで実行される場合は、 ODBC 64 ビット情報を参照してください。
返品
SQL_SUCCESS、SQL_SUCCESS_WITH_INFO、SQL_ERROR、またはSQL_INVALID_HANDLE。
Diagnostics
SQLBindColがSQL_ERRORまたはSQL_SUCCESS_WITH_INFOを返すと、SQLGetDiagRecを呼び出し、HandleTypeをSQL_HANDLE_STMT、HandleをStatementHandleで呼び出すことで、関連するSQLSTATE値を取得できます。 以下の表は 、通常SQLBindColが返すSQLSTATE 値を一覧にし、この関数の文脈でそれぞれを説明します。「(DM)」という表記は、ドライバーマネージャーが返すSQLstateの記述の前に記載されます。 特に明記されていない限り、各 SQLSTATE 値に関連付けられている戻りコードはSQL_ERROR。
| SQLSTATE | エラー | Description |
|---|---|---|
| 01000 | 一般的な警告 | ドライバー固有の情報メッセージ。 (関数はSQL_SUCCESS_WITH_INFOを返します。 |
| 07006 | 制限付きデータ型属性違反 | (DM) ColumnNumber の引数は0で、 TargetType の引数はSQL_C_BOOKMARKやSQL_C_VARBOOKMARKではありませんでした。 |
| 07009 | 無効な記述子インデックス | ColumnNumberという引数に指定された値は、結果セットの最大列数を超えていました。 |
| HY000 | 一般的なエラー | 特定の SQLSTATE がなく、実装固有の SQLSTATE が定義されていないエラーが発生しました。 *MessageText バッファー内の SQLGetDiagRec によって返されるエラー メッセージには、エラーとその原因が記述されています。 |
| HY001 | メモリ割り当てエラー | ドライバーは、関数の実行または完了をサポートするために必要なメモリを割り当てませんでした。 |
| HY003 | 無効なアプリケーション バッファーの種類 | TargetTypeという引数は有効なデータ型でもSQL_C_DEFAULTでもありません。 |
| HY010 | 関数シーケンス エラー | (DM) StatementHandle に関連付けられている接続ハンドルに対して非同期実行関数が呼び出されました。 この非同期関数は SQLBindCol が呼び出された時点でも実行中でした。 (DM) SQLExecute、 SQLExecDirect、または SQLMoreResultsStatementHandle が呼び出され、SQL_PARAM_DATA_AVAILABLEが返されました。 この関数は、すべてのストリーミング パラメーターのデータが取得される前に呼び出されました。 (DM) 非同期実行関数が StatementHandle に対して呼び出され、この関数が呼び出されたときにはまだ実行されていました。 (DM) SQLExecute、 SQLExecDirect、 SQLBulkOperations、または SQLSetPos が StatementHandle に対して呼び出され、SQL_NEED_DATAが返されました。 この関数は、すべての実行時データ パラメーターまたは列に対してデータが送信される前に呼び出されました。 |
| HY013 | メモリ管理エラー | メモリが不足している可能性があるため、基になるメモリ オブジェクトにアクセスできなかったため、関数呼び出しを処理できませんでした。 |
| HY090 | 文字列またはバッファーの長さが無効です | (DM) BufferLength 引数に指定された値が0未満でした。 (DM)運転手はODBC 2でした。x ドライバーの場合、 ColumnNumber の引数は0に設定されており、 BufferLength の引数に指定された値も4ではありませんでした。 |
| HY117 | 不明なトランザクション状態のため、接続が中断されます。 切断関数と読み取り専用関数のみが許可されます。 | (DM) 中断状態の詳細については、「 SQLEndTran 関数を参照してください。 |
| HYC00 | 省略可能な機能が実装されていません | ドライバーやデータソースは、 TargetType 引数と対応する列のドライバー固有のSQLデータ型の組み合わせで指定された変換をサポートしていません。 ColumnNumberの引数は0で、ドライバーはブックマークをサポートしていません。 ドライバーはODBC 2のみをサポートしています。x と TargetType の引数は以下のいずれかでした。 SQL_C_NUMERIC SQL_C_SBIGINT SQL_C_UBIGINT および付録 Dのデータ型 に記載されている区間Cデータ型のいずれかです。 このドライバは3.50以前のODBCバージョンのみをサポートしており、 TargetType の引数はSQL_C_GUIDされました。 |
| HYT01 | 接続がタイムアウトしました | データ ソースが要求に応答する前に、接続タイムアウト期間の有効期限が切れています。 接続タイムアウト期間は、SQL_ATTR_CONNECTION_TIMEOUT SQLSetConnectAttr によって設定されます。 |
| IM001 | ドライバーは、この関数をサポートしていません | (DM) StatementHandle に関連付けられているドライバーは、関数をサポートしていません。 |
Comments
SQLBindCol は、結果セット内の列をアプリケーション内のデータバッファや長さ/インジケーターバッファに関連付けたり、 バインディング したりするために使われます。 アプリケーションが SQLFetch、 SQLFetchScroll、または SQLsetPosを 呼び出してデータを取得すると、ドライバーは指定されたバッファ内のバウンドされた列のデータを返します。詳細については、 SQLFetch 関数を参照してください。 アプリケーションが SQLBulkOperations を呼び出して行の更新や挿入、または SQLSetPosで 行の更新を行うと、ドライバーは指定されたバッファからバウンドされた列のデータを取得します。詳細については、 SQLBulkOperations Function または SQLSetPos Functionを参照してください。 バインディングの詳細については、「 結果の取得(基本)」を参照してください。
カラムはバインドされてもデータを取得する必要がないことに注目してください。 アプリケーションは また、SQLGetData を呼び出してカラムからデータを取得することもできます。 一部の列を行にバインドし、他の列を SQLGetData で呼び出すことは可能ですが、これにはいくつかの制限があります。 詳細は SQLGetDataをご覧ください。
カラムの結合、解消、再結合
カラムは、結果セットからデータが取得された後でも、いつでもバウンド、アンバインド、またはリバウンドされることがあります。 新しいバインディングは、バインディングを使用する関数が呼び出された次回に有効となります。 例えば、アプリケーションが結果セットの列をバインドし、 SQLFetchを呼び出したとします。 ドライバはバウンドバッファ内のデータを返します。 次に、アプリケーションが列を別のバッファセットにバインドしたとします。 ドライバーは、新たにバウンドされたバッファにフェッチされた行のデータを置きません。 代わりに、 SQLFetch が再度呼び出されるのを待ち、次の行のデータを新たにバインドされたバッファに配置します。
Note
文属性SQL_ATTR_USE_BOOKMARKSは、列0にバインドする前に必ず設定しておくべきです。 これは必須ではありませんが、強く推奨されます。
バインディング列
カラムをバインドするには、アプリケーションが SQLBindCol を呼び出し、データバッファのカラム番号、型、アドレス、長さ、そして長さ/インジケートバッファのアドレスを渡します。 これらのアドレスの使用方法については、このセクションの後半にある「バッファアドレス」を参照してください。 バインディングカラムの詳細については、「 Using SQLBindCol」をご覧ください。
これらのバッファの使用は先延ばしにされます。つまり、アプリケーションは それらをSQLBindCol にバインドしますが、ドライバは他の関数、すなわち SQLBulkOperations、 SQLFetch、 SQLFetchScroll、または SQLSetPosからアクセスします。 SQLBindColで指定されたポインタがバインディングが有効な限り有効であることを保証するのはアプリケーションの責任です。 もしアプリケーションがこれらのポインタを無効にすることを許可し、例えばバッファを解放し、それらが有効であることを期待する関数を呼び出す場合、その結果は定義されません。 詳細は「 繰延バッファ」を参照してください。
この束縛は、新しい束縛に置き換えられるか、列が束縛が解除されるか、文が解放されるまで有効です。
カラムの解消
単一の列をアンバインドするには、アプリケーションが SQLBindCol を呼び出し、 ColumnNumber をその列番号に設定し、 TargetValuePtr をnullポインタに設定します。 ColumnNumberが非バウンドの列を参照している場合、SQLBindColは依然としてSQL_SUCCESSを返します。
すべての列をアンバインドするには、アプリケーションが SQLFreeStmt を呼び出し、 fOption を SQL_UNBIND に設定します。 これはARDのSQL_DESC_COUNT場をゼロに設定することでも実現できます。
リバインディングカラム
アプリケーションは、次の 2 つの操作のいずれかを実行してバインディングを変更できます。
すでにバインドされているカラムに対して新しいバインディングを指定するために SQLBindCol を呼び出します。 ドライバーは、古いバインディングを新しいバインディングで上書きします。
SQLBindColへのバインディングコールで指定されたバッファアドレスに追加するオフセットを指定します。 詳細については、次のセクション「バインディングオフセット」をご覧ください。
バインディングオフセット
バインディングオフセットとは、データおよび長さ/インジケーターバッファのアドレス( TargetValuePtr および StrLen_or_IndPtr 引数で指定されたもの)に、それらがデリファレンスされる前に追加される値のことです。 オフセットが使われる場合、バインディングはアプリケーションのバッファ配置の「テンプレート」となり、オフセットを変更することでこの「テンプレート」をメモリの異なる領域に移動させることができます。 各バインディングで同じオフセットが各アドレスに加えられるため、異なる列のバッファ間の相対オフセットは各バッファ内で同じでなければなりません。 これは行ごとに綴じる場合に常に当てはまります。カラムワイズバインディングを使用する場合、アプリケーションはバッファを慎重に配置する必要があります。
バインディングオフセットの使用は、 SQLBindColを呼び出してカラムを再バインドするのと基本的に同じ効果を持ちます。 違いは 、SQLBindCol を新たに呼び出しるとデータバッファと長さ/インジケーターバッファの新しいアドレスを指定するのに対し、バインディングオフセットの使用はアドレスを変えず、単にオフセットを追加するだけである点です。 アプリケーションはいつでも新しいオフセットを指定でき、このオフセットは元々バウンドされたアドレスに必ず加算されます。 特に、オフセットが0に設定されている場合やステートメント属性がnullポインタに設定されている場合、ドライバーは元々バウンドされたアドレスを使用します。
バインディングオフセットを指定するために、アプリケーションはSQL_ATTR_ROW_BIND_OFFSET_PTR文属性をSQLINTEGERバッファのアドレスに設定します。 アプリケーションがバインディングを使う関数を呼び出す前に、このバッファにバイト単位のオフセットを設定します。 使用するバッファのアドレスを決定するために、ドライバはバインディング内のアドレスにオフセットを加えます。 アドレスとオフセットの合計は有効なアドレスでなければなりませんが、オフセットが加算されるアドレスが有効である必要はありません。 バインディングオフセットの使用方法の詳細については、この節の後半にある「バッファアドレス」を参照してください。
バインディングアレイ
行セットサイズ(SQL_ATTR_ROW_ARRAY_SIZE文属性の値)が1より大きい場合、アプリケーションは単一のバッファではなくバッファの配列をバインドします。 詳細は 「カーソルのブロック」を参照してください。
アプリケーションは配列を2通りの方法でバインドできます:
配列を各列にバインドします。 これは各データ構造(配列)が単一の列のデータを含むため、 カラムバイズバインディング と呼ばれます。
データを1行分保持する構造を定義し、これらの構造の配列をバインドします。 これは行 ごとのバインディング と呼ばれ、各データ構造が1行のデータを含むためです。
各バッファ配列は、行セットのサイズと同じ以上の要素を持つ必要があります。
Note
アプリケーションはアラインメントが有効であることを検証しなければなりません。 アライメントの考慮事項については 、「アライメント」を参照してください。
列方向のバインド
列ごとのバインディングでは、アプリケーションは各列に別々のデータ配列と長さ/インジケーター配列をバインドします。
列ごとのバインディングを使用する際、アプリケーションはまずSQL_ATTR_ROW_BIND_TYPE文属性をSQL_BIND_BY_COLUMNに設定します。 (これが既定値です)。バインドする列ごとに、アプリケーションは次の手順を実行します。
データバッファアレイを割り当てます。
長さ/インジケーター バッファーの配列を割り当てます。
Note
列方向のバインドを使用するときにアプリケーションが記述子に直接書き込む場合は、長さとインジケーター データに個別の配列を使用できます。
以下の引数で SQLBindCol を呼び出します:
TargetType はデータバッファ配列内の単一の要素の型です。
TargetValuePtr はデータバッファ配列のアドレスです。
BufferLength はデータバッファ配列内の単一の要素のサイズです。 BufferLength 引数は、データが固定長データの場合は無視されます。
StrLen_or_IndPtr は、長さ/インジケーター配列のアドレスです。
この情報の利用方法については、この節の後半にある「バッファアドレス」を参照してください。 列ごとの綴じについての詳細は「 Column-Wise 綴じ」を参照してください。
行方向のバインド
行ごとのバインディングでは、アプリケーションがバウンディングする各列のデータバッファと長さ/インジケーターバッファを含む構造を定義します。
行方向のバインドを使用するために、アプリケーションは次の手順を実行します。
単一のデータ行(データバッファと長さ/インジケーターバッファの両方を含む)を保持する構造を定義し、これらの構造の配列を割り当てます。
Note
行方向のバインドを使用するときにアプリケーションが記述子に直接書き込む場合は、長さデータとインジケーター データに個別のフィールドを使用できます。
SQL_ATTR_ROW_BIND_TYPE文属性を、単一のデータ行を含む構造体のサイズ、または結果の列がバインドされるバッファのインスタンスサイズに設定します。 長さには、すべてのバウンドされた列のスペースと構造体やバッファのパディングが含まれていなければなりません。これにより、バウンドカラムのアドレスが指定された長さで増分された際、結果が次の行の同じカラムの先頭を指し示すようにします。 ANSI C で sizeof 演算子を使用する場合、この動作が保証されます。
各バインドされる列に対して以下の引数で SQLBindCol を呼び出します:
TargetType は、カラムにバインドされるデータバッファメンバーのタイプです。
TargetValuePtr は、最初の配列要素のデータバッファメンバーのアドレスです。
BufferLength はデータバッファメンバーのサイズです。
StrLen_or_IndPtr は、バインドする長さ/インジケーター メンバーのアドレスです。
この情報の利用方法については、この節の後半にある「バッファアドレス」を参照してください。 列ごとの綴じについての詳細は「 Row-Wise 綴じ」を参照してください。
バッファアドレス
バッファアドレスは、データまたは長さ/インジケーターバッファの実際のアドレスです。 ドライバーはバッファに書き込み直前(フェッチ時間など)にバッファアドレスを計算します。 これは 、TargetValuePtr および StrLen_or_IndPtr 引数で指定されたアドレス、バインディングオフセット、行番号を用いて計算されます。
バウンドアドレス + バインディングオフセット + ((行番号 - 1) × 要素サイズ)
ここで、式の変数は以下の表に説明されているように定義されています。
| Variable | Description |
|---|---|
| バウンドアドレス | データバッファの場合、SQLBindColのTargetValuePtr 引数で指定されたアドレスです。 長さ/インジケーターバッファの場合、SQLBindColのStrLen_or_IndPtr引数で指定されたアドレスです。 詳細については、「Descriptors and SQLBindCol」セクションの「追加コメント」をご覧ください。 バウンドアドレスが0の場合、前の式で計算されたアドレスがゼロでなくても、データ値は返されません。 |
| バインディングオフセット | 行ごとのバインディングを使用する場合、SQL_ATTR_ROW_BIND_OFFSET_PTR文属性で指定されたアドレスに値が格納されます。 列ごとのバインディングが使われる場合や、SQL_ATTR_ROW_BIND_OFFSET_PTR文属性の値がnullポインタの場合、 バインディングオフセット は0となります。 |
| 列番号 | 行セット内の行の1ベースの数。 デフォルトである単一行フェッチの場合、これは1です。 |
| 要素サイズ | バウンド配列内の要素のサイズです。 列ごとのバインディングを使用する場合、長さ/インジケーターバッファの sizeof(SQLINTEGER) が使われます。 データバッファの場合、データ型が可変長の場合はSQLBindColのBufferLength引数の値、固定長の場合はデータ型のサイズです。 行ごとのバインディングを使用する場合、これはデータバッファと長さ/インジケーターバッファの両方の SQL_ATTR_ROW_BIND_TYPE ステートメント属性の値です。 |
ディスクリプタとSQLBindCol
以下のセクションでは 、SQLBindCol がディスクリプタとどのように相互作用するかについて説明します。
Caution
ある文に対して SQLBindCol を呼び出すと、他の文にも影響が出ることがあります。 これは、ステートメントに関連付けられている ARD が明示的に割り当てられ、他のステートメントにも関連付けられている場合に発生します。 SQLBindColはディスクリプタを修正するため、このディスクリプタに関連するすべての文に修正が適用されます。 もしこれが求められる動作でなければ、アプリケーションは SQLBindColを呼び出す前に、このディスクリプタを他の文から分離すべきです。
引数マッピング
概念的には、 SQLBindCol は以下のステップを順番に実行します。
SQLGetStmtAttrを呼び出してARDハンドルを取得します。
SQLGetDescFieldを呼び出してこのディスクリプタのSQL_DESC_COUNTフィールドを取得し、ColumnNumberの値がSQL_DESC_COUNTの値を超える場合はSQLSetDescFieldを呼び出してSQL_DESC_COUNTの値をColumnNumberに増やします。
SQLSetDescFieldを複数回呼び出して、ARDの以下のフィールドに値を割り当てます:
TargetTypeの値にSQL_DESC_CONCISE_TYPE SQL_DESC_TYPE設定しますが、TargetTypeがdatetimeまたはintervalサブタイプの簡潔な識別子のいずれかである場合、SQL_DESC_TYPEをそれぞれSQL_DATETIMEまたはSQL_INTERVALに設定します。SQL_DESC_CONCISE_TYPEを簡潔な識別子に設定します。SQL_DESC_DATETIME_INTERVAL_CODEは対応する日付時間または区間サブコードに割り当てられます。
TargetTypeに応じて、SQL_DESC_LENGTH、SQL_DESC_PRECISION、SQL_DESC_SCALE、SQL_DESC_DATETIME_INTERVAL_PRECISIONのいずれかを設定します。
SQL_DESC_OCTET_LENGTH フィールドを BufferLength の値に設定します。
SQL_DESC_DATA_PTRフィールドを TargetValuePtrの値に設定します。
SQL_DESC_INDICATOR_PTRフィールドを StrLen_or_IndPtrの値に設定します。 (以下の段落を参照してください。)
SQL_DESC_OCTET_LENGTH_PTRフィールドを StrLen_or_IndPtrの値に設定します。 (以下の段落を参照してください。)
StrLen_or_IndPtrの引数が指す変数は、指示情報と長さ情報の両方に使われます。 フェッチがその列のnull値に遭遇した場合、その変数にSQL_NULL_DATAを格納します。そうでなければ、この変数にデータ長を格納します。 nullポインタを StrLen_or_IndPtr として渡すことで、フェッチ操作がデータ長を返さないようにしますが、null値に遭遇し返す方法がない場合はフェッチが失敗しますSQL_NULL_DATA。
SQLBindColへの呼び出しが失敗した場合、ARDで設定されるはずのディスクリプタフィールドの内容は未定義となり、ARDのSQL_DESC_COUNTフィールドの値は変更されません。
COUNTフィールドの暗黙リセット
SQLBindCol は、SQL_DESC_COUNTの値が増加する場合にのみ ColumnNumber の引数の値にSQL_DESC_COUNTを設定します。 もしTargetValuePtr argumentの値がnullポインタで、ColumnNumberの値がSQL_DESC_COUNT(すなわち最も高いバウンディングカラムのバインディングを解除した場合)であれば、SQL_DESC_COUNTは残る最も高いバウンドカラムの数に設定されます。
SQL_DEFAULTに関する注意点
カラムデータを正常に取得するためには、アプリケーションはアプリケーションバッファ内のデータの長さと開始点を正確に決定しなければなりません。 アプリケーションが明示的な TargetTypeを指定すると、アプリケーションの誤解が容易に検出されます。 しかし、アプリケーションがSQL_DEFAULTの TargetType を指定すると、 SQLBindCol はアプリケーションが意図したデータ型とは異なるカラムに適用できます。これはメタデータの変更や別のカラムに適用することで可能です。 この場合、アプリケーションが必ずしもフェッチされたカラムデータの開始点や長さを決定できるとは限りません。 これにより、未報告のデータエラーやメモリ違反が発生する可能性があります。
コード例
以下の例では、アプリケーションがCustomersテーブル上で SELECT 文を実行し、顧客ID、名前、電話番号の結果セットを名前順に並べて返します。 その後、 SQLBindCol を呼び出してデータの列をローカルバッファにバインドします。 最後に、アプリケーションは SQLFetch で各行のデータを取得し、各顧客の名前、ID、電話番号を印刷します。
さらなるコード例については、 SQLBulkOperations Function、 SQLColumns Function、 SQLFetchScroll Function、 SQLSetPos Functionを参照してください。
// SQLBindCol_ref.cpp
// compile with: odbc32.lib
#include <windows.h>
#include <stdio.h>
#define UNICODE
#include <sqlext.h>
#define NAME_LEN 50
#define PHONE_LEN 60
void show_error() {
printf("error\n");
}
int main() {
SQLHENV henv;
SQLHDBC hdbc;
SQLHSTMT hstmt = 0;
SQLRETURN retcode;
SQLWCHAR szName[NAME_LEN], szPhone[PHONE_LEN], sCustID[NAME_LEN];
SQLLEN cbName = 0, cbCustID = 0, cbPhone = 0;
// Allocate environment handle
retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
// Set the ODBC version environment attribute
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);
// Allocate connection handle
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);
// Set login timeout to 5 seconds
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);
// Connect to data source
retcode = SQLConnect(hdbc, (SQLWCHAR*) L"NorthWind", SQL_NTS, (SQLWCHAR*) NULL, 0, NULL, 0);
// Allocate statement handle
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);
retcode = SQLExecDirect(hstmt, (SQLWCHAR *) L"SELECT CustomerID, ContactName, Phone FROM CUSTOMERS ORDER BY 2, 1, 3", SQL_NTS);
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
// Bind columns 1, 2, and 3
retcode = SQLBindCol(hstmt, 1, SQL_C_WCHAR, &sCustID, 100, &cbCustID);
retcode = SQLBindCol(hstmt, 2, SQL_C_WCHAR, szName, NAME_LEN, &cbName);
retcode = SQLBindCol(hstmt, 3, SQL_C_WCHAR, szPhone, PHONE_LEN, &cbPhone);
// Fetch and print each row of data. On an error, display a message and exit.
for (int i=0 ; ; i++) {
retcode = SQLFetch(hstmt);
if (retcode == SQL_ERROR || retcode == SQL_SUCCESS_WITH_INFO)
show_error();
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO)
{
//replace wprintf with printf
//%S with %ls
//warning C4477: 'wprintf' : format string '%S' requires an argument of type 'char *'
//but variadic argument 2 has type 'SQLWCHAR *'
//wprintf(L"%d: %S %S %S\n", i + 1, sCustID, szName, szPhone);
printf("%d: %ls %ls %ls\n", i + 1, sCustID, szName, szPhone);
}
else
break;
}
}
// Process data
if (retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) {
SQLCancel(hstmt);
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
}
SQLDisconnect(hdbc);
}
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
}
}
SQLFreeHandle(SQL_HANDLE_ENV, henv);
}
}
また、 サンプルODBCプログラムも参照してください。
関連関数
| ~についての情報 | 参照先 |
|---|---|
| 結果セット内の列に関する情報を返す | SQLDescribeCol関数 |
| データブロックのフェッチまたは結果セットのスクロール | SQLFetchScroll 関数 |
| 複数行のデータをフェッチする | SQLFetch 関数 |
| 文の列バッファを解放する | SQLFreeStmt 関数 |
| データの列の一部またはすべてをフェッチする | SQLGetData 関数 |
| 結果セットの列数を返す | SQLNumResultCols 関数 |