

Atualizações Em Recordsets do lado Cliente
Considere a seguinte atualização em um recordset ADO conectado
Dim rs As New Recordset
rs.CursorLocation = adUseClient
rs.Open "SELECT * from Clientes", _
STRING_DE_CONEXAO, , adLockOptimistic
rs.Update "Nome", "Carlos Gomes"
rs.Close
ADO gera uma Query Based Update (QBU) para realizar esta operação:
UPDATE "Clientes" SET "Nome"= ?
WHERE "IDCliente" = ? AND "Nome"= ?
Valores de parâmetros são fornecidos como parte do processo de atualização
A cláusula WHERE tem duas partes:
-Os campos de 'novos valores' (mudados)
-A chave primária
Campos de Novos Valores
ADO identifica campos de 'Novos Valores' comparando duas propriedades de cada objeto Field:
-UnderlyingValue
-Value
O nome da tabela e da coluna para as cláusulas UPDATE e SET são derivadas das propriedades dinâmicas de um objeto Field:
-SCHEMANAME, CATALOGNAME
-BASETABLENAME
-BASECOLUMNNAME
Identificação de Linha
O UPDATE precisa identificar a linha em questão. ADO identifica a chave primária.
-Usa a propriedade dinâmica KEYCOLUMN
Se o recordset não contém uma chave primária ...
-O UPDATE pode atualizar mais de um registro. ADO gera um erro, mas atualiza mesmo assim.
-Com o SQLServer 7, ADO automaticamente recupera as chaves primárias para os recordsets atualizáveis.
Armazenadas como 'Colunas Ocultas'
Bloqueio
Por que a cláusula WHERE, abaixo, contém o(s) campo(s) de
'Novo(s) Valor(es)'?
UPDATE "Clientes" SET "Nome" = ?
WHERE "IDCliente" = ? AND "Nome" = ?
Acima, na cláusula WHERE, "IDCliente"
= ? identifica a linha, "Nome" = ? simula bloqueio.
Após o UPDATE, ADO checa o número de registros afetados. Um valor de 0 gera um erro:
-2147217864 Linha não pode ser bloqueada para atualização.
Alguns valores podem ter sido mudados desde que foi lida pela última vez.
Bloqueio baseado nos campos de 'Novos Valores' não é o mesmo que bloqueio de registro inteiro.
ADO permite que você controle que campos são usados para gerar a cláusula WHERE:
rs.Properties("Update Criteria") = adCriteriaKey
rs.Properties("Update Criteria") = adCriteriaUpdCols
rs.Properties("Update Criteria") = adCriteriaAllCols
rs.Properties("Update Criteria") = adCriteriaTimeStamp
Atualizando Joins
No mundo real, muitas consultas são baseadas em joins, e as pessoas querem atualizá-las.
Considere
SELECT R.IDRegiao As ID ,R.DescricaoDeRegiao,
T.IDTerritorio, T.DescricaoDeTerritorio, T.IDRegiao
FROM Regioes R, Territorios T
where R.IDRegiao = 4 and R.IDRegiao = T.IDRegiao

Esta consulta retorna os seguintes dados
| ID |
Descrição
da Região |
IDTerritorio |
Descrição
do Territorio |
IdRegiao |
|
| 4 |
Sudeste |
38222 |
Santos |
1 |
| 4 |
Sudeste |
43234 |
Rio
de Janeiro |
1 |
| 4 |
Sudeste |
12984 |
São
Paulo |
1 |
| 4 |
Sudeste |
41344 |
Campos |
1 |
| 4 |
Sudeste |
25421 |
Campinas |
1 |
| 4 |
Sudeste |
13754 |
Ribeirão
Preto |
1 |
| 4 |
Sudeste |
23456 |
Goitacazes |
1 |
| 4 |
Sudeste |
29872 |
Sorocaba |
1 |
Join - rs.Update
Aqui está o que ocorre quando eu mudo o campo DescricaoDeRegiao da tabela
Regioes e chamo um Update:
UPDATE Regiao" SET "DescricaoDeRegiao"=?
WHERE "DescricaoDeRegiao"=? AND "IDRegiao"=?
... e quando eu mudo DescricaoDeTerritorio da tabela Territorios e chamo Update:
UPDATE "Territorios" SET "DescricaoDeTerritorio"=?
WHERE "IDTerritorio=?
AND "DescricaoDeTerritorio"=?
... e se eu mudo ambos estes campos e chamo Update
UPDATE "Regioes" SET "DescricaoDeRegiao"=?
WHERE "DescricaoDeRegiao"=? AND "IDRegiao"=?
UPDATE "Territorios" SET "DescricaoDeTerritorio"=?
WHERE "IDTerritorio"=?
AND "DescricaoDeTerritorio"=?
Join - rs.Delete
A diversão começa quando eu chamo rs.Delete:
DELETE FROM "Territorios" WHERE "IDTerritorio"=?
DELETE FROM "Regioes" WHERE "IDRegiao"=?
Eu provavelmente não quero que isto aconteça!
Se o meu banco de dados tem integridade referencial, isto irá causar um erro.
Join - rs.AddNew
Se eu apenas forneço os campos da tabela Territorios
INSERT INTO Territorios" ("IDTerritorio","DescricaoDeTerritorio","IDRegiao") VALUES (?,?,?)
Isto parece estar bem, mas:
- Agora há vazios no recordset, porque eu não forneci valores para os campos de Regioes
-Se eu fornecer valores para estes campos, ADO gera um comando INSERT para a tabela Regioes.
O quê provavelmente eu não quero também!
O Problema
QBU tem dois problemas potenciais quando o recordset é baseado em joins:
1.rs.Delete tentará deletar um registro de cada tabela usada no recordset
2.Para evitar a geração de um indesejável insert após um rs.AddNew, eu tenho vazios no meu recordset onde os dados deveriam estar.
A Soluçao
ADO 2.1 indroduziu o conceito de 'Unique Table' (Tabela Única):
-Comandos Delete são gerados apenas para 'Unique Tables'
-Quando uma 'Unique Table' é especificada, um comando Resync personalizado pode ser usado para preencher os vazios deixados após uma chamada a rs.AddNew
Especificando uma tabela única
rs.Properties("Unique Catalog") = "NorthWind"
rs.Properties("Unique Table") = "Territorios"
rs.Delete
gera o seguinte SQL:
DELETE FROM "Territorios" WHERE "IDTerritorio"=?
Especificando um Resync personalizado
rs.Properties("Unique Catalog") = "NorthWind"
rs.Properties("Unique Table") = "Territorios"
rs.Properties("Resync Command") = _ ' ATRIBUI A
PROPRIEDADE DINÂMICA
' RESYNC COMMAND
"select R.IDRegiao As ID, " & _
"R.DescricaoDeRegiao, T.IDTerritorio, " & _
"T.DescricaoDeTerritorio, T.IDRegiao " & _
"from Regioes R, Territorios T Where " & _
"T.IDTerritorio = ? And R.IDRegiao = T.IDRegiao"
'INCLUI UM MARCADOR DE
'PARÂMETRO PARA CADA
'CAMPO DA CHAVE
'PRIMÁRIA DA TABELA ÚNICA
rs.AddNew
rs!IDTerritorio = 1000
rs!DescricaoDeTerritorio = "Sorocaba"
rs!IDRegiao = 4
rs.Update ' ADICIONA SEM TOCAR NA TABELA REGIOES
rs.Resync adAffectCurrent 'CHAMA RESYNC PARA PREENCHER OS VAZIOS