Моделирование инструкций позиционированного обновления и удаления

Если источник данных не поддерживает позиционированные инструкции обновления и удаления, драйвер может имитировать их. Например, библиотека курсоров 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 , который он создает, зависит от драйвера. В некоторых источниках данных определение идентификатора строки может быть дорогостоящим. Тем не менее, выполняется быстрее и гарантируется, что имитированная инструкция обновляет или удаляет не более одной строки. В зависимости от возможностей базовых СУБД, использование идентификатора строки может быть дорогостоящим для настройки. Однако быстрее выполнять и гарантировать, что имитированная инструкция будет обновлять или удалять только одну строку. Вариант использования всех столбцов в результирующем наборе обычно гораздо проще настроить. Однако выполнение выполняется медленнее, и если столбцы не однозначно идентифицируют строку, это может привести к непреднамеренно обновляемым или удаленным строкам, особенно если список выбора для результирующего набора не содержит все столбцы, существующие в базовой таблице.

В зависимости от того, какие из предыдущих стратегий поддерживает драйвер, приложение может выбрать стратегию, которую он хочет использовать с атрибутом оператора SQL_ATTR_SIMULATE_CURSOR. Хотя приложение может показаться нечетным, чтобы непреднамеренно обновлять или удалять строку, приложение может удалить этот риск, гарантируя, что столбцы в результирующем наборе однозначно определяют каждую строку в результирующем наборе. Это позволяет сохранить драйверу усилия, необходимые для этого.

Если драйвер выбирает использование идентификатора строки, он перехватывает инструкцию SELECT FOR UPDATE , которая создает результирующий набор. Если столбцы в списке выбора не определяют строку, драйвер добавляет необходимые столбцы в конец списка выбора. Некоторые источники данных имеют один столбец, который всегда однозначно определяет строку, например столбец ROWID в Oracle; Если такой столбец доступен, драйвер использует это. В противном случае драйвер вызывает SQLSpecialColumns для каждой таблицы в предложении FROM , чтобы получить список столбцов, однозначно определяющих каждую строку. Общее ограничение, которое приводит к этому методу, заключается в том, что моделирование курсоров завершается ошибкой, если в предложении FROM существует несколько таблиц.

Независимо от того, как драйвер определяет строки, обычно удаляет предложение FOR UPDATE OF от инструкции SELECT FOR UPDATE перед отправкой в источник данных. Предложение FOR UPDATE OF используется только с позиционированных инструкций обновления и удаления. Источники данных, которые не поддерживают позиционированные инструкции обновления и удаления, обычно не поддерживают его.

Когда приложение отправляет позиционированную инструкцию обновления или удаления для выполнения, драйвер заменяет предложение 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 и добавляет его в список выбора. и удаляет предложение 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 и Телефон в этом предложении к переменным в своем кэше:

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