符合性
推出版本: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 上呼叫 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) 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。 操作參數為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。 若應用程式呼叫 SQLFetch 或 SQLFetchScroll ,並使用 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 插入資料,應用程式會執行以下步驟序列:
執行一個返回結果集的查詢。
將 SQL_ATTR_ROW_ARRAY_SIZE 陳述句屬性設定為它想插入的列數。
呼叫 SQLBindCol 來綁定它想插入的資料。 資料被綁定到大小等於 SQL_ATTR_ROW_ARRAY_SIZE 的陣列。
Note
SQL_ATTR_ROW_STATUS_PTR 陳述式屬性所指向的陣列大小應該要麼等於 SQL_ATTR_ROW_ARRAY_SIZE,要麼SQL_ATTR_ROW_STATUS_PTR應該是空指標。
呼叫 SQLBulkOperations(StatementHandle, SQL_ADD) 來執行插入。
如果應用程式已設定 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 之前,不必先呼叫 SQLFetch 或 SQLFetchScroll(除非是針對 ODBC 2 時)。x 驅動程式;參見向下相容性與標準合規)。
若在包含重複欄位的游標上呼叫 SQLBulkOperations,且 操作參數為 SQL_ADD,則該行為為驅動程式定義。 驅動程式可以回傳驅動程式定義的 SQLSTATE,將資料加入結果集中出現的第一欄,或執行其他驅動程式定義的行為。
使用書籤進行大量更新
要透過書籤搭配 SQLBulkOperations 進行大量更新,應用程式依序執行以下步驟:
將 SQL_ATTR_USE_BOOKMARKS 陳述 屬性設為 SQL_UB_VARIABLE。
執行一個返回結果集的查詢。
將 SQL_ATTR_ROW_ARRAY_SIZE 陳述句屬性設定為它想更新的列數。
呼叫 SQLBindCol 來綁定它想更新的資料。 資料被綁定到大小等於 SQL_ATTR_ROW_ARRAY_SIZE 的陣列。 它也會呼叫 SQLBindCol 來綁定第 0 欄(書籤欄位)。
將它有興趣更新的資料列的書籤複製到綁定到第 0 欄的陣列中。
更新綁定緩衝區的資料。
Note
SQL_ATTR_ROW_STATUS_PTR 陳述式屬性所指向的陣列大小應為 SQL_ATTR_ROW_ARRAY_SIZE,否則SQL_ATTR_ROW_STATUS_PTR應為空指標。
呼叫 SQLBulkOperations(StatementHandle, SQL_UPDATE_BY_BOOKMARK)。
Note
如果應用程式已設定 SQL_ATTR_ROW_STATUS_PTR 陳述式屬性,它可以檢查此陣列以查看操作結果。
可選擇性呼叫 SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK) 將資料取回綁定的應用程式緩衝區,以驗證更新是否已發生。
若資料已更新,驅動程式會將相應列的列狀態陣列值改為SQL_ROW_UPDATED。
SQLBulkOperations 執行的大量更新可透過呼叫 SQLParamData 與 SQLPutData 來包含長資料。 欲了解更多資訊,請參閱本函式參考文獻後面的「提供大量插入與更新的長資料」。
如果書籤在游標間持續存在,應用程式在透過書籤更新前,就不需要呼叫 SQLFetch 或 SQLFetchScroll 。 它可以使用從先前游標儲存的書籤。 若書籤無法在游標間持續存在,應用程式必須呼叫 SQLFetch 或 SQLFetchScroll 來取得書籤。
若在包含重複欄位的游標上呼叫 SQLBulkOperations,且 Operation 參數為 SQL_UPDATE_BY_BOOKMARK,則該行為由驅動程式定義。 驅動程式可以回傳驅動程式定義的 SQLSTATE、更新結果集中出現的第一欄,或執行其他驅動程式定義的行為。
使用書籤進行批量取物
要使用 SQLBulkOperations 進行大量取用書籤,應用程式依序執行以下步驟:
將 SQL_ATTR_USE_BOOKMARKS 陳述 屬性設為 SQL_UB_VARIABLE。
執行一個返回結果集的查詢。
將 SQL_ATTR_ROW_ARRAY_SIZE 陳述句屬性設定為它想要取得的列數。
呼叫 SQLBindCol 來綁定它想要擷取的資料。 資料被綁定到大小等於 SQL_ATTR_ROW_ARRAY_SIZE 的陣列。 它也會呼叫 SQLBindCol 來綁定第 0 欄(書籤欄位)。
將它有興趣擷取的資料列的書籤複製到綁定到第 0 欄的陣列中。 (這假設應用程式已經分別取得書籤。)
Note
SQL_ATTR_ROW_STATUS_PTR 陳述式屬性所指向的陣列大小應為 SQL_ATTR_ROW_ARRAY_SIZE,否則SQL_ATTR_ROW_STATUS_PTR應為空指標。
呼叫 SQLBulkOperations(StatementHandle, SQL_FETCH_BY_BOOKMARK)。
如果應用程式已設定 SQL_ATTR_ROW_STATUS_PTR 陳述式屬性,它可以檢查此陣列以查看操作結果。
如果書籤在游標間持續存在,應用程式在以書籤擷取前就不需要呼叫 SQLFetch 或 SQLFetchScroll 。 它可以使用從先前游標儲存的書籤。 若書籤無法跨游標持續存在,應用程式必須呼叫一次 SQLFetch 或 SQLFetchScroll 來取得書籤。
使用書籤執行大量刪除
要使用 SQLBulkOperations 的書籤執行大量刪除,應用程式依序執行以下步驟:
將 SQL_ATTR_USE_BOOKMARKS 陳述 屬性設為 SQL_UB_VARIABLE。
執行一個返回結果集的查詢。
將 SQL_ATTR_ROW_ARRAY_SIZE 陳述句屬性設定為它想刪除的列數。
呼叫 SQLBindCol 來綁定第 0 欄(書籤欄)。
將想要刪除的列的書籤複製到綁定到第 0 欄的陣列中。
Note
SQL_ATTR_ROW_STATUS_PTR 陳述式屬性所指向的陣列大小應為 SQL_ATTR_ROW_ARRAY_SIZE,否則SQL_ATTR_ROW_STATUS_PTR應為空指標。
呼叫 SQLBulkOperations(StatementHandle, SQL_DELETE_BY_BOOKMARK)。
如果應用程式已設定 SQL_ATTR_ROW_STATUS_PTR 陳述式屬性,它可以檢查此陣列以查看操作結果。
如果書籤在游標間持續存在,應用程式刪除書籤前不必呼叫 SQLFetch 或 SQLFetchScroll 。 它可以使用從先前游標儲存的書籤。 若書籤無法跨游標持續存在,應用程式必須呼叫一次 SQLFetch 或 SQLFetchScroll 來取得書籤。
提供大量插入與更新所需的長資料
透過呼叫 SQLBulkOperations 來提供大量插入與更新的長資料。 要插入或更新長資料,應用程式除了本主題前述「執行批量插入」與「使用書籤執行大量更新」章節所述步驟外,還需執行以下步驟。
當應用程式使用 SQLBindCol 綁定資料時,會在執行時資料欄位的 *TargetValuePtr 緩衝區中放置應用程式定義的值,例如欄位編號。 這個值之後可以用來識別欄位。
應用程式會將 SQL_LEN_DATA_AT_EXEC(長度)巨集的結果放入 *StrLen_or_IndPtr 緩衝區。 若欄位的 SQL 資料型態為 SQL_LONGVARBINARY、SQL_LONGVARCHAR,或長資料來源特定型態,且驅動程式回傳 SQLGetInfo 中SQL_NEED_LONG_DATA_LEN資訊型別的「Y 」,長度 即為該參數要傳送的資料位元組數;否則,必須是非負值,且會被忽略。
當呼叫 SQLBulkOperations 時,若有執行時資料欄位,函式會回傳 SQL_NEED_DATA,並進入步驟 3,隨後進行步驟。 (若執行時沒有資料欄位,則程序完成。)
應用程式呼叫 SQLParamData ,取得第一個執行時資料欄位 *TargetValuePtr 緩衝區的位址。 SQLParamData 會傳回SQL_NEED_DATA。 應用程式會從 *TargetValuePtr 緩衝區取得應用程式定義的值。
Note
雖然數據執行時參數類似於數據執行數據行,但 SQLParamData 所傳回的值會針對每個數據行不同。
執行時資料欄位是列集中的欄位,當資料在用 SQLBulkOperations 更新或插入資料時,會以 SQLPutData 傳送。 它們會與 SQLBindCol 系結。 SQLParamData 回傳的值是正在處理的 *TargetValuePtr 緩衝區中該列的位址。
應用程式會呼叫 SQLPutData 一次或多次,以傳送欄位的資料。 若無法在 SQLPutData 指定的 *TargetValuePtr 緩衝區回傳所有資料值,則需多次呼叫;只有在將字元C資料傳送到具有字元、二進位或資料來源特定資料型別的欄位,或將二進位C資料傳送到具有字元、二進位或資料來源特定資料型別的欄位時,才允許對同一欄位呼叫多次SQLPutData。
應用程式再次呼叫 SQLParamData ,以表示該欄位的所有資料已送出。
若有更多執行時資料欄位, SQLParamData 會回傳SQL_NEED_DATA及下一個執行時資料欄位的 TargetValuePtr 緩衝區位址。 應用程式會重複步驟 4 和 5。
如果執行時的資料欄位已無,則程序完成。 如果該語句成功執行, SQLParamData 會回傳 SQL_SUCCESS 或 SQL_SUCCESS_WITH_INFO;若執行失敗,則回傳SQL_ERROR。 此時, SQLParamData 可以回傳任何 SQLBulkOperations 能回傳的 SQLSTATE。
若操作被取消或 SQLParamData 或 SQLPutData 發生錯誤,且 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 函式 |