SQLBulkOperations 関数

適合 性
導入されたバージョン:ODBC 3.0 規格準拠:ODBC

Summary
SQLBulkOperations は、ブックマークによる更新、削除、フェッチを含む一括挿入および一括ブックマーク操作を実行します。

構文

  
SQLRETURN SQLBulkOperations(  
     SQLHSTMT       StatementHandle,  
     SQLUSMALLINT   Operation);  

引数

StatementHandle
[入力]ステートメント ハンドル。

Operation
[入力]実行する操作:

SQL_ADD SQL_UPDATE_BY_BOOKMARK SQL_DELETE_BY_BOOKMARK SQL_FETCH_BY_BOOKMARK

詳細については、「コメント」を参照してください。

返品

SQL_SUCCESS、SQL_SUCCESS_WITH_INFO、SQL_NEED_DATA、SQL_STILL_EXECUTING、SQL_ERROR、またはSQL_INVALID_HANDLE。

Diagnostics

SQLBulkOperationsがSQL_ERRORまたはSQL_SUCCESS_WITH_INFOを返す場合、SQLGetDiagRecを呼び出してHandleTypeをSQL_HANDLE_STMT、HandleをStatementHandleで呼び出すことで関連するSQLSTATE値を取得できます。 以下の表は 、通常SQLBulkOperationsが返すSQLSTATE の値を一覧にし、それぞれをこの関数の文脈で説明しています。「(DM)」という表記は、ドライバーマネージャーが返すSQLstateの記述の前に記載されます。 特に明記されていない限り、各 SQLSTATE 値に関連付けられている戻りコードはSQL_ERROR。

SQL_SUCCESS_WITH_INFOまたはSQL_ERRORを返せるすべてのSQLSTATE(01xxx SQLSTATEを除く)については、複数行操作の1行以上でエラーが発生した場合はSQL_SUCCESS_WITH_INFO返し、単一行操作でエラーが発生した場合はSQL_ERROR返します。

SQLSTATE エラー Description
01000 一般的な警告 ドライバー固有の情報メッセージ。 (関数はSQL_SUCCESS_WITH_INFOを返します。
01004 文字列データの右切り切り Operation引数はSQL_FETCH_BY_BOOKMARKされ、SQL_C_CHARまたはSQL_C_BINARYのデータ型を持つ列に対して文字列やバイナリデータが返されると、非空文字や非NULLのバイナリデータの切り捨てが生じました。
01S01 エラー・イン・ロー Operationの引数はSQL_ADDされ、操作中に1行以上でエラーが発生しましたが、少なくとも1行は正常に追加されました。 (関数はSQL_SUCCESS_WITH_INFOを返します。

(このエラーは、アプリケーションがODBC 2を扱っている場合にのみ発生します。x ドライバー。)
01S07 小数部の切り捨て Operation引数はSQL_FETCH_BY_BOOKMARKされ、アプリケーションバッファのデータ型はSQL_C_CHARやSQL_C_BINARYではなく、1つ以上の列に対してアプリケーションバッファに戻されたデータは切り詰められていました。 (数値Cデータ型では、分数部分が切り詰められました。時間成分を含む時間、タイムスタンプ、区間Cのデータ型では、分数部分が切り捨てられています。)

(関数はSQL_SUCCESS_WITH_INFOを返します。
07006 制限付きデータ型属性違反 Operation引数がSQL_FETCH_BY_BOOKMARKされ、結果セット内のカラムの値がSQLBindColの呼び出し時に指定されたTargetType引数で指定されたデータ型に変換できませんでした。

Operation引数はSQL_UPDATE_BY_BOOKMARKまたはSQL_ADDであり、アプリケーションバッファ内のデータ値は結果セット内の列のデータ型に変換できませんでした。
07009 無効な記述子インデックス 項 Operation は SQL_ADD であり、ある列は結果セットの列数より大きい列番号で結ばれていました。
21S02 派生テーブルの次数が列リストと一致しない 議論の「 作戦 」はSQL_UPDATE_BY_BOOKMARKであった。また、すべての列が非バウンドまたは読み取り専用であったり、バウンドされた長さ/インジケーターバッファの値がSQL_COLUMN_IGNOREされたため、どの列も更新できませんでした。
22001 文字列データの右切り切り 結果セット内の列に文字や2進数の値を割り当てると、非空欄(文字の場合)またはノンヌル(バイナリの場合)文字やバイトが切り詰められました。
22003 範囲外の数値 Operationの引数はSQL_ADDまたはSQL_UPDATE_BY_BOOKMARKであり、結果セットの列に数値を割り当てると、その数値の全体(分数ではなく)部分が切り詰められました。

Operationという引数はSQL_FETCH_BY_BOOKMARKであり、1つ以上のバウンドされた列の数値を返すと有意な桁数が失われることになります。
22007 datetime 形式が無効です Operationの引数はSQL_ADDまたはSQL_UPDATE_BY_BOOKMARKであり、結果セット内の列に日付やタイムスタンプの値が割り当てられると、年、月、日のフィールドが範囲外になってしまいました。

Operationという引数はSQL_FETCH_BY_BOOKMARKであり、1つ以上のバウンディングされた列に対して日付やタイムスタンプの値を返すと、年、月、日のフィールドが範囲外になってしまいます。
22008 日付/時刻フィールドオーバーフロー Operationの引数はSQL_ADDまたはSQL_UPDATE_BY_BOOKMARKであり、データが結果セットの列に送信される際にdatetimeフィールド(年、月、日、時、分、または秒)が、そのフィールドの許容値の範囲外に収まるか、グレゴリオ暦の自然な時間ルールに基づく無効となる結果となりました。

Operationの引数はSQL_FETCH_BY_BOOKMARKされ、結果セットから取得されたデータに対してdatetime算術を行った結果、datetimeフィールド(年、月、日、時、分、または秒)がフィールドの許容値の範囲外に属するか、グレゴリオ暦の自然な日付ルールに基づいて無効とされました。
22015 間隔フィールドのオーバーフロー Operationの引数はSQL_ADDまたはSQL_UPDATE_BY_BOOKMARKであり、正確な数値または区間C型を区間SQLデータ型に割り当てると、有意数字の損失が生じました。

作戦の議論はSQL_ADD、あるいは SQL_UPDATE_BY_BOOKMARK かのどちらかでした。インターバルSQL型に割り当てる際、その区間SQL型にC型の値を表現することはありませんでした。

Operationの引数はSQL_FETCH_BY_BOOKMARKされ、正確な数値または区間SQL型から区間C型に割り当てると、先頭フィールドの有数桁が失われました。

オペレーションの主張は、SQL_FETCH_BY_BOOKMARKであった。区間C型に割り当てる際、区間C型におけるSQL型の値を表現しませんでした。
22018 キャスト指定の文字値が無効です オペレーションの主張は、SQL_FETCH_BY_BOOKMARKであった。C型は正確な数値または近似数値、日付時間、または区間データ型でした。列のSQL型は文字データ型であり、また、列内の値は束縛されたC型の有効なリテラルではありませんでした。

議論 は「作戦 」SQL_ADDかSQL_UPDATE_BY_BOOKMARKであった。SQL型は正確な数値またはおおよその数値、日付時間、または区間データ型でした。CタイプはSQL_C_CHAR、また、列内の値がバウンドされたSQL型の有効なリテラルではなかった。
23000 整合性制約違反 操作の議論はSQL_ADD、SQL_DELETE_BY_BOOKMARK、またはSQL_UPDATE_BY_BOOKMARKであり、整合性制約が違反されました。

Operationの引数はSQL_ADDされており、バウンディングされていない列はNOT NULLとして定義され、デフォルトはありません。

Operationの引数はSQL_ADDされ、バウンドされたStrLen_or_IndPtrバッファで指定された長さはSQL_COLUMN_IGNOREされ、列にはデフォルト値がありませんでした。
24000 カーソル状態が無効 StatementHandleは実行中でしたが、StatementHandleには結果セットが関連付けられていませんでした。
40001 シリアル化エラー リソースが別のトランザクションとデッドロックしたため、トランザクションがロールバックされました。
40003 ステートメントの入力候補が不明です この関数の実行中に関連付けられた接続が失敗し、トランザクションの状態を特定できません。
42000 構文エラーまたはアクセス違反 ドライバーは Operation の引数で要求された操作を実行するために必要な行をロックすることができませんでした。
44000 WITH CHECK OPTION 違反 Operationの引数はSQL_ADDまたはSQL_UPDATE_BY_BOOKMARKであり、挿入または更新はWITH CHECK OPTIONを指定して作成されたビューテーブル(またはビューテーブルから派生したテーブル)上で行われ、挿入または更新の影響を受けた1行以上がビューテーブルに存在しなくなるようにしました。
HY000 一般的なエラー 特定の SQLSTATE がなく、実装固有の SQLSTATE が定義されていないエラーが発生しました。 *MessageText バッファー内の SQLGetDiagRec によって返されるエラー メッセージには、エラーとその原因が記述されています。
HY001 メモリ割り当てエラー ドライバーは、関数の実行または完了をサポートするために必要なメモリを割り当てませんでした。
HY008 操作が取り消されました StatementHandle に対して非同期処理が有効になりました。 関数が呼び出され、実行が完了する前に、 SQLCancel または SQLCancelHandle が StatementHandle で呼び出されました。 その後、 StatementHandle で関数が再度呼び出されました。

関数が呼び出され、実行が完了する前に、 SQLCancel または SQLCancelHandle がマルチスレッド アプリケーション内の別のスレッドから StatementHandle で呼び出されました。
HY010 関数シーケンス エラー (DM) StatementHandle に関連付けられている接続ハンドルに対して非同期実行関数が呼び出されました。 この非同期関数は 、SQLBulkOperations 関数が呼び出された時点でも実行中でした。

(DM) SQLExecute、 SQLExecDirect、または SQLMoreResultsStatementHandle が呼び出され、SQL_PARAM_DATA_AVAILABLEが返されました。 この関数は、すべてのストリーミング パラメーターのデータが取得される前に呼び出されました。

(DM) 指定された StatementHandle は実行状態にありませんでした。 この関数は、 まずSQLExecDirect、 SQLExecute、またはカタログ関数を呼び出すことなく呼び出しられました。

(DM) 非同期実行関数 (この関数ではない) が StatementHandle に対して呼び出されこの関数が呼び出されたときにはまだ実行されていました。

(DM) SQLExecute、SQLExecDirect、またはSQLSetPosがStatementHandleのために呼び出され、返SQL_NEED_DATA。 この関数は、すべての実行時データ パラメーターまたは列に対してデータが送信される前に呼び出されました。

(DM)運転手はODBC 2でした。xドライバー、そしてSQLBulkOperationsはSQLFetchScrollやSQLFetchが呼び出される前にStatementHandleとして呼び出されました。

(DM) SQLBulkOperationsは、StatementHandle上でSQLExtendedFetchが呼び出された後に呼び出されました。
HY011 現在、属性を設定できません (DM)運転手はODBC 2でした。x ドライバ、SQL_ATTR_ROW_STATUS_PTR文属性は SQLFetch または SQLFetchScroll および SQLBulkOperationsの呼び出し間に設定されていました。
HY013 メモリ管理エラー メモリが不足している可能性があるため、基になるメモリ オブジェクトにアクセスできなかったため、関数呼び出しを処理できませんでした。
HY090 文字列またはバッファーの長さが無効です 作戦の議論はSQL_ADD、あるいは SQL_UPDATE_BY_BOOKMARK かのどちらかでした。データ値はヌルポインタではありません。Cデータ型はSQL_C_BINARYまたはSQL_C_CHARでした。列長の値は0より小さいが、SQL_DATA_AT_EXEC、SQL_COLUMN_IGNORE、SQL_NTS、SQL_NULL_DATA、またはSQL_LEN_DATA_AT_EXEC_OFFSET以下ではなかった。

長さ/インジケーターバッファ内の値はSQL_DATA_AT_EXECでした。SQL型はSQL_LONGVARCHAR、SQL_LONGVARBINARY、または長データソース固有の長型のいずれかでした。 SQLGetInfo のSQL_NEED_LONG_DATA_LEN情報型は「Y」でした。

Operationの引数はSQL_ADDされ、SQL_ATTR_USE_BOOKMARK文属性はSQL_UB_VARIABLEに設定され、列0はこの結果セットのブックマークの最大長さに満たない長さのバッファに割り当てられていました。 (この長さはIRDのSQL_DESC_OCTET_LENGTHフィールドで利用可能で、 SQLDescribeCol、 SQLColAttribute、 またはSQLGetDescFieldを呼び出すことで取得できます。)
HY092 無効な属性識別子 (DM) Operation 引数に指定された値が無効でした。

Operationの引数はSQL_ADD、SQL_UPDATE_BY_BOOKMARK、またはSQL_DELETE_BY_BOOKMARKで、SQL_ATTR_CONCURRENCY文属性はSQL_CONCUR_READ_ONLYに設定されていました。

Operationの引数はSQL_DELETE_BY_BOOKMARK、SQL_FETCH_BY_BOOKMARK、またはSQL_UPDATE_BY_BOOKMARKであり、ブックマーク列はバインドされておらず、SQL_ATTR_USE_BOOKMARKS文属性もSQL_UB_OFFに設定されていました。
HY117 不明なトランザクション状態のため、接続が中断されます。 切断関数と読み取り専用関数のみが許可されます。 (DM) 中断状態の詳細については、「 SQLEndTran 関数を参照してください。
HYC00 省略可能な機能が実装されていません ドライバーやデータソースは、 Operation 引数で求められた操作をサポートしていません。
HYT00 タイムアウトの期限が切れました データ ソースが結果セットを返す前に、クエリのタイムアウト期間が期限切れになりました。 タイムアウト期間は SQLSetStmtAttr で設定され、 属性 引数はSQL_ATTR_QUERY_TIMEOUTです。
HYT01 接続がタイムアウトしました データ ソースが要求に応答する前に、接続タイムアウト期間の有効期限が切れています。 接続タイムアウト期間は、SQL_ATTR_CONNECTION_TIMEOUT SQLSetConnectAttr によって設定されます。
IM001 ドライバーは、この関数をサポートしていません (DM) StatementHandle に関連付けられているドライバーは、関数をサポートしていません。
IM017 非同期通知モードでポーリングが無効になっている 通知モデルが使用されるたびに、ポーリングは無効になります。
IM018 SQLCompleteAsync は、このハンドルに対する前の非同期操作を完了するために呼び出されていません。 ハンドルに対する前の関数呼び出しがSQL_STILL_EXECUTINGを返し、通知モードが有効になっている場合は、後処理を実行して操作を完了するために、 SQLCompleteAsync をハンドルで呼び出す必要があります。

Comments

Caution

SQLBulkOperationsを呼び出せる文の状態や、ODBC 2との互換性のために何をすべきかについての情報。xのアプリケーションについては、付録G:後方互換性のためのドライバーガイドラインのブロックカーソル、スクロール可能カーソル、後方互換性のセクションを参照してください。

アプリケーションは SQLBulkOperations を用いて、現在のクエリに対応するベーステーブルまたはビューに対して以下の操作を行います。

  • 新しい行を追加します。

  • 各行がブックマークで識別される行のセットを更新します。

  • 各行がブックマークで識別される行のセットを削除します。

  • 各行がブックマークで識別される一連の行を取得します。

SQLBulkOperationsを呼び出した後、ブロックカーソルの位置は未定義になります。 アプリケーションはカーソル位置を設定するために SQLFetchScroll を呼び出さなければなりません。 アプリケーションは SQLFetchScroll をSQL_FETCH_FIRST、SQL_FETCH_LAST、SQL_FETCH_ABSOLUTE、またはSQL_FETCH_BOOKMARKの FetchOrientation 引数でのみ呼び出すべきです。 アプリケーションが SQLFetch または SQLFetchScroll をSQL_FETCH_PRIOR、SQL_FETCH_NEXT、またはSQL_FETCH_RELATIVEの FetchOrientation 引数で呼び出す場合、カーソル位置は未定義となります。

SQLBulkOperationsの呼び出しで行われる一括操作では、SQLBindCol呼び出しで指定された列長/インジケーターバッファをSQL_COLUMN_IGNOREに設定することで、カラムを無視できます。

アプリケーションがSQLBulkOperationsを呼び出す際にSQL_ATTR_ROW_OPERATION_PTR文属性を設定する必要はありません。なぜなら、この関数で一括操作を行う際に行を無視できないからです。

SQL_ATTR_ROWS_FETCHED_PTR文属性が指すバッファには 、SQLBulkOperationsの呼び出しによって影響を受ける行数が含まれています。

Operation引数がSQL_ADDまたはSQL_UPDATE_BY_BOOKMARKで、カーソルに関連付けられたクエリ仕様のselectリストに同じ列への参照が複数ある場合、エラーが発生するか、ドライバが重複した参照を無視して要求された操作を実行するかはドライバーで定義されます。

SQLBulkOperationsの使い方については、「SQLBulkOperationsによるデータの更新」をご覧ください。

バルクインサートの実施

SQLBulkOperationsでデータを挿入するには、アプリケーションは以下の手順を実行します。

  1. 結果セットを返すクエリを実行します。

  2. SQL_ATTR_ROW_ARRAY_SIZE文属性を挿入したい行数に設定します。

  3. 挿入したいデータをバインドするために SQLBindCol を呼び出します。 データはSQL_ATTR_ROW_ARRAY_SIZEの値に等しいサイズの配列に結合されます。

    Note

    SQL_ATTR_ROW_STATUS_PTR文属性が指す配列のサイズはSQL_ATTR_ROW_ARRAY_SIZEに等しいか、SQL_ATTR_ROW_STATUS_PTRはヌルポインタであるべきです。

  4. SQLBulkOperations(StatementHandle, SQL_ADD)を呼び出して挿入を行います。

  5. アプリケーションがSQL_ATTR_ROW_STATUS_PTR文属性を設定している場合、この配列を検査して操作の結果を確認できます。

アプリケーションが SQLBulkOperations を呼び出す前に列0をバインドし、 Operation 引数がSQL_ADDの場合、ドライバは新たに挿入された行のブックマーク値でバウンドされた列0バッファを更新します。 これを実現するには、アプリケーションが文を実行する前にSQL_ATTR_USE_BOOKMARKS文属性をSQL_UB_VARIABLEに設定していなければなりません。 (これはODBC 2では機能しません。x ドライバー。)

SQLBulkOperationsでは、SQLParamDataやSQLPutDataへの呼び出しを使って、長データを部分的に追加できます。 詳細については、この関数参照の後半にある「Provide Long Data for Bulk Inserts and Updates」をご覧ください。

アプリケーションがSQLBulkOperationsを呼び出す前にSQLFetchやSQLFetchScrollを呼び出す必要はありません(ODBC 2に対抗する場合を除く)。x ドライバー;詳細は「後方互換性および標準準拠」を参照してください。

この動作は、重複列を含むカーソル上で SQLBulkOperationsが Operation 引数SQL_ADDを付けて呼び出された場合にドライバーで定義されます。 ドライバはドライバ定義のSQLSTATEを返したり、結果セットの最初の列にデータを追加したり、他のドライバ定義の動作を実行したりできます。

ブックマークを使った一括更新の実施

SQLBulkOperationsでブックマークを使って一括更新を行う場合、アプリケーションは以下のステップを順番に実行します。

  1. SQL_ATTR_USE_BOOKMARKS文属性をSQL_UB_VARIABLEに設定します。

  2. 結果セットを返すクエリを実行します。

  3. SQL_ATTR_ROW_ARRAY_SIZE文の属性を更新したい行数に設定します。

  4. 更新したいデータをバインドするために SQLBindCol を呼び出します。 データはSQL_ATTR_ROW_ARRAY_SIZEの値に等しいサイズの配列に結合されます。 また、 SQLBindCol を呼び出して列0(ブックマーク列)をバインドします。

  5. 更新したい行のブックマークを列0に割り当てられた配列にコピーします。

  6. バウンドバッファ内のデータを更新します。

    Note

    SQL_ATTR_ROW_STATUS_PTR文属性が指す配列のサイズはSQL_ATTR_ROW_ARRAY_SIZEに等しく、SQL_ATTR_ROW_STATUS_PTRはヌルポインタであるべきです。

  7. SQLBulkOperations(StatementHandle, SQL_UPDATE_BY_BOOKMARK)を呼び出します。

    Note

    アプリケーションがSQL_ATTR_ROW_STATUS_PTR文属性を設定している場合、この配列を検査して操作の結果を確認できます。

  8. オプションで SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK)を呼び出して、更新が行われたかバウンドされたアプリケーションバッファにデータを取得します。

  9. データが更新されている場合、ドライバーは該当する行の行ステータス配列の値をSQL_ROW_UPDATEDに変更します。

SQLBulkOperationsによる大量更新は、SQLParamDataやSQLPutDataへの呼び出しを用いて長データを含めることができます。 詳細については、この関数参照の後半にある「Provide Long Data for Bulk Inserts and Updates」をご覧ください。

ブックマークがカーソル間で持続する場合、アプリケーションはブックマークで更新する前に SQLFetch や SQLFetchScroll を呼び出す必要はありません。 以前のカーソルから保存したブックマークを使うことができます。 ブックマークがカーソル間で永続しない場合は、アプリケーションは SQLFetch または SQLFetchScroll を呼び出してブックマークを取得しなければなりません。

この動作は、重複列を含むカーソル上で SQLBulkOperationsが Operation 引数SQL_UPDATE_BY_BOOKMARKで呼び出された場合、ドライバーで定義されます。 ドライバはドライバ定義のSQLSTATEを返したり、結果セットの最初の列を更新したり、その他のドライバ定義の動作を実行したりできます。

ブックマークを使った大量取ってくる方法

SQLBulkOperationsでブックマークを使った一括フェッチを行う場合、アプリケーションは以下の手順を順番に実行します。

  1. SQL_ATTR_USE_BOOKMARKS文属性をSQL_UB_VARIABLEに設定します。

  2. 結果セットを返すクエリを実行します。

  3. SQL_ATTR_ROW_ARRAY_SIZE文属性を取得したい行数に設定します。

  4. 取得したいデータをバインドするために SQLBindCol を呼び出します。 データはSQL_ATTR_ROW_ARRAY_SIZEの値に等しいサイズの配列に結合されます。 また、 SQLBindCol を呼び出して列0(ブックマーク列)をバインドします。

  5. 取得したい行のブックマークを列0に割り当てられた配列にコピーします。 (これは、アプリケーションがすでに別途ブックマークを取得していることを前提としています。)

    Note

    SQL_ATTR_ROW_STATUS_PTR文属性が指す配列のサイズはSQL_ATTR_ROW_ARRAY_SIZEに等しく、SQL_ATTR_ROW_STATUS_PTRはヌルポインタであるべきです。

  6. SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK)を呼び出します。

  7. アプリケーションがSQL_ATTR_ROW_STATUS_PTR文属性を設定している場合、この配列を検査して操作の結果を確認できます。

ブックマークがカーソル間で持続する場合、アプリケーションはブックマークで取得する前に SQLFetch や SQLFetchScroll を呼び出す必要はありません。 以前のカーソルから保存したブックマークを使うことができます。 ブックマークがカーソル間で永続しない場合は、アプリケーションは SQLFetch または SQLFetchScroll を一度呼び出してブックマークを取得しなければなりません。

ブックマークを使った一括削除の実施

SQLBulkOperationsを使ってブックマークを使った一括削除を行う場合、アプリケーションは以下の手順を順番に実行します。

  1. SQL_ATTR_USE_BOOKMARKS文属性をSQL_UB_VARIABLEに設定します。

  2. 結果セットを返すクエリを実行します。

  3. SQL_ATTR_ROW_ARRAY_SIZE文属性を削除したい行数に設定します。

  4. SQLBindColを呼び出して列0(ブックマーク列)をバインドします。

  5. 削除したい行のブックマークを列0に割り当てられた配列にコピーします。

    Note

    SQL_ATTR_ROW_STATUS_PTR文属性が指す配列のサイズはSQL_ATTR_ROW_ARRAY_SIZEに等しく、SQL_ATTR_ROW_STATUS_PTRはヌルポインタであるべきです。

  6. SQLBulkOperations(StatementHandle, SQL_DELETE_BY_BOOKMARK)を呼び出します。

  7. アプリケーションがSQL_ATTR_ROW_STATUS_PTR文属性を設定している場合、この配列を検査して操作の結果を確認できます。

ブックマークがカーソル間で持続している場合、アプリケーションはブックマークで削除する前に SQLFetch や SQLFetchScroll を呼び出す必要はありません。 以前のカーソルから保存したブックマークを使うことができます。 ブックマークがカーソル間で永続しない場合は、アプリケーションは SQLFetch または SQLFetchScroll を一度呼び出してブックマークを取得しなければなりません。

大量挿入と更新のための長いデータの提供

SQLBulkOperationsの呼び出しによって、一括挿入や更新のために長データを提供できます。 長いデータを挿入または更新するには、アプリケーションは本トピックの「Perform Bulk Inserts」および「Perform Bulk Updates Using Bookmarks」セクションで説明した手順に加えて、以下の手順を実行します。

  1. SQLBindColを使ってデータをバインドすると、アプリケーションは実行時データカラム用の*TargetValuePtrバッファにカラム番号などのアプリケーション定義値を配置します。 この値は後で列を特定するために使われます。

    アプリケーションはSQL_LEN_DATA_AT_EXEC(長さ)マクロの結果を *StrLen_or_IndPtr バッファに配置します。 もしカラムのSQLデータ型がSQL_LONGVARBINARY、SQL_LONGVARCHAR、または長いデータソース固有のデータ型で、ドライバーが SQLGetInfoのSQL_NEED_LONG_DATA_LEN情報型として「Y」を返す場合、 長さ はパラメータに対して送信されるデータバイト数です。そうでなければ、非負の値でなければならず無視されます。

  2. SQLBulkOperationsが呼び出され、data-at-execution列がある場合、関数はSQL_NEED_DATAを返し、ステップ3に進みます。 (データ・アット・実行列がなければ、プロセスは完了します。)

  3. アプリケーションは SQLParamData を呼び出し、最初に処理されるデータ・アット・実行列の *TargetValuePtr バッファのアドレスを取得します。 SQLParamData はSQL_NEED_DATAを返します。 アプリケーションは *TargetValuePtr バッファからアプリケーション定義の値を取得します。

    Note

    実行時データ パラメーターは実行時データ列に似ていますが、 SQLParamData によって返される値はそれぞれ異なります。

    実行時データカラムは、行がSQLBulkOperationsで更新または挿入された際にSQLPutDataでデータが送信される行セット内のカラムです。 これらは、 SQLBindCol にバインドされます。 SQLParamDataが返す値は、処理中の*TargetValuePtrバッファの行のアドレスです。

  4. アプリケーションは SQLPutData を1回以上呼び出して、その列にデータを送ります。 SQLPutDataで指定された*TargetValuePtrバッファにすべてのデータ値を返せない場合は、複数の呼び出しが必要です。同じ列に対して複数回SQLPutDataを呼び出すのは、文字Cデータを文字、バイナリ、またはデータソース固有のデータ型を持つ列に送信する場合、または文字、バイナリ、またはデータソース固有のデータ型を持つ列に送信する場合のみ許可されます。

  5. アプリケーションは再び SQLParamData を呼び出し、すべてのデータがカラムに送信されたことを知らせます。

    • 実行時のデータカラムが多い場合、 SQLParamData は次に処理するデータ実行時カラムの TargetValuePtrバッファのアドレスとTargetValuePtr バッファのアドレスSQL_NEED_DATA返します。 アプリケーションは手順 4 と 5 を繰り返します。

    • もしデータ・アット・実行列がなければ、そのプロセスは完了します。 文が正常に実行された場合、 SQLParamData はSQL_SUCCESSまたはSQL_SUCCESS_WITH_INFOを返します。実行に失敗した場合はSQL_ERRORを返します。 この時点で、 SQLParamData は SQLBulkOperationsで返される任意のSQLSTATEを返すことができます。

SQLBulkOperationsがSQL_NEED_DATAを返し、すべての実行時データカラムのデータ送信前に操作がキャンセルされたりエラーが発生した場合、アプリケーションは文または文に関連する接続に対してSQLCancel、SQLGetDiagField、SQLGetDiagRec、SQLGetFunctions、SQLParamData、またはSQLPutDataのみを呼び出しることができます。 もし文や文に関連する接続に対して他の関数を呼び出すと、関数はSQL_ERRORとSQLSTATE HY010(関数列エラー)を返します。

もしアプリケーションが SQLCancel を呼び出している間に、ドライバが実行時のデータカラムにデータが必要な場合、ドライバはその操作をキャンセルします。 アプリケーションは再び SQLBulkOperations を呼び出せます。キャンセルはカーソルの状態や現在のカーソル位置には影響しません。

行の状態配列

行ステータス配列は 、SQLBulkOperationsを呼び出した後の各行のデータ値を表示します。 ドライバーは SQLFetch、 SQLFetchScroll、 SQLSetPos、または SQLBulkOperationsを呼び出した後、この配列のステータス値を設定します。 この配列は、SQLBulkOperationsの前にSQLFetchまたはSQLFetchScrollが呼び出されていない場合、SQLBulkOperationsへの呼び出しによって最初に入力されます。 この配列はSQL_ATTR_ROW_STATUS_PTR文属性によって指し示されます。 行の状態配列の要素数は、行セット内の行数(SQL_ATTR_ROW_ARRAY_SIZEステートメント属性で定義される)と等しくなければなりません。 この行ステータス配列に関する情報は SQLFetchを参照してください。

コード例

以下の例は、Customersテーブルから10行ずつデータを取得します。 その後、ユーザーに行動を促します。 ネットワークトラフィックを減らすために、例のバッファはバウンド配列内でローカルに更新、削除、挿入を行いますが、行セットデータより離れたオフセットで行います。 ユーザーがデータソースへの更新、削除、挿入を選択すると、コードは適切にバインディングオフセットを設定し、 SQLBulkOperationsを呼び出します。 簡便化のため、ユーザーは10回以上の更新、削除、挿入をバッファリングすることはできません。

// SQLBulkOperations_Function.cpp  
// compile with: ODBC32.lib  
#include <windows.h>  
#include <sqlext.h>  
#include "stdio.h"  
  
#define UPDATE_ROW 100  
#define DELETE_ROW 101  
#define ADD_ROW 102  
#define SEND_TO_DATA_SOURCE 103  
#define UPDATE_OFFSET 10  
#define INSERT_OFFSET 20  
#define DELETE_OFFSET 30  
  
// Define structure for customer data (assume 10 byte maximum bookmark size).  
typedef struct tagCustStruct {  
   SQLCHAR Bookmark[10];  
   SQLINTEGER BookmarkLen;  
   SQLUINTEGER CustomerID;  
   SQLINTEGER CustIDInd;  
   SQLCHAR CompanyName[51];  
   SQLINTEGER NameLenOrInd;  
   SQLCHAR Address[51];  
   SQLINTEGER AddressLenOrInd;  
   SQLCHAR Phone[11];  
   SQLINTEGER PhoneLenOrInd;  
} CustStruct;  
  
// Allocate 40 of these structures. Elements 0-9 are for the current rowset,  
// elements 10-19 are for the buffered updates, elements 20-29 are for  
// the buffered inserts, and elements 30-39 are for the buffered deletes.  
CustStruct CustArray[40];  
SQLUSMALLINT RowStatusArray[10], Action, RowNum, NumUpdates = 0, NumInserts = 0,  
NumDeletes = 0;  
SQLLEN BindOffset = 0;  
SQLRETURN retcode;  
SQLHENV henv = NULL;  
SQLHDBC hdbc = NULL;  
SQLHSTMT hstmt = NULL;  
  
int main() {  
   retcode = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);  
   retcode = SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER*)SQL_OV_ODBC3, 0);   
  
   retcode = SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc);   
   retcode = SQLSetConnectAttr(hdbc, SQL_LOGIN_TIMEOUT, (SQLPOINTER)5, 0);  
  
   retcode = SQLConnect(hdbc, (SQLCHAR*) "Northwind", SQL_NTS, (SQLCHAR*) NULL, 0, NULL, 0);  
   retcode = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt);  
  
   // Set the following statement attributes:  
   // SQL_ATTR_CURSOR_TYPE:           Keyset-driven  
   // SQL_ATTR_ROW_BIND_TYPE:         Row-wise  
   // SQL_ATTR_ROW_ARRAY_SIZE:        10  
   // SQL_ATTR_USE_BOOKMARKS:         Use variable-length bookmarks  
   // SQL_ATTR_ROW_STATUS_PTR:        Points to RowStatusArray  
   // SQL_ATTR_ROW_BIND_OFFSET_PTR:   Points to BindOffset  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER)SQL_CURSOR_KEYSET_DRIVEN, 0);  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_TYPE, (SQLPOINTER)sizeof(CustStruct), 0);  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)10, 0);  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_USE_BOOKMARKS, (SQLPOINTER)SQL_UB_VARIABLE, 0);  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_STATUS_PTR, RowStatusArray, 0);  
   retcode = SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_BIND_OFFSET_PTR, &BindOffset, 0);  
  
   // Bind arrays to the bookmark, CustomerID, CompanyName, Address, and Phone columns.  
   retcode = SQLBindCol(hstmt, 0, SQL_C_VARBOOKMARK, CustArray[0].Bookmark, sizeof(CustArray[0].Bookmark), &CustArray[0].BookmarkLen);  
   retcode = SQLBindCol(hstmt, 1, SQL_C_ULONG, &CustArray[0].CustomerID, 0, &CustArray[0].CustIDInd);  
   retcode = SQLBindCol(hstmt, 2, SQL_C_CHAR, CustArray[0].CompanyName, sizeof(CustArray[0].CompanyName), &CustArray[0].NameLenOrInd);  
   retcode = SQLBindCol(hstmt, 3, SQL_C_CHAR, CustArray[0].Address, sizeof(CustArray[0].Address), &CustArray[0].AddressLenOrInd);  
   retcode = SQLBindCol(hstmt, 4, SQL_C_CHAR, CustArray[0].Phone, sizeof(CustArray[0].Phone), &CustArray[0].PhoneLenOrInd);  
  
   // Execute a statement to retrieve rows from the Customers table.  
   retcode = SQLExecDirect(hstmt, (SQLCHAR*)"SELECT CustomerID, CompanyName, Address, Phone FROM Customers", SQL_NTS);  
  
   // Fetch and display the first 10 rows.  
   retcode = SQLFetchScroll(hstmt, SQL_FETCH_NEXT, 0);  
   // DisplayCustData(CustArray, 10);  
  
   // Call GetAction to get an action and a row number from the user.  
   // while (GetAction(&Action, &RowNum)) {  
   Action = SQL_FETCH_NEXT;  
   RowNum = 2;  
   switch (Action) {  
      case SQL_FETCH_NEXT:  
      case SQL_FETCH_PRIOR:  
      case SQL_FETCH_FIRST:  
      case SQL_FETCH_LAST:  
      case SQL_FETCH_ABSOLUTE:  
      case SQL_FETCH_RELATIVE:  
         // Fetch and display the requested data.  
         SQLFetchScroll(hstmt, Action, RowNum);  
         // DisplayCustData(CustArray, 10);  
         break;  
  
      case UPDATE_ROW:  
         // Check if we have reached the maximum number of buffered updates.  
         if (NumUpdates < 10) {  
            // Get the new customer data and place it in the next available element of  
            // the buffered updates section of CustArray, copy the bookmark of the row  
            // being updated to the same element, and increment the update counter.  
            // Checking to see we have not already buffered an update for this  
            // row not shown.  
            // GetNewCustData(CustArray, UPDATE_OFFSET + NumUpdates);  
            memcpy(CustArray[UPDATE_OFFSET + NumUpdates].Bookmark,  
               CustArray[RowNum - 1].Bookmark,  
               CustArray[RowNum - 1].BookmarkLen);  
            CustArray[UPDATE_OFFSET + NumUpdates].BookmarkLen =  
               CustArray[RowNum - 1].BookmarkLen;  
            NumUpdates++;  
         } else {  
            printf("Buffers full. Send buffered changes to the data source.");  
         }  
         break;  
      case DELETE_ROW:  
         // Check if we have reached the maximum number of buffered deletes.  
         if (NumDeletes < 10) {  
            // Copy the bookmark of the row being deleted to the next available element  
            // of the buffered deletes section of CustArray and increment the delete  
            // counter. Checking to see we have not already buffered an update for  
            // this row not shown.  
            memcpy(CustArray[DELETE_OFFSET + NumDeletes].Bookmark,  
               CustArray[RowNum - 1].Bookmark,  
               CustArray[RowNum - 1].BookmarkLen);  
  
            CustArray[DELETE_OFFSET + NumDeletes].BookmarkLen =  
               CustArray[RowNum - 1].BookmarkLen;  
  
            NumDeletes++;  
         } else  
            printf("Buffers full. Send buffered changes to the data source.");  
         break;  
  
      case ADD_ROW:  
         // reached maximum number of buffered inserts?  
         if (NumInserts < 10) {  
            // Get the new customer data and place it in the next available element of  
            // the buffered inserts section of CustArray and increment insert counter.  
            // GetNewCustData(CustArray, INSERT_OFFSET + NumInserts);  
            NumInserts++;  
         } else  
            printf("Buffers full. Send buffered changes to the data source.");  
         break;  
  
      case SEND_TO_DATA_SOURCE:  
         // If there are any buffered updates, inserts, or deletes, set the array size  
         // to that number, set the binding offset to use the data in the buffered  
         // update, insert, or delete part of CustArray, and call SQLBulkOperations to  
         // do the updates, inserts, or deletes. Because we will never have more than  
         // 10 updates, inserts, or deletes, we can use the same row status array.  
         if (NumUpdates) {  
            SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumUpdates, 0);  
            BindOffset = UPDATE_OFFSET * sizeof(CustStruct);  
            SQLBulkOperations(hstmt, SQL_UPDATE_BY_BOOKMARK);  
            NumUpdates = 0;  
         }  
  
         if (NumInserts) {  
            SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumInserts, 0);  
            BindOffset = INSERT_OFFSET * sizeof(CustStruct);  
            SQLBulkOperations(hstmt, SQL_ADD);  
            NumInserts = 0;  
         }  
  
         if (NumDeletes) {  
            SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)NumDeletes, 0);  
            BindOffset = DELETE_OFFSET * sizeof(CustStruct);  
            SQLBulkOperations(hstmt, SQL_DELETE_BY_BOOKMARK);  
            NumDeletes = 0;  
         }  
  
         // If there were any updates, inserts, or deletes, reset the binding offset  
         // and array size to their original values.  
         if (NumUpdates || NumInserts || NumDeletes) {  
            SQLSetStmtAttr(hstmt, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER)10, 0);  
            BindOffset = 0;  
         }  
         break;  
   }  
   // }  
  
   // Close the cursor.  
   SQLFreeStmt(hstmt, SQL_CLOSE);  
}  
~についての情報 参照先
結果セット内の列へのバッファーのバインド SQLBindCol 関数
ステートメント処理の取り消し SQLCancel 関数
データブロックのフェッチまたは結果セットのスクロール SQLFetchScroll 関数
記述子の単一フィールドを取得する方法 SQLGetDescField 関数
ディスクリプタの複数のフィールドを取得する方法 SQLGetDescRec 関数
記述子の単一フィールドを設定する SQLSetDescField 関数
ディスクリプタの複数フィールドを設定する SQLSetDescRec 関数
カーソルの位置調整、行セット内のデータの更新、データの更新・削除 SQLSetPos 関数
ステートメント属性の設定 SQLSetStmtAttr 関数