Partilhar via


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

Se a fonte de dados não suportar instruções posicionadas de atualização e eliminação, o driver pode simulá-las. Por exemplo, a biblioteca de cursores ODBC simula instruções posicionadas de atualização e eliminação. A estratégia geral para simular instruções de atualização e eliminação posicionadas é converter instruções posicionadas em sentenças pesquisadas. Isto é feito substituindo a cláusula ONDE ATUAL DE por uma cláusula ONDE pesquisada que identifica a linha atual.

Por exemplo, porque a coluna CustID identifica de forma única cada linha na tabela Clientes, a instrução de eliminação posicionada

DELETE FROM Customers WHERE CURRENT OF CustCursor  

pode ser convertido em

DELETE FROM Customers WHERE (CustID = ?)  

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

  • Colunas cujos valores servem para identificar de forma única cada linha da tabela. Por exemplo, chamar SQLSpecialColumns com SQL_BEST_ROWID retorna a coluna ou conjunto ótimo de colunas que servem este propósito.

  • Pseudo-colunas, fornecidas por algumas fontes de dados, com o objetivo de identificar unicamente cada linha. Estes também podem ser recuperados chamando SQLSpecialColumns.

  • Um índice único, se disponível.

  • Todas as colunas do conjunto de resultados.

Exatamente quais as colunas que um driver deve usar na cláusula WHERE que constrói dependem do driver. Em algumas fontes de dados, determinar um identificador de linha pode ser dispendioso. No entanto, é mais rápido de executar e garante que uma instrução simulada atualiza ou elimina no máximo uma linha. Dependendo das capacidades do SGBD subjacente, usar um identificador de linha pode ser dispendioso de configurar. No entanto, é mais rápido de executar e garante que uma instrução simulada irá atualizar ou eliminar apenas uma linha. A opção de usar todas as colunas do conjunto de resultados é geralmente muito mais fácil de configurar. No entanto, é mais lento a executar e, se as colunas não identificarem de forma única uma linha, pode resultar em que as linhas sejam atualizadas ou eliminadas involuntariamente, especialmente quando a lista de seleção para o conjunto de resultados não contém todas as colunas existentes na tabela subjacente.

Dependendo de qual das estratégias anteriores o driver suporta, uma aplicação pode escolher qual estratégia quer que o driver use com o atributo da instrução SQL_ATTR_SIMULATE_CURSOR. Embora possa parecer estranho para uma aplicação arriscar atualizar ou eliminar involuntariamente uma linha, a aplicação pode eliminar este risco garantindo que as colunas do conjunto de resultados identificam de forma única cada linha do conjunto de resultados. Isto poupa ao condutor o esforço de ter de o fazer.

Se o driver optar por usar um identificador de linha, interceta a instrução SELECT FOR UPDATE que cria o conjunto de resultados. Se as colunas da lista de seleção não identificam efetivamente uma linha, o driver adiciona as colunas necessárias ao final da lista de seleção. Algumas fontes de dados têm uma única coluna que identifica sempre de forma única uma linha, como a coluna ROWID no Oracle; se tal coluna estiver disponível, o driver usa esta. Caso contrário, o driver chama SQLSpecialColumns para cada tabela da cláusula FROM para recuperar uma lista das colunas que identificam de forma única cada linha. Uma restrição comum que resulta desta técnica é que a simulação do cursor falha se houver mais do que uma tabela na cláusula FROM .

Independentemente de como o driver identifica as linhas, normalmente remove a cláusula FOR UPDATE OF da instrução SELECT FOR UPDATE antes de a enviar para a fonte de dados. A cláusula FOR UPDATE OF é usada apenas com instruções de atualização e eliminação posicionadas. As fontes de dados que não suportam instruções posicionadas de atualização e eliminação geralmente não o suportam.

Quando a aplicação submete uma instrução de atualização ou eliminação posicionada para execução, o driver substitui a cláusula WHERE CURRENT OF por uma cláusula WHERE contendo o identificador de linha. Os valores destas colunas são recuperados de uma cache mantida pelo driver para cada coluna utilizada na cláusula WHERE . Depois de o driver substituir a cláusula WHERE , envia a instrução para a fonte de dados para execução.

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

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

Se a aplicação definiu SQL_ATTR_SIMULATE_CURSOR para pedir uma garantia de unicidade e se a fonte de dados não fornecer uma pseudo-coluna que identifique sempre de forma única uma linha, o driver chama SQLSpecialColumns para a tabela Customers, descobre que o CustID é a chave da tabela Customers e adiciona-a à lista de seleção, e remove a cláusula FOR UPDATE OF :

SELECT Name, Address, Phone, CustID FROM Customers  

Se a aplicação não tiver solicitado uma garantia de unicidade, o driver remove apenas a cláusula FOR UPDATE OF :

SELECT Name, Address, Phone FROM Customers  

Suponha que a aplicação percorre o conjunto de resultados e submete 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 a aplicação não tiver solicitado uma garantia de unicidade, o driver substitui a cláusula WHERE e associa o parâmetro CustID à variável na sua cache:

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

Se a aplicação não tiver solicitado uma garantia de unicidade, o driver substitui a cláusula ONDE e associa os parâmetros Nome, Endereço e Telefone nesta cláusula às variáveis na sua cache:

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