共用方式為


SQLSetPos 函式

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

摘要
SQLSetPos 會設定資料列集中的數據指標位置,並允許應用程式重新整理數據列集中的數據,或更新或刪除結果集中的數據。

語法

  
SQLRETURN SQLSetPos(  
      SQLHSTMT        StatementHandle,  
      SQLSETPOSIROW   RowNumber,  
      SQLUSMALLINT    Operation,  
      SQLUSMALLINT    LockType);  

引數

StatementHandle
[輸入]語句句柄。

RowNumber
[輸入]數據列集中要執行 Operation 自變數所指定作業的數據列集位置。 如果 RowNumber 是 0,此作業會套用到資料列集內的每一個資料列。

如需詳細資訊,請參閱。

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

SQL_POSITION SQL_REFRESH SQL_UPDATE SQL_DELETE

注意

Operation 自變數的SQL_ADD值已被取代為 ODBC 3.x。 ODBC 3.x 驅動程式必須支援SQL_ADD,以提供回溯相容性。 這項功能已由呼叫 SQLBulkOperations 取代為SQL_ADD作業 。 當 ODBC 3.x 應用程式與 ODBC 2.x 驅動程式搭配運作時,Driver Manager 會將呼叫對應至 SQLBulkOperations,並將SQL_ADD作業對應至具有 SQL_ADD 作業的 SQLSetPos

如需詳細資訊,請參閱。

LockType
[輸入]指定在執行 Operation 自變數中指定的作業之後,如何鎖定數據列。

SQL_LOCK_NO_CHANGE SQL_LOCK_EXCLUSIVE SQL_LOCK_UNLOCK

如需詳細資訊,請參閱。

傳回

SQL_SUCCESS、SQL_SUCCESS_WITH_INFO、SQL_NEED_DATA、SQL_STILL_EXECUTING、SQL_ERROR或SQL_INVALID_HANDLE。

診斷

SQLSetPos 傳回SQL_ERROR或SQL_SUCCESS_WITH_INFO時,藉由呼叫 SQLGetDiagRec 搭配SQL_HANDLE_STMT的 HandleTypeStatementHandle 句柄,即可取得相關聯的 SQLSTATE 值。 下表列出 SQLSetPos 通常傳回的 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。)
01001 數據指標作業衝突 Operation 自變數已SQL_DELETE或SQL_UPDATE,而且不會刪除或更新任何數據列或多個數據列。 (如需多個數據列更新的詳細資訊,請參閱SQL_ATTR_SIMULATE_CURSOR SQLSetStmtAttr.] 中的屬性(函式會傳回SQL_SUCCESS_WITH_INFO。)

Operation 自變數已SQL_DELETE或SQL_UPDATE,且作業因為開放式並行存取而失敗。 (函式會傳回SQL_SUCCESS_WITH_INFO。)
01004 字串數據右截斷 Operation 自變數是SQL_REFRESH,而針對數據類型為SQL_C_CHAR或SQL_C_BINARY的數據行傳回字串或二進位數據,會導致非空白字元或非 NULL 二進位數據截斷。
01S01 數據列中的錯誤 RowNumber 自變數為 0,而且執行以 Operation 自變數指定的作業時,一或多個數據列發生錯誤。

(如果一或多個數據列作業發生錯誤,但並非全部發生錯誤,則會傳回SQL_SUCCESS_WITH_INFO;如果單一數據列作業發生錯誤,則會傳回SQL_ERROR。

(只有在下列情況下才會傳回此 SQLSTATE:如果驅動程式是 ODBC 2.x 驅動程式,而且未使用數據指標連結庫,則 SQLSetPos 會在 SQLExtendedFetch 之後呼叫。
01S07 小數截斷 Operation 自變數已SQL_REFRESH,應用程式緩衝區的數據類型未SQL_C_CHAR或SQL_C_BINARY,且傳回至一或多個數據行的應用程式緩衝區的數據已截斷。 針對數值數據類型,數位的小數部分已截斷。 針對包含時間元件的 time、timestamp 和 interval 數據類型,時間的小數部分已截斷。

(函式會傳回SQL_SUCCESS_WITH_INFO。)
07006 受限制的數據類型屬性違規 在呼叫 SQLBindCol 時,無法將結果集中數據行的數據值轉換成 TargetType指定的數據類型。
07009 無效的描述元索引 自變數 Operation 已SQL_REFRESH或SQL_UPDATE,且數據行系結的數據行數目大於結果集中的數據行數目。
21S02 衍生數據表的程度不符合數據列清單 自變數 Operation 是SQL_UPDATE,而且無法更新任何數據行,因為所有數據行都是未繫結、只讀的,或是系結長度/指標緩衝區中的值SQL_COLUMN_IGNORE。
22001 字串數據,右截斷 Operation 自變數SQL_UPDATE,並將字元或二進位值指派給數據行會導致非空白(針對字元)或非 Null 字元或位元組截斷。
22003 超出範圍的數值 自變數 Operation 已SQL_UPDATE,並將數值指派給結果集中的數據行會導致截斷數位的整個部分(而不是小數部分)。

自變數 Operation 已SQL_REFRESH,並傳回一或多個系結數據行的數值會導致有效位數遺失。
22007 無效的日期時間格式 自變數 Operation 已SQL_UPDATE,且將日期或時間戳值指派給結果集中的數據行會導致年份、月份或日期字段超出範圍。

自變數 Operation 已SQL_REFRESH,並傳回一或多個系結數據行的日期或時間戳值會導致年份、月份或日期字段超出範圍。
22008 日期/時間欄位溢位 Operation 自變數是SQL_UPDATE,而結果集中所傳送數據之日期時間算術的效能會導致日期時間字段(年、月、日、小時、分鐘或第二個字段)的結果超出字段允許範圍的值範圍,或根據公曆的日期時間自然規則而無效。

Operation 自變數SQL_REFRESH,而從結果集中擷取之數據的日期時間算術效能,導致結果的日期時間字段(年、月、日、小時、分鐘或秒欄位)超出欄位允許範圍的值範圍,或根據公曆日期時間的自然規則而無效。
22015 間隔欄位溢位 Operation 自變數已SQL_UPDATE,而將精確數值或間隔 C 類型指派給間隔 SQL 數據類型會導致有效位數遺失。

Operation 自變數SQL_UPDATE;指派給間隔 SQL 類型時,在間隔 SQL 類型中沒有 C 型別的值表示法。

Operation 自變數SQL_REFRESH,並從確切的數值或間隔 SQL 類型指派給間隔 C 類型會導致前置字段中的顯著數位遺失。

Operation 自變數SQL_ REFRESH;指派給間隔 C 類型時,在間隔 C 類型中沒有 SQL 類型的值表示。
22018 轉換規格的字元值無效 Operation 自變數是SQL_REFRESH;C 類型是精確或近似數值、日期時間或間隔數據類型;數據行的 SQL 類型是字元數據類型;而且數據行中的值不是系結 C 型別的有效常值。

自變數 Operation 是SQL_UPDATE;SQL 類型是確切或近似數值、日期時間或間隔數據類型;C 類型是SQL_C_CHAR;而且數據行中的值不是系結 SQL 類型的有效常值。
23000 完整性條件約束違規 自變數 Operation 已SQL_DELETE或SQL_UPDATE,並違反完整性條件約束。
24000 無效的數據指標狀態 StatementHandle 處於執行狀態,但沒有結果集與 StatementHandle 相關聯。

(DM) 語句上已開啟數據指標,但未呼叫 SQLFetchSQLFetchScroll

已開啟 StatementHandle 上的數據指標,而且已呼叫 SQLFetchSQLFetchScroll,但數據指標位於結果集的開頭之前或結果集結尾之後。

自變數 Operation 是SQL_DELETE、SQL_REFRESH或SQL_UPDATE,而且游標位於結果集的開頭或結果集結尾之後。
40001 串行化失敗 交易因為與另一個交易發生資源死結而回復。
40003 語句完成未知 此函式執行期間相關聯的連接失敗,且無法判斷交易的狀態。
42000 語法錯誤或存取違規 驅動程式無法視需要鎖定數據列,以執行自變數 Operation 中所要求的作業。

驅動程式無法鎖定自變數 LockType 中所要求的數據列。
44000 WITH CHECK OPTION 違規 Operation 自變數已SQL_UPDATE,而且更新是在檢視數據表或衍生自檢視數據表的數據表上執行,而該數據表是由指定WITH CHECK OPTION 所建立,因此,更新所影響的一或多個數據列將不再出現在檢視數據表中。
HY000 一般錯誤 發生錯誤,其中沒有特定的 SQLSTATE,也沒有定義任何實作特定的 SQLSTATE。 *MessageText 緩衝區中 SQLGetDiagRec回的錯誤訊息描述錯誤及其原因。
HY001 記憶體配置錯誤 驅動程式無法配置支援執行或完成函式所需的記憶體。
HY008 作業已取消 已針對 StatementHandle 啟用異步處理。 已呼叫函式,並在完成執行之前,在 StatementHandle 上呼叫 SQLCancelSQLCancelHandle,然後在 StatementHandle再次呼叫函式。

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

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

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

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

(DM) 驅動程式是 ODBC 2.x 驅動程式,在呼叫 SQLFetch 之後,SQLSetPos 會呼叫 StatementHandle
HY011 無法立即設定屬性 (DM) 驅動程式是 ODBC 2.x 驅動程式;已設定SQL_ATTR_ROW_STATUS_PTR語句屬性;然後在呼叫 SQLFetchSQLFetchScrollSQLExtendedFetch 之前呼叫 SQLSetPos
HY013 記憶體管理錯誤 無法處理函式呼叫,因為基礎記憶體物件無法存取,可能是因為記憶體不足的情況。
HY090 無效的字串或緩衝區長度 Operation 自變數是SQL_UPDATE,數據值是 null 指標,而數據行長度值不是 0、SQL_DATA_AT_EXEC、SQL_COLUMN_IGNORE、SQL_NULL_DATA或小於或等於SQL_LEN_DATA_AT_EXEC_OFFSET。

Operation 自變數SQL_UPDATE;數據值不是 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或長數據源特定數據類型;和 SQLGetInfoSQL_NEED_LONG_DATA_LEN資訊類型為 「Y」。
HY092 無效的屬性識別碼 (DM) 為 Operation 自變數指定的值無效。

(DM) 為 LockType 自變數指定的值無效。

Operation 自變數SQL_UPDATE或SQL_DELETE,且SQL_ATTR_CONCURRENCY語句屬性SQL_ATTR_CONCUR_READ_ONLY。
HY107 超出範圍的數據列值 為自變數 RowNumber 指定的值大於數據列集中的數據列數目。
HY109 無效的數據指標位置 StatementHandle 相關聯的數據指標已定義為正向,因此數據指標無法放置在數據列集內。 請參閱 SQLSetStmtAttrSQL_ATTR_CURSOR_TYPE屬性的描述。

Operation 自變數SQL_UPDATE、SQL_DELETE或SQL_REFRESH,且 RowNumber 自變數所識別的數據列已刪除或尚未擷取。

(DM) RowNumber 自變數為 0, 而 Operation 自變數則SQL_POSITION。

在呼叫 SQLBulkOperations 之後呼叫 SQLSetPos,並在呼叫 SQLFetchScrollSQLFetch 之前呼叫。
HY117 聯機因為未知的交易狀態而暫停。 只允許中斷連線和唯讀函式。 (DM) 如需暫停狀態的詳細資訊,請參閱 SQLEndTran 函式
HYC00 未實作選擇性功能 驅動程式或數據源不支援 Operation 自變數或 LockType 自變數中所要求的作業。
HYT00 逾時已超過 數據源傳回結果集之前,查詢逾時期限已過期。 逾時期間是透過具有屬性的 SQLSetStmtAttr 來設定SQL_ATTR_QUERY_TIMEOUT。
HYT01 已超過連線逾時 在數據源回應要求之前,連線逾時期限已過期。 線上逾時期間是透過 SQLSetConnectAttr 來設定,SQL_ATTR_CONNECTION_TIMEOUT。
IM001 驅動程式不支援此函式 (DM) 與 StatementHandle 相關聯的驅動程式不支援 函式。
IM017 在異步通知模式中停用輪詢 每當使用通知模型時,輪詢就會停用。
IM018 尚未呼叫 SQLCompleteAsync ,以完成此句柄上的先前異步操作。 如果句柄上的上一個函式呼叫傳回SQL_STILL_EXECUTING且啟用通知模式, 則必須在句柄上呼叫 SQLCompleteAsync ,才能執行後續處理並完成作業。

註解

警告

如需語句中可以 呼叫 SQLSetPos 以及它需要執行哪些動作才能與 ODBC 2.x 應用程式相容的詳細資訊,請參閱 區塊數據指標、可捲動的數據指標和回溯相容性

RowNumber 自變數

RowNumber 自變數會指定要執行 Operation 自變數所指定作業之數據列集中的數據列數目。 如果 RowNumber 是 0,此作業會套用到資料列集內的每一個資料列。 RowNumber 必須是從 0 到數據列集中數據列數目的值。

注意

在 C 語言中,陣列是以 0 為基礎,而 RowNumber 自變數是以 1 為基礎。 例如,若要更新數據列集的第五列,應用程式會修改數位索引 4 的數據列集緩衝區,但指定 RowNumber 為 5。

所有作業都會將游標放在 RowNumber指定的數據列上。 下列作業需要資料指標位置:

  • 定位的更新和刪除語句。

  • 呼叫 SQLGetData

  • 使用SQL_DELETE、SQL_REFRESH和SQL_UPDATE選項呼叫 SQLSetPos

例如,如果 RowNumber 是 2,則呼叫具有 SQL_DELETE Operation 的 SQLSetPos 時,數據指標會放在數據列集的第二個數據列,並刪除該數據列。 第二個數據列實作數據列狀態陣列中的項目會變更為 SQL_ATTR_ROW_STATUS_PTR SQL_ROW_DELETED。

應用程式可以在呼叫 SQLSetPos 時指定資料指標位置。 一般而言,它會使用SQL_POSITION或SQL_REFRESH作業呼叫 SQLSetPos ,以在執行定位更新或刪除語句或呼叫 SQLGetData 之前放置游標。

Operation 自變數

Operation 自變數支援下列作業。 若要判斷數據源所支援的選項,應用程式會使用SQL_DYNAMIC_CURSOR_ATTRIBUTES1、SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1、SQL_KEYSET_CURSOR_ATTRIBUTES1或SQL_STATIC_CURSOR_ATTRIBUTES1資訊類型來呼叫 SQLGetInfo (視數據指標的類型而定)。

運算

引數
作業
SQL_POSITION 驅動程式會將游標放在 RowNumber指定的數據列上。

SQL_POSITION 作業會忽略SQL_ATTR_ROW_OPERATION_PTR語句屬性所指向的數據列狀態陣列內容。
SQL_REFRESH 驅動程式會將數據指標放在 RowNumber指定的數據列上,並在該數據列的數據列集緩衝區中重新整理數據。 如需驅動程式如何傳回數據列集緩衝區的詳細資訊,請參閱 SQLBindCol數據列和數據行系結的描述。

具有SQL_REFRESH作業的 SQLSetPos 會更新目前所擷取數據列集內數據列的狀態和內容。 這包括重新整理書籤。 因為緩衝區中的數據會重新整理,但不會重新整理,因此會修正數據列集中的成員資格。 這與呼叫 SQLFetchScroll 所執行的重新整理不同,其中 fetchOrientation 為 SQL_FETCH_RELATIVE,而 RowNumber 等於 0,這會從結果集重新擷取數據列集,以便在驅動程式和數據指標支持這些作業時顯示新增的數據並移除已刪除的數據。

使用 SQLSetPos 成功的重新整理將不會變更SQL_ROW_DELETED的數據列狀態。 在下次擷取之前,數據列集中已刪除的數據列將繼續標示為已刪除。 如果數據指標支援封裝,則數據列會在下一個擷取中消失(後續 的 SQLFetchSQLFetchScroll 不會傳回已刪除的數據列)。

執行 SQLSetPos 重新整理時,不會顯示新增的數據列。 此行為與 SQLFetchScroll 不同,其 FetchType 為 SQL_FETCH_RELATIVE 且 RowNumber 等於 0,這也會重新整理目前的數據列集,但如果數據指標支援這些作業,則會顯示新增的記錄或封裝已刪除的記錄。

使用 SQLSetPos 的成功重新整理會將SQL_ROW_ADDED的數據列狀態變更為SQL_ROW_SUCCESS(如果數據列狀態陣列存在)。

使用 SQLSetPos 成功重新整理,會將SQL_ROW_UPDATED的數據列狀態變更為數據列的新狀態(如果數據列狀態陣列存在)。

如果在數據列的 SQLSetPos 作業中發生錯誤,數據列狀態會設定為SQL_ROW_ERROR(如果數據列狀態陣列存在)。

對於以 SQL_CONCUR_ROWVER 或 SQL_CONCUR_VALUES SQL_ATTR_CONCURRENCY 語句屬性開啟的數據指標,使用 SQLSetPos 重新整理可能會更新數據源用來偵測數據列已變更的開放式並行值。 如果發生這種情況,每當從伺服器重新整理數據列集緩衝區時,用來確保數據指標並行更新的數據列版本或值。 這會針對重新整理的每個數據列發生。

SQL_ATTR_ROW_OPERATION_PTR 語句屬性所指向的數據列狀態陣列內容會針對 SQL_REFRESH Operation 忽略。
SQL_UPDATE 驅動程式會將游標放在 RowNumber 所指定的數據列上,並使用數據列集緩衝區中的值來更新基礎數據列(SQLBindCol 中的 TargetValuePtr變數)。 它會從長度/指標緩衝區擷取數據長度(SQLBindCol 中的StrLen_or_IndPtr自變數)。 如果任何數據行的長度SQL_COLUMN_IGNORE,則不會更新數據行。 更新數據列之後,驅動程式會將數據列狀態陣列的對應專案變更為SQL_ROW_UPDATED或SQL_ROW_SUCCESS_WITH_INFO(如果數據列狀態陣列存在)。

如果具有 operation 自變數的 SQLSetPos 在包含重複數據行的數據指標上呼叫SQL_UPDATE,這是驅動程式定義的行為。 驅動程式可以傳回驅動程式定義的 SQLSTATE、更新結果集中出現的第一個數據行,或執行其他驅動程式定義的行為。

SQL_ATTR_ROW_OPERATION_PTR語句屬性所指向的數據列作業陣列可用來指出在大量更新期間應該忽略目前數據列集中的數據列。 如需詳細資訊,請參閱此函式參考稍後的。
SQL_DELETE 驅動程式會將游標放在 RowNumber指定的數據列上,並刪除基礎數據列。 它會將數據列狀態陣列的對應專案變更為SQL_ROW_DELETED。 刪除數據列之後,下列數據列無效:定位的更新和刪除語句、對SQLGetData的呼叫,以及將 Operation 設定為 SQL_POSITION 以外的任何專案對 SQLSetPos 的呼叫 對於支援封裝的驅動程式,從數據源擷取新數據時,數據列會從數據指標中刪除。

數據列是否保持可見,取決於數據指標類型。 例如,靜態和索引鍵集驅動數據指標可看見已刪除的數據列,但動態數據指標看不到。

SQL_ATTR_ROW_OPERATION_PTR語句屬性所指向的數據列作業陣列可用來指出在大量刪除期間應該忽略目前數據列集中的數據列。 如需詳細資訊,請參閱此函式參考稍後的。

LockType 自變數

LockType 自變數提供一種方式,讓應用程式控制並行。 在大部分情況下,支援並行層級和交易的數據源僅支援LockType自變數的SQL_LOCK_NO_CHANGE值。 LockType 自變數通常僅用於檔案型支援。

LockType 自變數會在執行 SQLSetPos 之後指定數據列的鎖定狀態。 如果驅動程式無法鎖定數據列以執行要求的作業或滿足 LockType 自變數,則會傳回 SQL_ERROR和STATE 42000 (語法錯誤或存取違規)。

雖然已針對單一語句指定 LockType 自變數,但lock會將相同的許可權授予連接上的所有語句。 特別是,連接上一個語句取得的鎖定,可由相同連接上的不同語句解除鎖定。

透過 SQLSetPos 鎖定的數據列會保持鎖定狀態,直到應用程式針對 LockType 設定為 SQL_LOCK_UNLOCK的數據列呼叫 SQLSetPos,或是應用程式使用 SQL_CLOSE 選項呼叫 SQLFreeHandleSQLFreeStmt 為止。 對於支援交易的驅動程式,當應用程式呼叫 SQLEndTran 來認可或回覆連線上的交易時,會解除鎖定透過 SQLSetPos 鎖定的數據列(如果在認可或回復交易時關閉數據指標,如 SQLGetInfo傳回的SQL_CURSOR_COMMIT_BEHAVIOR和SQL_CURSOR_ROLLBACK_BEHAVIOR資訊類型所指示)。

LockType 自變數支援下列類型的鎖定。 若要判斷數據源支援哪些鎖定,應用程式會使用SQL_DYNAMIC_CURSOR_ATTRIBUTES1、SQL_FORWARD_ONLY_CURSOR_ATTRIBUTES1、SQL_KEYSET_CURSOR_ATTRIBUTES1或SQL_STATIC_CURSOR_ATTRIBUTES1資訊類型來呼叫 SQLGetInfo (視數據指標的類型而定)。

LockType 自變數 鎖定類型
SQL_LOCK_NO_CHANGE 驅動程式或數據源可確保數據列處於與呼叫 SQLSetPos 之前相同的鎖定或解除鎖定狀態。 LockType 的這個值可讓不支援明確數據列層級鎖定的數據源使用目前並行和交易隔離等級所需的任何鎖定。
SQL_LOCK_EXCLUSIVE 驅動程式或數據源會以獨佔方式鎖定數據列。 不同連接或不同應用程式中的語句無法用來取得數據列的任何鎖定。
SQL_LOCK_UNLOCK 驅動程式或數據源會解除鎖定數據列。

如果驅動程式支援SQL_LOCK_EXCLUSIVE但不支援SQL_LOCK_UNLOCK,則鎖定的數據列會保持鎖定狀態,直到發生上一段所述的其中一個函式呼叫為止。

如果驅動程式支援SQL_LOCK_EXCLUSIVE但不支援SQL_LOCK_UNLOCK,則鎖定的數據列會維持鎖定狀態,直到應用程式使用 SQL_CLOSE 選項呼叫 SQLFreeHandle 或 SQLFreeStmt 為止。 如果驅動程序支援交易,並在認可或回復交易時關閉數據指標,應用程式會呼叫 SQLEndTran

針對 SQLSetPos 中的更新和刪除作業,應用程式會使用 LockType 自變數,如下所示:

  • 為了保證數據列在擷取之後不會變更,應用程式會呼叫 SQLSetPos,並將 Operation 設定為 SQL_REFRESH 並將 LockType 設定為 SQL_LOCK_EXCLUSIVE。

  • 如果應用程式將 LockType 設定為 SQL_LOCK_NO_CHANGE,驅動程式會保證只有在應用程式為 SQL_ATTR_CONCURRENCY 語句屬性指定SQL_CONCUR_LOCK時,更新或刪除作業才會成功。

  • 如果應用程式為 SQL_ATTR_CONCURRENCY 語句屬性指定SQL_CONCUR_ROWVER或SQL_CONCUR_VALUES,則驅動程式會比較數據列版本或值,並在應用程式擷取數據列之後變更時拒絕作業。

  • 如果應用程式為 SQL_ATTR_CONCURRENCY 語句屬性指定SQL_CONCUR_READ_ONLY,驅動程式會拒絕任何更新或刪除作業。

如需SQL_ATTR_CONCURRENCY語句屬性的詳細資訊,請參閱 SQLSetStmtAttr

狀態和作業陣列

呼叫 SQLSetPos,會使用下列狀態和作業陣列:

  • 數據列狀態陣列(如 IRD 和 SQL_ATTR_ROW_STATUS_ARRAY 語句屬性中SQL_DESC_ARRAY_STATUS_PTR欄位所指向)包含資料列集中每個資料列的狀態值。 驅動程式會在呼叫 SQLFetch、SQLFetchScrollSQLBulkOperationsSQLSetPos 之後,設定此陣列中的狀態值。 這個陣列是由 SQL_ATTR_ROW_STATUS_PTR語句屬性所指向。

  • 數據列作業陣列(如 ARD 和 SQL_ATTR_ROW_OPERATION_ARRAY 語句屬性中SQL_DESC_ARRAY_STATUS_PTR欄位所指向)包含數據列集內每個數據列的值,指出是否忽略或執行大量作業的 SQLSetPos 呼叫。 陣列中的每個元素都會設定為 SQL_ROW_PROCEED (預設值) 或 SQL_ROW_IGNORE。 這個陣列是由 SQL_ATTR_ROW_OPERATION_PTR語句屬性所指向。

狀態和作業陣列中的元素數目必須等於數據列集中的數據列數目(如 SQL_ATTR_ROW_ARRAY_SIZE 語句屬性所定義)。

如需數據列狀態陣列的相關信息,請參閱 SQLFetch。 如需數據列作業陣列的相關信息,請參閱本節稍後的。

使用 SQLSetPos

在應用程式呼叫 SQLSetPos 之前,它必須執行下列步驟順序:

  1. 如果應用程式將呼叫 SQLSetPos 並將 Operation 設定為 SQL_UPDATE,請針對每個資料行呼叫 SQLBindCol (或 SQLSetDescRec),以指定其資料類型,並系結資料行資料和長度的緩衝區。

  2. 如果應用程式將呼叫 SQLSetPos 並將 Operation 設定為 SQL_DELETE 或 SQL_UPDATE,請呼叫 SQLColAttribute 以確定要刪除或更新的數據行是可更新的。

  3. 呼叫 SQLExecDirectSQLExecute 或目錄函式來建立結果集。

  4. 呼叫 SQLFetchSQLFetchScroll 以擷取數據。

如需使用 SQLSetPos 的詳細資訊,請參閱使用 SQLSetPos 更新數據。

使用 SQLSetPos 刪除數據

若要使用 SQLSetPos 刪除數據,應用程式會呼叫 SQLSetPos 並將 RowNumber 設定為要刪除的數據列數目,並將 Operation 設定為 SQL_DELETE。

刪除數據之後,驅動程式會將適當數據列實作數據列狀態陣列中的值變更為SQL_ROW_DELETED(或SQL_ROW_ERROR)。

使用 SQLSetPos 更新數據

應用程式可以傳遞系結數據緩衝區中數據行的值,或是對SQLPutData進行一或多個呼叫。 使用 SQLPutData 傳遞數據的數據行稱為數據執行中數據行 這些通常用來傳送SQL_LONGVARBINARY和SQL_LONGVARCHAR數據行的數據,並可與其他數據行混合。

若要使用 SQLSetPos 更新資料,應用程式:

  1. 將值放在與 SQLBindCol 系結的數據和長度/指標緩衝區中:

    • 針對一般數據行,應用程式會將新的數據行值放在 *TargetValuePtr 緩衝區中,並將該值的長度放在 *StrLen_or_IndPtr 緩衝區中。 如果不應該更新數據列,應用程式會將SQL_ROW_IGNORE放在該數據列作業陣列的元素中。

    • 若為數據執行中數據行,應用程式會在 *TargetValuePtr 緩衝區中放置應用程式定義的值,例如數據行編號。 此值稍後可用來識別數據行。

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

  2. 呼叫 SQLSetPos並將 Operation 自變數設定為 SQL_UPDATE,以更新數據列。

    • 如果沒有數據執行中數據行,程式就會完成。

    • 如果有任何數據執行中數據行,函式會傳回SQL_NEED_DATA,然後繼續進行步驟 3。

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

    注意

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

    注意

    數據執行參數是 SQL 語句中的參數,當語句以 SQLExecDirectSQLExecute 執行時,會使用 SQLPutData 傳送數據。 它們會與 SQLBindParameter 系結,或使用 SQLSetDescRec 設定描述項。 SQLParamData回的值是傳遞至 ParameterValuePtr 自變數中 SQLBindParameter32 位值。

    注意

    數據執行數據行是數據列集中的數據行,當數據列以 SQLSetPos 更新數據列時,會使用 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 可以傳回 SQLSetPos 可傳回的任何 SQLSTATE。

如果數據已更新,驅動程式會將適當數據列實作數據列狀態陣列中的值變更為SQL_ROW_UPDATED。

如果作業取消,或在 SQLParamData 或 SQLPutData發生錯誤,在 SQLSetPos 傳回SQL_NEED_DATA之後,以及針對所有執行中數據行傳送數據之前,應用程式只能呼叫 SQLCancelSQLGetDiagFieldSQLGetDiagRecSQLGetFunctionsSQLParamData與語句相關聯的連接。 如果函式針對語句或與語句相關聯的連接呼叫任何其他函式,則函式會傳回 SQL_ERROR 和 SQLSTATE HY010 (函式序列錯誤)。

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

當與數據指標相關聯的查詢規格 SELECT 清單包含相同數據行的多個參考時,無論產生錯誤還是驅動程式會忽略重複的參考,並執行要求的作業是驅動程式定義的。

執行大量作業

如果 RowNumber 自變數為 0,則驅動程式會針對數據列集內每個數據列的 Operation 自變數執行 Operation 自變數中指定的作業,該數據列集的欄位在SQL_ATTR_ROW_OPERATION_PTR語句屬性所指向的數據列作業數位中,其字段中的值為 SQL_ROW_PROCEED。 這是SQL_DELETE、SQL_REFRESH或SQL_UPDATE之 Operation 自變數的 RowNumber 自變數的有效值,但不是SQL_POSITION。 具有 SQL_POSITION 作業RowNumber 等於 0 的 SQLSetPos 會傳回 SQLSTATE HY109 (數據指標位置無效)。

如果發生與整個數據列集相關的錯誤,例如 SQLSTATE HYT00 (逾時過期),驅動程式會傳回SQL_ERROR和適當的 SQLSTATE。 數據列集緩衝區的內容未定義,且數據指標位置不會變更。

如果發生與單一資料列相關的錯誤,驅動程式:

  • 將 SQL_ATTR_ROW_STATUS_PTR 語句屬性所指向之數據列狀態陣列中數據列的項目設定為SQL_ROW_ERROR。

  • 在錯誤佇列中張貼一或多個額外的 SQLSTATE,並在診斷數據結構中設定SQL_DIAG_ROW_NUMBER欄位。

處理錯誤或警告之後,如果驅動程式完成數據列集中剩餘數據列的作業,則會傳回SQL_SUCCESS_WITH_INFO。 因此,針對傳回錯誤的每個數據列,錯誤佇列會包含零個或多個額外的 SQLSTATE。 如果驅動程式在處理錯誤或警告之後停止作業,則會傳回SQL_ERROR。

如果驅動程式傳回任何警告,例如 SQLSTATE 01004(數據已截斷),則會傳回套用至整個數據列集或數據列集中未知數據列的警告,再傳回套用至特定數據列的錯誤資訊。 它會傳回特定數據列的警告,以及這些數據列的任何其他錯誤資訊。

如果 RowNumber 等於 0,且 Operation 是SQL_UPDATE、SQL_REFRESH或SQL_DELETE,SQLSetPos 所操作的數據列數目是由 SQL_ATTR_ROWS_FETCHED_PTR 語句屬性所指向。

如果 RowNumber 等於 0,且 Operation 是SQL_DELETE、SQL_REFRESH或SQL_UPDATE,則作業後的目前數據列與作業前的目前數據列相同。

忽略大量作業中的數據列

數據列作業陣列可用來指出使用 SQLSetPos 進行大量作業時,應該忽略目前數據列集中的數據列。 若要指示驅動程式在大量作業期間忽略一或多個資料列,應用程式應該執行下列步驟:

  1. 呼叫 SQLSetStmtAttr 將 SQL_ATTR_ROW_OPERATION_PTR 語句屬性設定為指向 SQLUSMALLINT 陣列。 您也可以呼叫 SQLSetDescField 來設定 ARD 的SQL_DESC_ARRAY_STATUS_PTR標頭欄位,這需要應用程式取得描述元句柄。

  2. 將資料列作業陣列的每個元素設定為兩個值之一:

    • SQL_ROW_IGNORE,表示已排除大量作業的數據列。

    • SQL_ROW_PROCEED,表示數據列包含在大量作業中。 (這是預設值。)

  3. 呼叫 SQLSetPos 以執行大量作業。

下列規則適用於資料列作業陣列:

  • SQL_ROW_IGNORE和SQL_ROW_PROCEED只會影響使用 SQLSetPos 搭配 SQL_DELETE或SQL_UPDATE作業的大量作業 。 它們不會影響使用 SQL_REFRESH 或 SQL_POSITION 作業SQLSetPos 的呼叫。

  • 根據預設,指標會設定為 null。

  • 如果指標為 null,所有數據列都會更新,就像所有元素都設定為SQL_ROW_PROCEED一樣。

  • 將項目設定為 SQL_ROW_PROCEED不保證作業會發生在該特定數據列上。 例如,如果數據列集中的特定數據列具有狀態SQL_ROW_ERROR,則不論應用程式是否指定了SQL_ROW_PROCEED,驅動程式都可能無法更新該數據列。 應用程式必須一律檢查數據列狀態陣列,以查看作業是否成功。

  • SQL_ROW_PROCEED在頭檔中定義為 0。 應用程式可以將數據列作業陣列初始化為 0,以處理所有資料列。

  • 如果數據列作業陣列中的元素編號 「n」 設定為 SQL_ROW_IGNORE,而且呼叫 SQLSetPos 來執行大量更新或刪除作業,則數據列集中的第 n 個數據列會在呼叫 SQLSetPos 之後維持不變。

  • 應用程式應該會自動將唯讀數據行設定為SQL_ROW_IGNORE。

忽略大量作業中的數據行

為了避免嘗試更新一或多個唯讀數據行所產生的不必要的處理診斷,應用程式可以將系結長度/指標緩衝區中的值設定為SQL_COLUMN_IGNORE。 如需詳細資訊,請參閱 SQLBindCol

程式碼範例

在下列範例中,應用程式可讓用戶流覽 ORDERS 數據表並更新訂單狀態。 數據指標是以數據列集大小為 20 的索引鍵集驅動,並使用開放式並行控制來比較數據列版本。 擷取每個數據列集之後,應用程式會列印它,並允許用戶選取並更新訂單的狀態。 應用程式會使用 SQLSetPos 將游標放在選取的數據列上,並執行數據列的位置更新。 (為了清楚起見,省略錯誤處理。

#define ROWS 20  
#define STATUS_LEN 6  
  
SQLCHAR        szStatus[ROWS][STATUS_LEN], szReply[3];  
SQLINTEGER     cbStatus[ROWS], cbOrderID;  
SQLUSMALLINT   rgfRowStatus[ROWS];  
SQLUINTEGER    sOrderID, crow = ROWS, irow;  
SQLHSTMT       hstmtS, hstmtU;  
  
SQLSetStmtAttr(hstmtS, SQL_ATTR_CONCURRENCY, (SQLPOINTER) SQL_CONCUR_ROWVER, 0);  
SQLSetStmtAttr(hstmtS, SQL_ATTR_CURSOR_TYPE, (SQLPOINTER) SQL_CURSOR_KEYSET_DRIVEN, 0);  
SQLSetStmtAttr(hstmtS, SQL_ATTR_ROW_ARRAY_SIZE, (SQLPOINTER) ROWS, 0);  
SQLSetStmtAttr(hstmtS, SQL_ATTR_ROW_STATUS_PTR, (SQLPOINTER) rgfRowStatus, 0);  
SQLSetCursorName(hstmtS, "C1", SQL_NTS);  
SQLExecDirect(hstmtS, "SELECT ORDERID, STATUS FROM ORDERS ", SQL_NTS);  
  
SQLBindCol(hstmtS, 1, SQL_C_ULONG, &sOrderID, 0, &cbOrderID);  
SQLBindCol(hstmtS, 2, SQL_C_CHAR, szStatus, STATUS_LEN, &cbStatus);  
  
while ((retcode == SQLFetchScroll(hstmtS, SQL_FETCH_NEXT, 0)) != SQL_ERROR) {  
   if (retcode == SQL_NO_DATA_FOUND)  
      break;  
   for (irow = 0; irow < crow; irow++) {  
      if (rgfRowStatus[irow] != SQL_ROW_DELETED)  
         printf("%2d %5d %*s\n", irow+1, sOrderID, NAME_LEN-1, szStatus[irow]);  
   }  
   while (TRUE) {  
      printf("\nRow number to update?");  
      gets_s(szReply, 3);  
      irow = atoi(szReply);  
      if (irow > 0 && irow <= crow) {  
         printf("\nNew status?");  
         gets_s(szStatus[irow-1], (ROWS * STATUS_LEN));  
         SQLSetPos(hstmtS, irow, SQL_POSITION, SQL_LOCK_NO_CHANGE);  
         SQLPrepare(hstmtU,  
          "UPDATE ORDERS SET STATUS=? WHERE CURRENT OF C1", SQL_NTS);  
         SQLBindParameter(hstmtU, 1, SQL_PARAM_INPUT,  
            SQL_C_CHAR, SQL_CHAR,  
            STATUS_LEN, 0, szStatus[irow], 0, NULL);  
         SQLExecute(hstmtU);  
      } else if (irow == 0) {  
         break;  
      }  
   }  
}  

如需更多範例,請參閱使用 SQLSetPos 來定位 Update 和 Delete 語句和更新數據列集中的數據列。

如需下列資訊 請參閱
將緩衝區系結至結果集中的數據行 SQLBindCol 函式
執行與區塊數據指標位置無關的大量作業 SQLBulkOperations 函式
取消語句處理 SQLCancel 函式
擷取數據區塊或捲動結果集 SQLFetchScroll 函式
取得描述項的單一欄位 SQLGetDescField 函式
取得描述項的多個字段 SQLGetDescRec 函式
設定描述項的單一欄位 SQLSetDescField 函式
設定描述元的多個字段 SQLSetDescRec 函式
設定語句屬性 SQLSetStmtAttr 函式

另請參閱

ODBC API 參考
ODBC 標頭檔