SQLBulkOperations 函式

一致性
引進的版本:ODBC 3.0 標準合規性:ODBC

摘要
SQLBulkOperations 會執行大量插入和大量書簽作業,包括依書簽進行更新、刪除和擷取。

語法

  
SQLRETURN SQLBulkOperations(  
     SQLHSTMT       StatementHandle,  
     SQLUSMALLINT   Operation);  

引數

StatementHandle
[輸入]語句控制碼。

運算
[輸入]要執行的作業:

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。

診斷

SQLBulkOperations 傳回SQL_ERROR或SQL_SUCCESS_WITH_INFO時,可以藉由呼叫 SQLGetDiagRec 搭配 SQL_HANDLE_STMT 的 HandleType 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 字串資料右截斷 Operation 引數是SQL_FETCH_BY_BOOKMARK,而針對資料類型為SQL_C_CHAR或SQL_C_BINARY的資料行傳回字串或二進位資料,會導致非空白字元或非 Null 二進位資料截斷。
01S01 資料列中的錯誤 Operation 引數SQL_ADD,在執行作業時發生一或多個資料列時發生錯誤,但至少一個資料列已成功新增。 (函式會傳回SQL_SUCCESS_WITH_INFO。)

(只有當應用程式使用 ODBC 2 時,才會引發此錯誤。 x driver.)
01S07 小數截斷 Operation 引數已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 衍生資料表的程度不符合資料行清單 引數 Operation 是SQL_UPDATE_BY_BOOKMARK,而且沒有資料行可更新,因為所有資料行都是未系結或唯讀的,或是系結長度/指標緩衝區中的值SQL_COLUMN_IGNORE。
22001 字串資料右截斷 將字元或二進位值指派給結果集中的資料行,導致截斷非空白(適用于字元)或非 Null 字元或位元組。
22003 超出範圍的數值 Operation 引數SQL_ADD或SQL_UPDATE_BY_BOOKMARK,並將數值指派給結果集中的資料行會導致截斷數位的整個部分(而不是小數部分)。

引數 Operation 已SQL_FETCH_BY_BOOKMARK,並傳回一或多個系結資料行的數值會導致有效位數遺失。
22007 不正確日期時間格式 Operation 引數SQL_ADD或SQL_UPDATE_BY_BOOKMARK,而將日期或時間戳記值指派給結果集中的資料行會導致年份、月份或日期欄位超出範圍。

引數 Operation 已SQL_FETCH_BY_BOOKMARK,並傳回一或多個系結資料行的日期或時間戳記值會導致年份、月份或日期欄位超出範圍。
22008 日期/時間欄位溢位 Operation 引數是SQL_ADD或SQL_UPDATE_BY_BOOKMARK,而且結果集中傳送至資料行的日期時間算術效能會導致日期時間欄位(年、月、日、小時、分鐘或第二個欄位)的結果落在欄位的允許範圍內,或根據西曆日期時間的自然規則而無效。

Operation 引數是SQL_FETCH_BY_BOOKMARK,而從結果集中擷取之資料的日期時間算術效能,會導致結果的日期時間欄位(年、月、日、小時、分鐘或第二個欄位)落在欄位的允許範圍內,或根據西曆日期時間的自然規則而無效。
22015 間隔欄位溢位 Operation 引數已SQL_ADD或SQL_UPDATE_BY_BOOKMARK,而將精確數值或間隔 C 類型指派給間隔 SQL 資料類型會導致重大數位遺失。

Operation 引數SQL_ADD或SQL_UPDATE_BY_BOOKMARK;指派給間隔 SQL 類型時,間隔 SQL 類型中沒有 C 型別的值標記法。

Operation 引數已SQL_FETCH_BY_BOOKMARK,並從確切的數值或間隔 SQL 類型指派給間隔 C 類型會導致前置欄位中的顯著數位遺失。

Operation 引數SQL_FETCH_BY_BOOKMARK;指派給間隔 C 類型時,在間隔 C 類型中沒有 SQL 類型的值標記法。
22018 轉換規格的字元值無效 Operation 引數是SQL_FETCH_BY_BOOKMARK;C 類型是確切或近似數值、日期時間或間隔資料類型;資料行的 SQL 類型是字元資料類型;而資料行中的值不是系結 C 型別的有效常值。

引數 Operation 是SQL_ADD或SQL_UPDATE_BY_BOOKMARK;SQL 類型是精確或近似數值、日期時間或間隔資料類型;C 類型是SQL_C_CHAR;而且資料行中的值不是系結 SQL 類型的有效常值。
23000 完整性條件約束違規 Operation 引數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 所建立的檢視資料表(或衍生自檢視資料表的資料表),這樣一或多個受插入或更新影響的資料列就不再出現在檢視資料表中。
HY000 一般錯誤 發生錯誤,其中沒有特定的 SQLSTATE,也沒有定義任何實作特定的 SQLSTATE。 *MessageText 緩衝區中 SQLGetDiagRec 回的錯誤訊息描述錯誤及其原因。
HY001 記憶體配置錯誤 驅動程式無法配置支援執行或完成函式所需的記憶體。
HY008 作業已取消 已針對 StatementHandle 啟用非同步處理。 已呼叫函式,並在完成執行之前, 在 StatementHandle 上 呼叫 SQLCancel SQLCancelHandle 。 然後在 StatementHandle 再次呼叫函式。

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

(DM) 已針對 StatementHandle 呼叫 SQLExecute SQLExecDirect SQLMoreResults ,並傳回SQL_PARAM_DATA_AVAILABLE。 在擷取所有資料流程參數的資料之前,會呼叫此函式。

(DM) 指定的 StatementHandle 未處於執行狀態。 未先呼叫 SQLExecDirect SQLExecute 或目錄函式,就會呼叫 函式。

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

(DM) 已針對 StatementHandle 呼叫 SQLExecute SQLExecDirect SQLSetPos ,並傳回SQL_NEED_DATA。 在針對所有資料執行中參數或資料行傳送資料之前,會呼叫此函式。

(DM) 驅動程式是 ODBC 2。 在呼叫 SQLFetchScroll 或 SQLFetch 之前 ,已針對 StatementHandle 呼叫 x 驅動程式和 SQLBulkOperations

(DM) SQLBulkOperations 是在 StatementHandle 上呼叫 SQLExtendedFetch 之後 呼叫的
HY011 無法立即設定屬性 (DM) 驅動程式是 ODBC 2。 x 驅動程式和 SQL_ATTR_ROW_STATUS_PTR 語句屬性是在呼叫 SQLFetch SQLFetchScroll SQLBulkOperations 之間設定。
HY013 記憶體管理錯誤 無法處理函式呼叫,因為基礎記憶體物件無法存取,可能是因為記憶體不足的情況。
HY090 不正確字串或緩衝區長度 Operation 引數是SQL_ADD或SQL_UPDATE_BY_BOOKMARK;資料值不是 null 指標;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 設定,其 Attribute 引數為 SQL_ATTR_QUERY_TIMEOUT。
HYT01 已超過連線逾時 在資料來源回應要求之前,連線逾時期限已過期。 連線逾時期間是透過 SQLSetConnectAttr 來設定,SQL_ATTR_CONNECTION_TIMEOUT。
IM001 驅動程式不支援此函式 (DM) 與 StatementHandle 相關聯的驅動程式不支援 函式。
IM017 在非同步通知模式中停用輪詢 每當使用通知模型時,輪詢就會停用。
IM018 尚未呼叫 SQLCompleteAsync ,以完成此控制碼上的先前非同步作業。 如果控制碼上的上一個函式呼叫傳回SQL_STILL_EXECUTING且啟用通知模式, 則必須在控制碼上呼叫 SQLCompleteAsync ,才能執行後續處理並完成作業。

註解

警告

如需可在 中呼叫 SQLBulkOperations 的語句 ,以及它必須執行哪些動作才能與 ODBC 2 相容的資訊。 x 應用程式,請參閱 附錄 G:回溯相容性的驅動程式指導方針中的區塊資料指標、可捲動的資料指標和回溯相容性 一節。

應用程式會使用 SQLBulkOperations 在對應至目前查詢的基表或檢視表上執行下列作業:

  • 新增資料列。

  • 更新一組資料列,其中每個資料列都是由書簽識別。

  • 刪除一組資料列,其中每個資料列都是由書簽識別。

  • 擷取一組資料列,其中每個資料列都是由書簽識別。

呼叫 SQLBulkOperations 之後,區塊資料指標位置是未定義的。 應用程式必須呼叫 SQLFetchScroll 來設定游標位置。 應用程式應該只 使用SQL_FETCH_FIRST、SQL_FETCH_LAST、SQL_FETCH_ABSOLUTE或SQL_FETCH_BOOKMARK的 FetchOrientation 引數呼叫 SQLFetchScroll 。 如果應用程式呼叫 SQLFetch 或 SQLFetchScroll 且其 FetchOrientation 引數為 SQL_FETCH_PRIOR、SQL_FETCH_NEXT 或 SQL_FETCH_RELATIVE,則資料指標位置未定義。

在呼叫 SQLBulkOperations 所執行的大量作業中可以忽略資料行,方法是將呼叫 SQLBindCol 中指定的資料行長度/指標緩衝區設定為SQL_COLUMN_IGNORE。

應用程式在呼叫 SQLBulkOperations 時不需要設定 SQL_ATTR_ROW_OPERATION_PTR 語句屬性,因為使用此函式執行大量作業時無法忽略資料列。

SQL_ATTR_ROWS_FETCHED_PTR 語句屬性所指向的緩衝區包含受 SQLBulkOperations 呼叫 影響的資料列數目。

當 Operation 引數SQL_ADD或SQL_UPDATE_BY_BOOKMARK,且與資料指標相關聯的查詢規格選取清單包含同一個資料行的多個參考時,不論產生錯誤還是驅動程式會忽略重複的參考並執行要求的作業,都是驅動程式定義。

如需如何使用 SQLBulkOperations 的詳細資訊,請參閱 使用 SQLBulkOperations 更新資料。

執行大量插入

若要使用 SQLBulkOperations 插入資料,應用程式會執行下列步驟順序:

  1. 執行傳回結果集的查詢。

  2. 將 SQL_ATTR_ROW_ARRAY_SIZE 語句屬性設定為想要插入的資料列數目。

  3. 呼叫 SQLBindCol 以系結想要插入的資料。 資料會系結至大小等於SQL_ATTR_ROW_ARRAY_SIZE值的陣列。

    注意

    SQL_ATTR_ROW_STATUS_PTR語句屬性所指向的陣列大小應等於 SQL_ATTR_ROW_ARRAY_SIZE,或SQL_ATTR_ROW_STATUS_PTR應該是 null 指標。

  4. 呼叫 SQLBulkOperations StatementHandle, SQL_ADD) 來執行插入。

  5. 如果應用程式已設定 SQL_ATTR_ROW_STATUS_PTR 語句屬性,它可以檢查此陣列以查看作業的結果。

如果應用程式在呼叫 具有 operation 引數 SQL_ADD的 SQLBulkOperations 之前系結資料行 0,則驅動程式會使用新插入資料列的書簽值來更新系結資料行 0 緩衝區。 若要發生這種情況,應用程式必須先將 SQL_ATTR_USE_BOOKMARKS 語句屬性設定為 SQL_UB_VARIABLE,才能執行 語句。 (這不適用於 ODBC 2。 x driver.)

您可以使用對 SQLParamData 和 SQLPutData 的呼叫,透過 SQLBulkOperations 在元件中新增長資料。 如需詳細資訊,請參閱此函式參考稍後的。

應用程式在呼叫 SQLBulkOperations 之前不需要呼叫 SQLFetch SQLFetchScroll (除非針對 ODBC 2 執行時)。 x 驅動程式;請參閱 回溯相容性和標準合規性 )。

如果 SQLBulkOperations 具有 SQL_ADD 的 Operation 引數,則會在包含重復資料行的資料指標上呼叫此行為。 驅動程式可以傳回驅動程式定義的 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. 更新系結緩衝區中的資料。

    注意

    SQL_ATTR_ROW_STATUS_PTR語句屬性所指向的陣列大小應該等於SQL_ATTR_ROW_ARRAY_SIZE,或SQL_ATTR_ROW_STATUS_PTR應該是 null 指標。

  7. 呼叫 SQLBulkOperations StatementHandle, SQL_UPDATE_BY_BOOKMARK)。

    注意

    如果應用程式已設定 SQL_ATTR_ROW_STATUS_PTR 語句屬性,它可以檢查此陣列以查看作業的結果。

  8. 選擇性地呼叫 SQLBulkOperations StatementHandle ,SQL_FETCH_BY_BOOKMARK)將資料擷取到系結的應用程式緩衝區,以確認更新是否已發生。

  9. 如果資料已更新,驅動程式會將適當資料列的資料列狀態陣列中的值變更為SQL_ROW_UPDATED。

SQLBulkOperations 所 執行的大量更新可以使用對 SQLParamData SQLPutData 呼叫來包含長 資料。 如需詳細資訊,請參閱此函式參考稍後的。

如果書簽在資料指標之間保存,應用程式就不需要在書簽更新之前呼叫 SQLFetch SQLFetchScroll 。 它可以使用它從上一個資料指標儲存的書簽。 如果書簽不會跨資料指標保存,應用程式必須呼叫 SQLFetch SQLFetchScroll 來擷取書簽。

如果 SQLBulkOperations 具有 SQL_UPDATE_BY_BOOKMARK 的 Operation 引數,則會在包含重復資料行的資料指標上呼叫此行為。 驅動程式可以傳回驅動程式定義的 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 之陣列的資料列書簽。 (這假設應用程式已經分別取得書簽。

    注意

    SQL_ATTR_ROW_STATUS_PTR語句屬性所指向的陣列大小應該等於SQL_ATTR_ROW_ARRAY_SIZE,或SQL_ATTR_ROW_STATUS_PTR應該是 null 指標。

  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 的陣列中。

    注意

    SQL_ATTR_ROW_STATUS_PTR語句屬性所指向的陣列大小應該等於SQL_ATTR_ROW_ARRAY_SIZE,或SQL_ATTR_ROW_STATUS_PTR應該是 null 指標。

  6. 呼叫 SQLBulkOperations StatementHandle, SQL_DELETE_BY_BOOKMARK)。

  7. 如果應用程式已設定 SQL_ATTR_ROW_STATUS_PTR 語句屬性,它可以檢查此陣列以查看作業的結果。

如果書簽在資料指標之間保存,應用程式就不需要在書簽刪除之前呼叫 SQLFetch SQLFetchScroll 。 它可以使用它從上一個資料指標儲存的書簽。 如果書簽不會跨資料指標保存,應用程式必須 呼叫 SQLFetch SQLFetchScroll 一次擷取書簽。

提供大量插入和更新的長資料

您可以針對呼叫 SQLBulkOperations 來執行 的大量插入和更新提供長資料。 若要插入或更新長資料,除了本主題稍早的和小節中所述的步驟之外,應用程式也會執行下列步驟。

  1. 當它使用 SQLBindCol 系結資料時,應用程式會在 *TargetValuePtr 緩衝區中 放置應用程式定義的值,例如資料行編號。 此值稍後可用來識別資料行。

    應用程式會將 SQL_LEN_DATA_AT_EXEC( length ) 宏的結果放在 *StrLen_or_IndPtr 緩衝區中。 如果資料行的 SQL 資料類型SQL_LONGVARBINARY、SQL_LONGVARCHAR或長資料來源特定資料類型,而驅動程式會針對 SQLGetInfo SQL_NEED_LONG_DATA_LEN資訊型別傳回 「Y」, 則 length 是要針對 參數傳送的資料位元組數;否則,它必須是非負值且會被忽略。

  2. 呼叫 SQLBulkOperations ,如果有資料執行中資料行,函式會傳回SQL_NEED_DATA,然後繼續進行步驟 3,如下所示。 (如果沒有執行中的資料行,則程式已完成。

  3. 應用程式會呼叫 SQLParamData 來擷取要處理之第一個資料執行資料行的 *TargetValuePtr 緩衝區位址。 SQLParamData 會傳回SQL_NEED_DATA。 應用程式會從 *TargetValuePtr 緩衝區擷 取應用程式定義的值。

    注意

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

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

  4. 應用程式會呼叫 SQLPutData 一或多次來傳送資料行的資料。 如果無法在 SQLPutData 中指定的 *TargetValuePtr 緩衝區中 傳回所有資料值,則只有將字元 C 資料傳送至具有字元、二進位或資料來源特定資料類型的資料行,或將二進位 C 資料傳送至具有字元的資料行時,才允許對相同資料行的多個呼叫 , binary 或資料來源特定的資料類型。

  5. 應用程式會再次呼叫 SQLParamData ,以發出所有資料已傳送給資料行的訊號。

    • 如果有更多資料執行資料行, SQLParamData 會傳回SQL_NEED_DATA和 TargetValuePtr 緩衝區的 位址,以便處理下一個執行資料行。 應用程式會重複步驟 4 和 5。

    • 如果沒有任何資料執行中資料行,程式就會完成。 如果語句成功執行, SQLParamData 會傳回SQL_SUCCESS或SQL_SUCCESS_WITH_INFO;如果執行失敗,則會傳回SQL_ERROR。 此時, SQLParamData 可以傳回 SQLBulkOperations 可傳 回的任何 SQLSTATE。

如果作業已取消,或在 SQLBulkOperations 傳回SQL_NEED_DATA, 而且在針對所有執行中資料行傳送資料之前,SQLParamData SQLParanctions、SQLGetDiagRec、SQLGetFunctions、SQLParamData 或 SQLPutData 之後,應用程式只能呼叫 SQLCancel SQLGetDiagField SQLGetDiagRec SQLGetFunctions SQLParamData SQLPutData 做為語句或與語句相關聯的連接。 如果函式針對 語句或與 語句相關聯的連接呼叫任何其他函式,則函式會傳回 SQL_ERROR 和 SQLSTATE HY010 (函式序列錯誤)。

如果應用程式呼叫 SQLCancel ,而驅動程式仍需要執行資料行的資料,則驅動程式會取消作業。 然後,應用程式可以再次呼叫 SQLBulkOperations ;取消不會影響資料指標狀態或目前的資料指標位置。

資料列狀態陣列

資料列狀態陣列會在呼叫 SQLBulkOperations 之後,包含資料列集內每個資料列的狀態值。 驅動程式會在呼叫 SQLFetch 、SQLFetchScroll SQLSetPos SQLBulkOperations 之後,設定此陣列中的狀態值。 如果 SQLFetch SQLFetchScroll 在 SQLBulkOperations 之前 尚未呼叫 SQLBulkOperations ,此陣列一開始會由呼叫 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 函式

另請參閱

ODBC API 參考
ODBC 標頭檔