模擬定位更新和刪除語句

如果資料來源不支援定位式的更新與刪除語句,驅動程式可以模擬這些語句。 例如,ODBC 游標資料庫模擬定位更新與刪除的語句。 模擬定位更新與刪除語句的一般策略是將定位語句轉換為已搜尋語句。 這是透過將 WHERE CURRENT OF 子句替換為已搜尋的 WHERE 子句來識別當前列來完成。

例如,由於 CustID 欄位能唯一識別 Customers 資料表中的每一列,因此定位刪除語句可以使用此識別功能進行操作

DELETE FROM Customers WHERE CURRENT OF CustCursor  

可能被轉換為

DELETE FROM Customers WHERE (CustID = ?)  

驅動程式可在 WHERE 子句中使用以下 列識別碼 之一:

  • 欄位的值用來唯一識別表格中的每一列。 例如,呼叫 SQLSpecialColumns 搭配 SQL_BEST_ROWID 會回傳達成此目的的最佳欄位或欄位集合。

  • 偽欄位,由某些資料來源提供,目的是用來唯一識別每一列。 這些資料也可以透過呼叫 SQLSpecialColumns 來取得。

  • 如果有,則提供獨特的索引。

  • 結果集中的所有欄位。

驅動程式在 WHERE 子句中應使用哪些欄位,取決於驅動程式。 在某些資料來源中,確定列識別碼可能成本較高。 然而,它執行速度更快,且能保證模擬語句最多更新或刪除一列。 根據底層資料庫管理系統(DBMS)的能力,使用列識別碼的設定成本可能相當高昂。 然而,它執行速度更快,且能保證模擬語句只會更新或刪除一列。 使用結果集中所有欄位的選項通常更容易設定。 然而,執行速度較慢,且若欄位無法唯一識別某一列,可能導致資料列被無意間更新或刪除,尤其當該結果集的選擇清單未包含底層資料表中所有欄位時。

根據驅動程式支援的前述策略,應用程式可以選擇想要驅動程式採用哪種策略,並帶有 SQL_ATTR_SIMULATE_CURSOR 陳述屬性。 雖然應用程式可能冒著無意間更新或刪除某一列的風險,但應用程式可以透過確保結果集中的欄位唯一識別每一列來消除此風險。 這樣可以省去駕駛人必須親自操作的麻煩。

若驅動程式選擇使用列識別碼,則會攔截建立結果集的 SELECT FOR UPDATE 語句。 若 select 清單中的欄位無法有效識別某一列,驅動程式會在 select 清單的末尾新增必要的欄位。 有些資料來源只有一個欄位,能始終唯一識別某一列,例如 Oracle 中的 ROWID 欄位;若有此類欄位,驅動程式會使用此欄。 否則,驅動程式會針對 FROM 子句中的每個資料表呼叫 SQLSpecialColumns,以取得唯一識別每列的欄位清單。 此技術常見的限制是,若 FROM 子句中有多個資料表,游標模擬會失敗。

不論驅動程式如何識別列,通常會在將 FOR UPDATE OF 子句從 SELECT FOR UPDATE 陳述式中移除後,再將其送至資料來源。 FOR UPDATE OF 子句僅用於定位式 update 與 delete 語句。 資料來源若不支援定位式更新和刪除語句,通常就不支援此功能。

當應用程式提交定位更新或刪除語句以執行時,驅動程式會將 WHERE CURRENT OF 子句替換為包含列識別符的 WHERE 子句。 這些欄位的值是從驅動程式為其在 WHERE 子句中使用的每個欄位維護的快取中取得的。 驅動程式替換 WHERE 子句後,會將該陳述式傳送至資料來源執行。

例如,假設應用程式提交以下語句以建立結果集:

SELECT Name, Address, Phone FROM Customers FOR UPDATE OF Phone, Address  

如果應用程式設定了SQL_ATTR_SIMULATE_CURSOR請求唯一性保證,且資料來源沒有提供一個總是能唯一識別某列的虛擬欄位,驅動程式會呼叫 SQLSpecialColumns 來存取 Customers 資料表,發現 CustID 是 Customers 資料表的金鑰,並將此資料加入至 select 清單中,並刪除 FOR UPDATE OF 條款:

SELECT Name, Address, Phone, CustID FROM Customers  

若應用程式未請求唯一性保證,驅動程式僅移除 FOR UPDATE OF 子句:

SELECT Name, Address, Phone FROM Customers  

假設應用程式在結果集中捲動,並提交以下定位更新語句以供執行,其中 Cust 是該結果集上的游標名稱:

UPDATE Customers SET Address = ?, Phone = ? WHERE CURRENT OF Cust  

若應用程式未請求唯一性保證,驅動程式會替換 WHERE 子句,並將 CustID 參數綁定至快取中的變數:

UPDATE Customers SET Address = ?, Phone = ? WHERE (CustID = ?)  

若應用程式未要求唯一性保證,驅動程式會替換 WHERE 子句,並將此子句中的 Name、Address 與 Phone 參數綁定至快取中的變數:

UPDATE Customers SET Address = ?, Phone = ?  
   WHERE (Name = ?) AND (Address = ?) AND (Phone = ?)