SQLBulkOperations 函式

符合性
推出版本:ODBC 3.0 標準合規性:ODBC

總結
SQLBulkOperations 執行大量插入與大量書籤操作,包括更新、刪除及以書籤取回。

Syntax

  
SQLRETURN SQLBulkOperations(  
     SQLHSTMT       StatementHandle,  
     SQLUSMALLINT   Operation);  

論點

StatementHandle
[輸入]語句句柄。

Operation
[輸入]執行操作:

SQL_ADD SQL_UPDATE_BY_BOOKMARK SQL_DELETE_BY_BOOKMARK SQL_FETCH_BY_BOOKMARK

如需詳細資訊,請參閱。

Returns

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 SQLSTATEs),如果多列操作的一個或多個列發生錯誤(但不是全部),則回傳 SQL_SUCCESS_WITH_INFO SQL_ERROR,若單列操作發生錯誤則回傳 。

SQLSTATE 錯誤 說明
01000 一般警告 驅動程式特定的資訊訊息。 (函式會傳回SQL_SUCCESS_WITH_INFO。)
01004 字串資料右截斷 操作 參數被 SQL_FETCH_BY_BOOKMARK,對於資料型態為 SQL_C_CHAR 或 SQL_C_BINARY 的欄位回傳字串或二進位資料,會導致非空白字元或非 NULL 二進位資料被截斷。
01S01 排錯 操作 參數被 SQL_ADD,執行操作時一列或多列發生錯誤,但至少有一列成功新增。 (函式會傳回SQL_SUCCESS_WITH_INFO。)

(此錯誤僅在應用程式使用 ODBC 2 時出現。x 驅動程式。)
01S07 小數截斷 操作 參數SQL_FETCH_BY_BOOKMARK ,應用程式緩衝區的資料型別未SQL_C_CHAR或SQL_C_BINARY,且回傳至應用程式緩衝區的一個或多個欄位資料被截斷。 (對於數值 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 字串資料右截斷 將字元或二進位值指派到結果集中的欄位,會導致非空白(字元)或非空(二進位)字元或位元組被截斷。
22003 超出範圍的數值 運算參數為SQL_ADD或SQL_UPDATE_BY_BOOKMARK,且在結果集中將數值賦予欄位,導致整個(而非小數)部分的數字被截斷。

參數 Operation 是SQL_FETCH_BY_BOOKMARK的,若回傳一個或多個綁定欄位的數值,會導致有意義位數的遺失。
22007 無效的日期時間格式 操作參數為SQL_ADD或SQL_UPDATE_BY_BOOKMARK,且在結果集中的欄位指派日期或時間戳值會導致年份、月份或日期欄位超出範圍。

參數 Operation 是SQL_FETCH_BY_BOOKMARK的,若回傳一個或多個綁定欄位的日期或時間戳值,會導致年份、月份或日期欄位超出範圍。
22008 日期/時間欄位溢位 操作參數為SQL_ADD或SQL_UPDATE_BY_BOOKMARK,且對資料傳送至結果集欄位的日期時間運算執行時,結果的日期時間欄位(年份、月份、日、小時、分鐘或秒欄位)超出該欄位允許的值範圍,或根據格里曆自然時間規則判定無效。

操作 參數被 SQL_FETCH_BY_BOOKMARK,對從結果集取得資料時執行日期時間運算,結果的日期時間欄位(年份、月份、日、小時、分鐘或秒欄位)超出該欄位允許的值範圍,或根據格里曆自然時間規則無效。
22015 間隔欄位溢位 Operation參數為SQL_ADD或SQL_UPDATE_BY_BOOKMARK,且將精確的數值或區間C型別指派到區間SQL資料型別時,會導致有效位數的遺失。

行動 論點 則SQL_ADD或 SQL_UPDATE_BY_BOOKMARK;當指派到區間 SQL 型別時,區間 SQL 型別中沒有 C 型別的值表示。

操作 參數被 SQL_FETCH_BY_BOOKMARK,從精確的數值或區間 SQL 類型指派到區間 C 類型時,會導致前導欄位中缺少有效數字。

行動 論點 SQL_FETCH_BY_BOOKMARK;當指派到區間 C 類型時,則不會表示該區間 C 類型中 SQL 類型的值。
22018 轉換規格的字元值無效 行動 論點 SQL_FETCH_BY_BOOKMARK;C 型態則是精確或近似數值、日期時間或區間資料型態;欄位的 SQL 型態是字元資料型別;而欄位中的值並非束縛 C 類型的有效文字。

論點 Operation 是SQL_ADD或 SQL_UPDATE_BY_BOOKMARK;SQL 型別則是精確或近似的數值、日期時間或區間資料型別;C型則SQL_C_CHAR;而欄位中的值並非綁定 SQL 型別的有效文字。
23000 完整性條件約束違規 操作參數為SQL_ADD、SQL_DELETE_BY_BOOKMARK或SQL_UPDATE_BY_BOOKMARK,且完整性約束被違反。

操作 參數被 SQL_ADD,未綁定的欄位定義為 NOT NULL,且沒有預設值。

Operation 參數SQL_ADD,綁定StrLen_or_IndPtr緩衝區指定的長度SQL_COLUMN_IGNORE,且欄位沒有預設值。
24000 無效的數據指標狀態 StatementHandle 處於執行狀態,但沒有任何結果集與 StatementHandle 相關聯。
40001 串行化失敗 該交易因與另一筆交易發生資源死結而被回滾。
40003 語句完成未知 此函式執行期間相關聯的連接失敗,且無法判斷交易的狀態。
42000 語法錯誤或存取違規 驅動程式無法鎖定該列以執行 Operation 參數中要求的操作。
44000 WITH CHECK OPTION 違規 操作參數為SQL_ADD或SQL_UPDATE_BY_BOOKMARK,插入或更新是在一個已檢視的表格(或由該檢視表格衍生的表格)上執行,該表格是透過指定 WITH CHECK OPTION 建立的,使得一個或多個受插入或更新影響的列將不再出現在檢視表格中。
HY000 一般誤差 發生錯誤,其中沒有特定的 SQLSTATE,也沒有定義任何實作特定的 SQLSTATE。 *MessageText 緩衝區中 SQLGetDiagRec回的錯誤訊息描述錯誤及其原因。
HY001 記憶體配置錯誤 驅動程式無法配置支援執行或完成函式所需的記憶體。
HY008 行動取消 已針對 StatementHandle 啟用異步處理。 已呼叫函式,並在完成執行之前,在 StatementHandle 上呼叫 SQLCancelSQLCancelHandle。 然後在 StatementHandle再次呼叫函式。

呼叫函式,並在完成執行之前,從多線程應用程式中的不同線程呼叫語句Handle 或 SQLCancelHandle
HY010 函式順序錯誤 (DM) 已針對與 StatementHandle 相關聯的連接句柄呼叫異步執行函式。 當呼叫 SQLBulkOperations 函式時,這個非同步函式仍在執行中。

(DM) 已針對 StatementHandle 呼叫 SQLExecuteSQLExecDirectSQLMoreResults,並傳回SQL_PARAM_DATA_AVAILABLE。 在擷取所有數據流參數的數據之前,會呼叫此函式。

(DM) 指定的 StatementHandle 並未處於執行狀態。 該函式在未先呼叫 SQLExecDirectSQLExecute 或目錄函式的情況下被呼叫。

(DM) 呼叫 StatementHandle 的異步執行函式(而非此函式),並在呼叫此函式時仍在執行中。

(DM) SQLExecuteSQLExecDirectSQLSetPos 被呼叫 StatementHandle 並返回SQL_NEED_DATA。 在針對所有數據執行中參數或數據行傳送數據之前,會呼叫此函式。

(DM)駕駛員是ODBC 2型。x 驅動程式,而 SQLBulkOperationsSQLFetchScrollSQLFetch 之前,先呼叫 StatementHandle

(DM) SQLBulkOperations 是在 StatementHandle 上呼叫 SQLExtendedFetch 後被呼叫的。
HY011 無法立即設定屬性 (DM)駕駛員是ODBC 2型。x 驅動程式,SQL_ATTR_ROW_STATUS_PTR 陳述式屬性則在呼叫 SQLFetchSQLFetchScrollSQLBulkOperations 之間設定。
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欄位取得,可透過呼叫 SQLDescribeColSQLColAttributeSQLGetDescField 取得。)
HY092 屬性識別碼無效 (DM) Operation 參數所指定的值無效。

Operation參數為SQL_ADD、SQL_UPDATE_BY_BOOKMARK或SQL_DELETE_BY_BOOKMARK,SQL_ATTR_CONCURRENCY語句屬性設為SQL_CONCUR_READ_ONLY。

操作參數為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 連線已逾時 在數據源回應要求之前,連線逾時期限已過期。 線上逾時期間是透過 SQLSetConnectAttr 來設定,SQL_ATTR_CONNECTION_TIMEOUT。
IM001 驅動程式不支援此函式 (DM) 與 StatementHandle 相關聯的驅動程式不支援 函式。
IM017 在異步通知模式中停用輪詢 每當使用通知模型時,輪詢就會停用。
IM018 尚未呼叫 SQLCompleteAsync ,以完成此句柄上的先前異步操作。 如果句柄上的上一個函式呼叫傳回SQL_STILL_EXECUTING且啟用通知模式, 則必須在句柄上呼叫 SQLCompleteAsync ,才能執行後續處理並完成作業。

評論

Caution

關於可以呼叫哪些陳述式狀態, SQLBulkOperations 可以被呼叫,以及它必須做什麼才能與 ODBC 2 相容的資訊。x個應用程式, 請參閱附錄G:向下相容驅動程式指引中的 區塊游標、可捲動游標與向下相容 性章節。

應用程式使用 SQLBulkOperations 對應當前查詢的基底資料表或檢視執行以下操作:

  • 新增列。

  • 更新一組列,每列以書籤標示。

  • 刪除一組每列以書籤標示的列。

  • 取得一組列,每列以書籤標示。

呼叫 SQLBulkOperations 後,區塊游標位置未定義。 應用程式必須呼叫 SQLFetchScroll 來設定游標位置。 應用程式應僅以 SQL_FETCH_FIRST、SQL_FETCH_LAST、SQL_FETCH_ABSOLUTE 或 SQL_FETCH_BOOKMARK 的 FetchOrientation 參數呼叫 SQLFetchScroll。 若應用程式呼叫 SQLFetchSQLFetchScroll ,並使用 SQL_FETCH_PRIOR、SQL_FETCH_NEXT 或 SQL_FETCH_RELATIVE 的 FetchOrientation 參數,游標位置則未定義。

在呼叫 SQLBulkOperations 的批量操作中,可以將呼叫 SQLBindCol 中指定的欄位長度/指示符緩衝區設為 SQL_COLUMN_IGNORE 來忽略欄位。

應用程式在呼叫 SQLBulkOperations 時不必設定 SQL_ATTR_ROW_OPERATION_PTR 語句屬性,因為在執行 Bulk 運算時,列不可忽略。

SQL_ATTR_ROWS_FETCHED_PTR 陳述句屬性所指向的緩衝區包含呼叫 SQLBulkOperations 所影響的列數。

Operation 參數為 SQL_ADD 或 SQL_UPDATE_BY_BOOKMARK,且與游標相關的查詢規範 select-list 包含多個指向同一欄位的參考時,驅動程式會自行定義是否產生錯誤,或是驅動程式忽略重複的參考並執行所請求的操作。

欲了解更多如何使用 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. 呼叫 SQLBulkOperationsStatementHandle, 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。 欲了解更多資訊,請參閱本函式參考文獻後面的「提供大量插入與更新的長資料」。

應用程式在呼叫 SQLBulkOperations 之前,不必先呼叫 SQLFetchSQLFetchScroll(除非是針對 ODBC 2 時)。x 驅動程式;參見向下相容性與標準合規)。

若在包含重複欄位的游標上呼叫 SQLBulkOperations,且 操作參數為 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. 呼叫 SQLBulkOperationsStatementHandle, SQL_UPDATE_BY_BOOKMARK)。

    Note

    如果應用程式已設定 SQL_ATTR_ROW_STATUS_PTR 陳述式屬性,它可以檢查此陣列以查看操作結果。

  8. 可選擇性呼叫 SQLBulkOperationsStatementHandle, SQL_FETCH_BY_BOOKMARK) 將資料取回綁定的應用程式緩衝區,以驗證更新是否已發生。

  9. 若資料已更新,驅動程式會將相應列的列狀態陣列值改為SQL_ROW_UPDATED。

SQLBulkOperations 執行的大量更新可透過呼叫 SQLParamDataSQLPutData 來包含長資料。 欲了解更多資訊,請參閱本函式參考文獻後面的「提供大量插入與更新的長資料」。

如果書籤在游標間持續存在,應用程式在透過書籤更新前,就不需要呼叫 SQLFetchSQLFetchScroll 。 它可以使用從先前游標儲存的書籤。 若書籤無法在游標間持續存在,應用程式必須呼叫 SQLFetchSQLFetchScroll 來取得書籤。

若在包含重複欄位的游標上呼叫 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. 呼叫 SQLBulkOperationsStatementHandle, SQL_FETCH_BY_BOOKMARK)。

  7. 如果應用程式已設定 SQL_ATTR_ROW_STATUS_PTR 陳述式屬性,它可以檢查此陣列以查看操作結果。

如果書籤在游標間持續存在,應用程式在以書籤擷取前就不需要呼叫 SQLFetchSQLFetchScroll 。 它可以使用從先前游標儲存的書籤。 若書籤無法跨游標持續存在,應用程式必須呼叫一次 SQLFetchSQLFetchScroll 來取得書籤。

使用書籤執行大量刪除

要使用 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. 呼叫 SQLBulkOperationsStatementHandle, SQL_DELETE_BY_BOOKMARK)。

  7. 如果應用程式已設定 SQL_ATTR_ROW_STATUS_PTR 陳述式屬性,它可以檢查此陣列以查看操作結果。

如果書籤在游標間持續存在,應用程式刪除書籤前不必呼叫 SQLFetchSQLFetchScroll 。 它可以使用從先前游標儲存的書籤。 若書籤無法跨游標持續存在,應用程式必須呼叫一次 SQLFetchSQLFetchScroll 來取得書籤。

提供大量插入與更新所需的長資料

透過呼叫 SQLBulkOperations 來提供大量插入與更新的長資料。 要插入或更新長資料,應用程式除了本主題前述「執行批量插入」與「使用書籤執行大量更新」章節所述步驟外,還需執行以下步驟。

  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 時,若有執行時資料欄位,函式會回傳 SQL_NEED_DATA,並進入步驟 3,隨後進行步驟。 (若執行時沒有資料欄位,則程序完成。)

  3. 應用程式呼叫 SQLParamData ,取得第一個執行時資料欄位 *TargetValuePtr 緩衝區的位址。 SQLParamData 會傳回SQL_NEED_DATA。 應用程式會從 *TargetValuePtr 緩衝區取得應用程式定義的值。

    Note

    雖然數據執行時參數類似於數據執行數據行,但 SQLParamData傳回的值會針對每個數據行不同。

    執行時資料欄位是列集中的欄位,當資料在用 SQLBulkOperations 更新或插入資料時,會以 SQLPutData 傳送。 它們會與 SQLBindCol 系結。 SQLParamData 回傳的值是正在處理的 *TargetValuePtr 緩衝區中該列的位址。

  4. 應用程式會呼叫 SQLPutData 一次或多次,以傳送欄位的資料。 若無法在 SQLPutData 指定的 *TargetValuePtr 緩衝區回傳所有資料值,則需多次呼叫;只有在將字元C資料傳送到具有字元、二進位或資料來源特定資料型別的欄位,或將二進位C資料傳送到具有字元、二進位或資料來源特定資料型別的欄位時,才允許對同一欄位呼叫多次SQLPutData

  5. 應用程式再次呼叫 SQLParamData ,以表示該欄位的所有資料已送出。

    • 若有更多執行時資料欄位, SQLParamData 會回傳SQL_NEED_DATA及下一個執行時資料欄位的 TargetValuePtr 緩衝區位址。 應用程式會重複步驟 4 和 5。

    • 如果執行時的資料欄位已無,則程序完成。 如果該語句成功執行, SQLParamData 會回傳 SQL_SUCCESS 或 SQL_SUCCESS_WITH_INFO;若執行失敗,則回傳SQL_ERROR。 此時, SQLParamData 可以回傳任何 SQLBulkOperations 能回傳的 SQLSTATE。

若操作被取消或 SQLParamDataSQLPutData 發生錯誤,且 SQLBulkOperations 回傳SQL_NEED_DATA且所有執行時資料尚未傳送,應用程式只能呼叫 SQLCancelSQLGetDiagFieldSQLGetDiagRecSQLGetFunctionsSQLParamDataSQLPutData ,來取得該語句或與該語句相關的連線。 如果它呼叫任何其他函式來執行該語句或與該語句相關的連線,函式會回傳 SQL_ERROR 和 SQLSTATE HY010(函式序列錯誤)。

如果應用程式呼叫 SQLCancel ,而驅動程式仍需要執行時資料欄位的資料,驅動程式會取消該操作。 應用程式接著可以再次呼叫 SQLBulkOperations ;取消不會影響游標狀態或當前游標位置。

列狀態陣列

列狀態陣列包含在呼叫 SQLBulkOperations 後,列集中每一列資料的狀態值。 驅動程式在呼叫 SQLFetchSQLFetchScrollSQLSetPosSQLBulkOperations 後,設定此陣列中的狀態值。 若在 SQLBulkOperations 之前未呼叫 SQLFetchSQLFetchScroll,則此陣列最初會由呼叫 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 函式