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的 HandleType StatementHandle 控制碼 ,即可取得相關聯的 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) 語句上已開啟 資料指標,但 未呼叫 SQLFetch SQLFetchScroll

已開啟 StatementHandle 上的 資料指標,而且 已呼叫 SQLFetch SQLFetchScroll ,但資料指標位於結果集的開頭之前或結果集結尾之後。

引數 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 上 呼叫 SQLCancel SQLCancelHandle ,然後在 StatementHandle 再次呼叫函式。

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

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

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

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

(DM) 驅動程式是 ODBC 2.x 驅動程式,在 呼叫 SQLFetch 之後 ,SQLSetPos 會呼叫 StatementHandle
HY011 無法立即設定屬性 (DM) 驅動程式是 ODBC 2.x 驅動程式;已設定SQL_ATTR_ROW_STATUS_PTR語句屬性;然後在 呼叫 SQLFetch SQLFetchScroll SQLExtendedFetch 之前 呼叫 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或長資料來源特定資料類型;和 SQLGetInfo SQL_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 相關聯的資料指標已定義為正向,因此資料指標無法放置在資料列集內。 請參閱 SQLSetStmtAttr SQL_ATTR_CURSOR_TYPE屬性的描述。

Operation 引數SQL_UPDATE、SQL_DELETE或SQL_REFRESH,且 RowNumber 引數所 識別的資料列已刪除或尚未擷取。

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

在呼叫 SQLBulkOperations 之後 呼叫 SQLSetPos ,並在呼叫 SQLFetchScroll SQLFetch 之前 呼叫。
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的資料列狀態。 在下次擷取之前,資料列集中已刪除的資料列將繼續標示為已刪除。 如果資料指標支援封裝,則資料列會在下一個擷取中消失(後續 的 SQLFetch SQLFetchScroll 不會傳回已刪除的資料列)。

執行 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 和 SQLSTATE 42000 (語法錯誤或存取違規)。

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

透過 SQLSetPos 鎖定的資料列會保持鎖定狀態,直到應用程式針對 LockType 設定為 SQL_LOCK_UNLOCK的資料列 呼叫 SQLSetPos ,或是應用程式使用 SQL_CLOSE 選項呼叫 SQLFreeHandle SQLFreeStmt 為止。 對於支援交易的驅動程式,當應用程式呼叫 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 、SQLFetchScroll SQLBulkOperations SQLSetPos 之後,設定此陣列中的狀態值。 這個陣列是由 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. 呼叫 SQLExecDirect SQLExecute 或目錄函式來建立結果集。

  4. 呼叫 SQLFetch SQLFetchScroll 以擷取資料。

如需使用 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或長資料來源特定資料類型,而驅動程式會針對 SQLGetInfo SQL_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 語句中的參數,當語句以 SQLExecDirect SQLExecute 執行時,會使用 SQLPutData 傳送 資料。 它們會與 SQLBindParameter 系結,或使用 SQLSetDescRec 設定描述項 。 SQLParamData 回的值是傳遞至 ParameterValuePtr 引數中 SQLBindParameter 的 32 位值。

    注意

    資料執行資料行是資料列集中的資料行,當資料列以 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之後,以及針對所有執行中資料行傳送資料之前,應用程式只能 呼叫 SQLCancel SQLGetDiagField SQLGetDiagRec SQLGetFunctions SQLParamData 與語句相關聯的 連接。 如果函式針對 語句或與 語句相關聯的連接呼叫任何其他函式,則函式會傳回 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 標頭檔