This is an example of a HTML caption with a link.
Artigos

ADO: Atualizando registros com ClientDataSets e DataSetProviders

Quando voce utiliza os componentes ADO, seu engine para acesso a banco de dados deixa de ser o BDE e passa a ser o MDAC. Certifique-se de estar usando o MDAC mais novo disponível. O UpdateSQL é utilizado apenas por aplicações que utilizam BDE. Trata-se de um componente para definição em design time das sentenças SQLs a serem utilizadas pelas Queries. Oque acontece é que o BDE está descontinuado desde 1999 e, com ele, o nosso velho amigo UpdateSQL. Mas como então serão definidas as sentenças SQLs ? Existem dois caminhos: utilizar ou não utilizar ClientDataSets e DataSetProviders.

Vou exemplificar o primeiro caso. Vamos começar do inicio.

1) Na aplicação abaixo, acesso uma base DB2 onde existe uma tabela de veículos com seus respectivos tipos relacionados por um simples join. Para acessar a base, voce deve utilizar um componente TADOConnection (no BDE voce utilizaria o TDatabase). Informe uma string de conexão ou um arquivo que contenha essas informações (Arquivos Data Link). Utilizar um ou outro vai depender de sua estratégia de distribuição. Note que utilizando string de conexão (não dinamicamente, claro) as informações de conexão ao banco estarão codificadas no seu EXE. Com arquivos Data Link voce pode atualizar essas informações sem ter de gerar uma nova versão do executavel. É mais ou menos como usar alias do BDE ou definir o acesso dentro da aplicação.

2) Agora eu vou colocar um TADOQuery, definir a sentenca SQL e apontar para o TADOConnection (note que o TADOQuery pode apontar diretamente para o banco, mas isso não será demonstrado aqui). Trarei campos da tabela que considero principal para atualização, deleção, inserção (veículo) e uma que somente usarei para descrever o código do tipo. Assim teremos:
select v.*, t.descr_tipo_veiculo from tb_veiculo v, tb_tipo_veiculo t where (t.id_tipo_veiculo = v.id_tipo_veiculo)

3) O próximo componente a ser adicionado é o TDataSetProvider. Observe que ele possui uma propriedade denominada UpdateMode. Sim, aqui é uma parte do que estamos procurando. UpdateMode define o critério de atualização de registros quando é disparado o método ApplyUpdates. Mas se aqui é uma parte, onde estará a outra ? Antes disso, note que a propriedade DataSet aponta para componente ADOQuery1 adicionado anteriormente. O provider servirá como fonte de informações para o clientdataset. Agora examine as propriedades do clientdataset1. ProviderName aponta corretamente para DataSetProvider1. Por último, um datasource que aponta para o clientdataset (da mesma forma como poderia apontar para um TTable, TQuery, TADOQuery, TSQLQuery, etc...). Desta forma, temos:
TDataSource -> TClientDataSet -> TDataSetProvider -> TADOQuery -> TADOConnection
'->' significa 'aponta para'

4) Agora vamos ver onde está a outra parte do problema. Se, por um lado, o critério para atualização dos registros é definido no Provider, por outro, a definição de quem será atualizado e quem será utilizado como chave nesta mesma atualização é feito individualmente em cada TField. Para isso, adicionei no ADOQuery1 fields persistentes e utilizei a propriedade ProviderFlags, individualmente. Neste exemplo voce notará que estou usando UpdateMode (DataSetProvider) como upWhereAll e ajustando os ProviderFlags (Field), DOS CAMPOS DA TABELA PRINCIPAL, como [pfInUpdate,pfInWhere]. Entretanto, o campo que vem através do JOIN, possui ProviderFlags ajustado para []. Ou seja, este campo não fará parte, em hipótese alguma, do SQL que será construído pelo DataSetProvider para atualização.

5) Agora experimente:
a) Alterar ProviderFlags do campo que é trazido pelo Join (DESCR_TIPO_VEICULO), ativando pfInUpdate e/ou pfInWhere. Note que ocorrerão erros de SQL, pois o Provider montará de forma errada a sentença SQL de atualização. Lógico que, se você ativar pfInUpdate só verá o erro se tentar atualizar o campo DESCR_TIPO_VEICULO.
b) Alterar a sentença SQL para "... from tb_tipo_veiculo t, tb_veiculo v ...". Toda a aplicação ficará inválida pois será considerado como tabela principal tb_tipo_veiculo ao invés de tb_veiculo. Voce pode controlar isso codificando o evento OnGetTableName (DataSetProvider) e ajustando o parametro TableName para o nome da tabela que considera como principal.

Bom, aí está o "TUpdateSQL" neste novo mundo ! Recomendo ler o help do delphi, tópicos:
- UpdateMode,TBaseProvider;
- ProviderFlags, TField;

Lembre-se apenas de distribuir Midas.dll junto com sua aplicação ou compilar a unit necessária junto com seu executável.