Olá pessoal, neste artigo será demonstrado um conjunto de configurações na propriedade ProviderFlags do componente TSQLQuery que possibilita gerar instruções SQL de Update e Delete para os campos de uma tabela, mesmo quando nossa consulta envolve relacionamento com várias tabelas.

No início parece meio confuso, mas com o decorrer do artigo será visto como esse tipo de funcionalidade pode ser muito útil no cotidiano.

Será utilizado o SGBD MySQL 5.5, Delphi XE e os componentes da paleta DBExpress para acessar os dados, mas nada impede de serem utilizados outros SGBDs, versões anteriores ou posteriores do Delphi ou engines de acesso (ZEOS, ADO etc.), pois essa propriedade ProviderFlags está presente em todas as engines mencionadas.

Para esse artigo vamos construir o seguinte cenário: criar um banco de dados “devmedia” contendo 3 tabelas (“cliente”, “vendedor”, “pedido”).

Tabela para cadastro de clientes

Na tabela de “cliente” vamos criar campos básicos, apenas para ilustração das informações do cliente. Segue o script abaixo:

Listagem 1: Script para criar a tabela de “cliente”


CREATE TABLE `cliente` (
  `id` smallint(11) NOT NULL AUTO_INCREMENT,
  `nome` varchar(60) DEFAULT NULL,
  `fone` char(12) DEFAULT NULL,
  `celular` char(12) DEFAULT NULL,
  `email` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Clientes previamente cadastrados

Figura 1: Clientes previamente cadastrados

Tabela para cadastro de vendedores

Na tabela de “vendedor” vamos criar apenas dois campos, sendo que o principal é nome do vendedor, segue script abaixo:

Listagem 2: Script para criar a tabela de “vendedor”


CREATE TABLE `vendedor` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `nome` varchar(40) DEFAULT NULL,
  `comissao` decimal(9,2) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
Vendedores previamente cadastrados

Figura 2: Vendedores previamente cadastrados

Tabela para cadastro de pedidos

Na tabela de “pedido” vamos criar alguns campos básicos, somente para ilustração, o detalhe nessa tabela são os campos que fazem relacionamento com as tabelas de “cliente” (campo id_cliente) e “vendedor” (campo id_vendedor). Notem que não vamos gravar dados do cliente como: nome, email, telefone e nem o nome do vendedor, pois essas informações serão capturadas com a instrução SQL. Segue o script abaixo:

Listagem 3: Script para criar a tabela de “pedido”


CREATE TABLE `pedido` (
  `id` smallint(11) NOT NULL AUTO_INCREMENT,
  `id_cliente` int(11) DEFAULT NULL,
  `valor_total` decimal(9,2) DEFAULT NULL,
  `data_venda` date DEFAULT NULL,
  `id_vendedor` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 

Observação: Não foram criadas chaves estrangeiras (FK) na tabela “pedido”, o objetivo do artigo não é explanar integridade dos dados, mas sim facilidades que tais configurações podem trazer. Não foi criada uma tabela de “itens_pedido”, os valores na tabela de “pedido” foram cadastrados aleatoriamente.

Pedidos previamente cadastrados

Figura 3: Pedidos previamente cadastrados

Finalizada a fase de criação da base de dados, vamos abrir o Delphi e criar um novo projeto. Nesse projeto será necessário apenas um formulário, onde será possível visualizar, editar e excluir registros no DBGrid. Para melhor ilustrar o desempenho das configurações na propriedade ProviderFlags, vamos utilizar um componente (TSQLMonitor) da paleta DBExpress, muito interessante para o monitoramento das instruções SQL que são enviadas para o banco de dados.

Vamos inserir no form os seguintes componentes:

ComponentesConfigurações das Propriedades
1 -TSQLConnectionName = Conexao
Driver = MySQL
Database = devmedia
HostName = localhost
Password = 011224 //Exemplo
ServerCharset = utf8
UserName = root
1 - TSQLQueryName = “qryPedido”
SQL = Será descrita abaixo.
SQLConnection = Conexao
1 - TDataSetProviderName = dspPedido
DataSet = qryPedido
UpdateMode = upWhereKeyOnly
1 - TClientDataSetName = cdsPedido
ProviderName = dspPedido
1 - TDataSourceName = dtsPedido
DataSet = cdsPedido
1 - TSQLMonitorName = SQLMonitor
SQLConnection = Conexao
Active = true
1 - TDBGridName = grdPedidos
DataSource = dtsPedido
Align = alTop
1 - TMemoName = mmoSQL
ScrollBars = ssVertical
Align = alBottom
2 - TBitBtn1 – Name = btnExcluir
Caption = “Excluir”
Kind = bkCancel
1 – Name = btnGravar
Caption = “Gravar”
Kind = bkOK

Tabela 1: Lista de componentes e suas respectivas configurações

Layout do formulário

Figura 4: Layout do formulário

Na tabela acima faltou informar a propriedade SQL do componente TSQLQuery, nessa propriedade temos que digitar nossa instrução SQL para trazer os dados e posteriormente, através do componente ClientDataSet, popular o DBGrid. Essa instrução SQL envolverá dados das três tabelas que criamos acima, mas o grande segredo dessa consulta é que poderemos alterar dados do pedido mesmo trazendo dados de outras tabelas, segue abaixo instrução SQL:

Listagem 4: Instrução SQL para carregar DBGrid


SELECT p.id, c.nome AS cliente, c.email, p.valor_total, p.data_venda, v.nome as vendedor 
FROM pedido p INNER JOIN cliente c  ON p.id_cliente = c.id
INNER JOIN vendedor v ON p.id_vendedor = v.id

Observem que essa instrução retornará além dos dados da tabela “pedido”, o nome e email do cliente que estão gravados somente na tabela “cliente” e o nome do vendedor que está gravado na tabela “vendedor”, tudo isso é possível através do uso dos campos de relacionamento (id_cliente e id_vendedor) entre as tabelas nas cláusulas do INNER JOIN.

Agora vamos a tão aguardada configuração da propriedade ProviderFlags dos campos. Após inserida a instrução SQL na devida propriedade do componente TSQLQuery, vamos alterar a propriedade Active para true. Com um duplo click ou clicando em cima do componente com o botão direito do mouse e selecionando a opção “Fields Editor...”, será aberta uma janela.

Pop-up com a opção Fields Editor

Figura 5: Pop-up com a opção Fields Editor

Após selecionada a opção Fields Editor será aberta uma janela vazia, clicar novamente com o botão direito do mouse dentro dessa janela e selecionar a opção “Add all fields”. Serão adicionados todos os campos da instrução SQL.

Adicionando campos ao Fields Editor

Figura 6: Adicionando campos ao Fields Editor

Clicando em cada campo serão exibidas no Object Inspector todas as propriedades do campo, entre elas existe a ProviderFlags, onde temos as seguintes opções:

  • pfInUpdate
  • pfInWhere
  • pfInKey
  • pfInHidden
Fields Editor com todos os campos da instrução SQL

Figura 7: Fields Editor com todos os campos da instrução SQL

Object Inspector com as opções de Flags

Figura 8: Object Inspector com as opções de Flags

FlagDescrição
pfInUpdateIndica se o campo será atualizado
pfInWhereIndica se o campo fara parte da cláusula Where
pfInKeyIndica se o campo é parte da Chave Primária
pfInHiddenIndica se o campo será oculto para os Clientes

Tabela 2: Lista de flags e descrição das configurações

Agora vamos iniciar as configurações individuais para cada campo que está no Fields Editor.

CampoFlagValor
idpfInUpdateFalse
pfInWhereTrue
pfInKeyTrue
pfInHiddenFalse
clientepfInUpdateFalse
pfInWhereFalse
pfInKeyFalse
pfInHiddenFalse
emailpfInUpdateFalse
pfInWhereFalse
pfInKeyFalse
pfInHiddenFalse
valor_totalpfInUpdateTrue
pfInWhereFalse
pfInKeyFalse
pfInHiddenFalse
data_vendapfInUpdateTrue
pfInWhereFalse
pfInKeyFalse
pfInHiddenFalse
vendedorpfInUpdateFalse
pfInWhereFalse
pfInKeyFalse
pfInHiddenFalse

Tabela 3: Configurações individuais de cada campo

O objetivo desse artigo é demonstrar como atualizar dados de uma tabela envolvida em uma consulta com outras tabelas, usando as configurações do ProviderFlags. Nesse caso vamos alterar e excluir dados da tabela “pedido”, sem alterar nenhuma informação das tabelas “cliente” e “vendedor” apesar das duas estarem envolvidas na instrução SQL de consulta.

Campo “id” é Chave Primária da tabela “pedido” então informamos que ele é o campo chave primária e que participará da cláusula Where das instruções.

Como os campos “cliente” e “email” não fazem parte da tabela “pedido”, deixamos todas as flags como false, isso indica que esses campos não fazem parte da Chave Primária, não serão atualizados e não participarão da cláusula Where. Aí está o segredo para trabalharmos com várias tabelas e manipularmos dados de apenas uma única tabela, pois essas configurações isolam esses dois campos do restante das instruções. Poderemos observar melhor com as informações do SQLMonitor.

Campos “valor_total” e “data_venda” pertencem à tabela “pedido”, então nesse caso poderão ser atualizados com a instrução Update. Para isso deixamos como True apenas a flag pfInUpdate, pois não fazem parte da Chave Primária e não existe necessidade dos mesmos fazerem parte da cláusula Where.

Campo “vendedor” não faz parte da tabela “pedido” somente da tabela “vendedor”, então todas as suas flags serão alteradas para False, pois ele não é parte de Chave Primária, não será atualizado e não participará das cláusulas Where.

Agora vamos codificar os dois botões, serão códigos bem simples, pois vamos alterar e excluir os dados direto no DBGrid.

O botão “Gravar” verifica se cdsPedido está em estado de Edição ou Inserção, caso verdadeiro, grava e atualiza as informações no banco de dados.

Listagem 5: Código do evento OnClick do botão “btnGravar”


if cdsPedido.State in [dsEdit, dsInsert] then
begin
cdsPedido.Post;
cdsPedido.ApplyUpdates(0);
end; 

O botão “Excluir” verifica se cdsPedido está em estado de Edição ou Inserção, caso verdadeiro, exclui e atualiza informações no banco de dados.

Listagem 6: Código do evento OnClick do botão “btnExcluir”


if cdsPedido.State in [dsBrowse] then
begin
cdsPedido.Delete;
cdsPedido.ApplyUpdates(0);
end; 

Para finalizar, vamos exibir as instruções SQL que estão sendo enviadas para o banco de dados utilizando o componente TSQLMonitor.

No evento OnLogTrace do componente TSQLMonitor vamos definir que todas as instruções que forem enviadas para banco de dados serão exibidas no componente TMemo, desse modo poderemos observar toda a “mágica” das configurações do ProvideFlags.

Listagem 7: Código do evento OnLogTrace do componente TSQLMonitor


mmoSQL.Lines.Add(TraceInfo.Message); 
Informações transmitidas ao banco de dados

Figura 9: Informações transmitidas ao banco de dados

Pronto, agora é só executar aplicação, como já foram cadastradas informações para testes segue abaixo demonstração.

Observem que ao iniciar a aplicação e carregar o DBGrid já foram transmitidas informações de consulta para o banco de dados.

Vamos alterar o valor_total da venda “10” para 2000,00 e clicar no botão “Gravar”, observem a instrução SQL usando na cláusula Where o valor do campo “id”, somente a tabela “pedido” será modificada.

Instrução SQL para Update do registro

Figura 10: Instrução SQL para Update do registro

Agora vamos selecionar a venda “7” e clicar no botão “Excluir”, será excluído o registro da tabela “pedido” usando o valor do campo id na cláusula Where.

Instrução SQL para Exclusão do registro

Figura 11: Instrução SQL para Exclusão do registro

Observem que a tabela “pedido” só possui os ids do cliente e do vendedor, os restantes das informações como nome e email estão gravadas nas respectivas tabelas. Para capturar todas essas informações em uma mesma consulta usamos JOINs, ou seja, comparações entre as tabelas. Mas existe a necessidade de alterar informações dos campos da tabela “pedido”, então foram configuradas adequadamente as flags isolando os campos que não fazem parte dessa tabela. Com essa técnica foi possível editar e excluir registros da tabela “pedido” sem alterar nenhuma informação das outras tabelas relacionadas na consulta.

Bom pessoal, nesse artigo foi demonstrado como podemos configurar a propriedade ProviderFlags para trabalhar de acordo com nossas necessidades, existem várias outras combinações possíveis. Com o auxílio do SQLMonitor foi possível observar como as instruções SQL são enviadas para o banco de dados.

Espero que tenham apreciado e até a próxima.

Caso surja alguma dúvida meu e-mail é wllfl@ig.com.br. Fiquem à vontade também para usar a seção de comentários.

Abraço a todos!