Compartilhar via


Simular instruções de exclusão e atualização posicionadas

Se a fonte de dados não der suporte a instruções de atualização e exclusão posicionadas, o driver poderá simulá-las. Por exemplo, a biblioteca de cursores ODBC simula instruções de atualização e exclusão posicionadas. A estratégia geral para simular instruções de atualização e exclusão posicionadas é converter instruções posicionadas em instruções pesquisadas. Isso é feito substituindo a cláusula WHERE CURRENT OF por uma cláusula WHERE pesquisada que identifica a linha atual.

Por exemplo, como a coluna CustID identifica exclusivamente cada linha na tabela Clientes, a instrução de exclusão posicionada

DELETE FROM Customers WHERE CURRENT OF CustCursor  

pode ser convertido em

DELETE FROM Customers WHERE (CustID = ?)  

O driver pode usar um dos seguintes identificadores de linha na cláusula WHERE :

  • Colunas cujos valores servem para identificar exclusivamente cada linha da tabela. Por exemplo, chamar SQLSpecialColumns com SQL_BEST_ROWID retorna a coluna ou o conjunto ideal de colunas que atendem a essa finalidade.

  • Pseudo-colunas, fornecidas por algumas fontes de dados, com a finalidade de identificar exclusivamente cada linha. Eles também podem ser recuperáveis chamando SQLSpecialColumns.

  • Um índice exclusivo, se disponível.

  • Todas as colunas no conjunto de resultados.

Exatamente quais colunas um driver deve usar na cláusula WHERE que ele constrói depende do driver. Em algumas fontes de dados, determinar um identificador de linha pode ser caro. No entanto, é mais rápido executar e garante que uma instrução simulada atualize ou exclua no máximo uma linha. Dependendo dos recursos do DBMS subjacente, o uso de um identificador de linha pode ser caro para configurar. No entanto, é mais rápido executar e garante que uma instrução simulada atualizará ou excluirá apenas uma linha. A opção de usar todas as colunas no conjunto de resultados geralmente é muito mais fácil de configurar. No entanto, é mais lento executar e, se as colunas não identificarem exclusivamente uma linha, podem resultar em linhas sendo atualizadas ou excluídas involuntariamente, especialmente quando a lista de seleção para o conjunto de resultados não contém todas as colunas que existem na tabela subjacente.

Dependendo de quais das estratégias anteriores o driver dá suporte, um aplicativo pode escolher qual estratégia deseja que o driver use com o atributo de instrução SQL_ATTR_SIMULATE_CURSOR. Embora possa parecer estranho que um aplicativo arrisque a atualização ou exclusão acidental de uma linha, o aplicativo pode remover esse risco garantindo que as colunas no conjunto de resultados identifiquem exclusivamente cada linha no conjunto de resultados. Isso salva o driver do esforço de ter que fazer isso.

Se o driver optar por usar um identificador de linha, ele intercepta a instrução SELECT FOR UPDATE que cria o conjunto de resultados. Se as colunas na lista de seleção não identificarem efetivamente uma linha, o driver adicionará as colunas necessárias ao final da lista de seleção. Algumas fontes de dados têm uma única coluna que sempre identifica exclusivamente uma linha, como a coluna ROWID no Oracle; se essa coluna estiver disponível, o driver usará isso. Caso contrário, o driver chamará SQLSpecialColumns para cada tabela na cláusula FROM para recuperar uma lista das colunas que identificam exclusivamente cada linha. Uma restrição comum resultante dessa técnica é que a simulação de cursor falhará se houver mais de uma tabela na cláusula FROM .

Não importa como o driver identifica linhas, ele geralmente remove a cláusula FOR UPDATE OF da instrução SELECT FOR UPDATE antes de enviá-la para a fonte de dados. A cláusula FOR UPDATE OF é usada apenas com instruções de atualização e exclusão posicionadas. Fontes de dados que não dão suporte a instruções de atualização e exclusão posicionadas geralmente também não oferecem suporte a essas operações.

Quando o aplicativo envia uma instrução de atualização ou exclusão posicionada para execução, o driver substitui a cláusula WHERE CURRENT OF por uma cláusula WHERE que contém o identificador de linha. Os valores dessas colunas são recuperados de um cache mantido pelo driver para cada coluna que ele usa na cláusula WHERE . Depois que o driver substitui a cláusula WHERE , ele envia a instrução para a fonte de dados para execução.

Por exemplo, suponha que o aplicativo envie a seguinte instrução para criar um conjunto de resultados:

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

Se o aplicativo tiver definido SQL_ATTR_SIMULATE_CURSOR para solicitar uma garantia de exclusividade e se a fonte de dados não fornecer uma pseudo-coluna que sempre identifique exclusivamente uma linha, o driver chamará SQLSpecialColumns para a tabela Customers, descobrirá que CustID é a chave para a tabela Clientes e adiciona isso à lista de seleção, e remove a cláusula FOR UPDATE OF :

SELECT Name, Address, Phone, CustID FROM Customers  

Se o aplicativo não tiver solicitado uma garantia de exclusividade, o driver removerá apenas a cláusula FOR UPDATE OF :

SELECT Name, Address, Phone FROM Customers  

Suponha que o aplicativo navegue pelo conjunto de resultados e envie a seguinte instrução de atualização posicionada para execução, onde Cust é o nome do cursor sobre o conjunto de resultados:

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

Se o aplicativo não tiver solicitado uma garantia de exclusividade, o driver substituirá a cláusula WHERE e associará o parâmetro CustID à variável em seu cache:

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

Se o aplicativo não tiver solicitado uma garantia de exclusividade, o driver substituirá a cláusula WHERE e associará os parâmetros Name, Address e Phone nesta cláusula às variáveis em seu cache:

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