Olá, leitores! Como participo de fóruns sobre programação, tenho notado que muitos desenvolvedores possuem algumas dúvidas relacionadas ao componente Query do Delphi. Este componente, de extrema utilidade, dispõe de recursos para inserir, atualizar, excluir registros e selecionar dados de uma tabela. O foco deste artigo é apresentar os conceitos básicos e as principais funcionalidades do componente Query, bem como algumas dicas para tirar proveito deste componente.
“Query”, em inglês, significa pergunta, questão ou dúvida. Nos conceitos de programação, quando executamos algum comando no banco de dados, esperamos que ele retorne os resultados desejados. Portanto, um comando SQL pode ser comparado a uma “questão” direcionada ao banco de dados, que por sua vez, fica responsável de retornar com a resposta. O componente Query tem exatamente essa função: submeter comandos SQL ao banco de dados e obter o retorno. Não vou entrar em detalhes sobre a linguagem SQL, pressupondo que você, desenvolvedor, já tenha uma noção dos comandos para manipulação de dados.
Onde eu encontro o componente Query?
O componente Query herda as propriedades da classe TDataSet. O que eu quero dizer é que não existe apenas um tipo de componente Query, ou seja, depende de qual conjunto de componentes que você está utilizando para conectar com o banco de dados.
- Se você estiver utilizando dbExpress, o nome do componente é
TSQLQuery
; - No conjunto ADO (dbGo), o componente é o
TADOQuery
; - Caso esteja utilizando o ZeosLib, o componente em questão é o
TZQuery
; - Nos componentes IBX, o nome é
IBQuery
; - Por fim, no FireDAC o componente se chama
TFDQuery
.
Como disse anteriormente, estes componentes herdam da mesma classe, portanto, os comandos são praticamente semelhantes, salvo algumas exceções.
Configurando um componente Query
Em primeiro lugar, para configurar uma Query é preciso definir a sua conexão. Isso pode ser feito através da propriedade Connection
ou SQLConnection
do componente, disponível no Object Inspector do Delphi.
Após essa configuração, já podemos escrever a instrução SQL que será executada no banco de dados. Vale lembrar que o foco deste artigo trata a atribuição de comandos via código, e não de modo gráfico. Portanto, em breve também vou postar um pequeno tutorial de como utilizar a Query como fonte de dados e exibir os registros em uma DBGrid.
Executando um comando SELECT
Vamos começar a estudar o componente Query trazendo dados de uma tabela. Como exemplo, vou utilizar uma tabela chamada CLIENTES de um banco de dados qualquer, mas nada impede que você faça os mesmos exemplos com outra tabela. As instruções que vamos executar no banco de dados devem ser escritas na propriedade SQL da Query. Nada mais óbvio, haha. Pois bem, vamos ao nosso primeiro exemplo, lembrando que estou utilizando o nome Query1
para generalizar os componentes Query em comum. O primeiro passo é atribuir o comando SQL à Query:
1 |
Query1.SQL.Text := 'Select * from CLIENTES where Codigo = 10'; |
E, em seguida, abri-la com o comando Open
:
1 |
Query1.Open; |
Simples, não?
Ok, já que agora selecionamos o cliente nº 10 no banco de dados, podemos acessar os campos e ler os dados através do método FieldByName
:
1 2 3 |
ShowMessage('Nome....:' + Query1.FieldByName('Nome').AsString); ShowMessage('Idade...:' + Query1.FieldByName('Idade').AsString); ShowMessage('Endereço:' + Query1.FieldByName('Nome').AsString); |
Acessando resultados de campos agregados
Mas temos um problema. Vamos supor que eu queira utilizar uma função SQL para agregação de dados, como MAX, MIN, SUM, AVG ou COUNT. Por exemplo, se executarmos a SQL:
1 |
Select COUNT(*) from CLIENTES where UF = 'SP' |
Os dados serão retornados, mas a coluna não terá nenhum nome. Sendo assim, não será possível acessar essa informação pelo FieldByName
da Query. Bom, para este problema temos duas soluções. A primeira é renomear a coluna com o resultado da agregação na própria SQL:
1 2 3 |
Query1.SQL.Text := 'Select COUNT(*) as Contador from CLIENTES where UF = 'SP''; Query1.Open; ShowMessage(Query1.FieldByName('Contador').AsString); |
A segunda opção é utilizar outra propriedade da Query, chamada Fields
. Essa propriedade enumera os campos retornados em ordem crescente, permitindo que o desenvolvedor acesse os dados através da posição do campo na Query:
1 2 3 |
Query1.SQL.Text := 'Select COUNT(*) from CLIENTES where UF = 'SP''; Query1.Open; ShowMessage(Query1.Fields[0].AsString); |
Neste caso, o campo número zero é a quantidade de clientes retornada pela Query. Da mesma forma, posso acessar qualquer campo da Query através da posição que ele se encontra:
1 2 3 |
ShowMessage('Nome....: ' + Query1.Fields[0].AsString); ShowMessage('Idade...: ' + Query1.Fields[1].AsString); ShowMessage('Endereço: ' + Query1.Fields[2].AsString); |
Porém, ao se utilizar o Fields
, o desenvolvedor pode se perder em meio a tantos campos retornados. Por exemplo, se a consulta retornou 15 campos, é praticamente inviável “decorar” a posição de cada um deles. Pensando assim, eu recomendo utilizar o FieldByName
e referenciar os campos pelo próprio nome. Além de facilitar a manutenção, o código-fonte fica mais legível.
Consultando vários registros
No exemplo acima retornamos apenas um resultado, isto é, o cliente número 10. A nossa necessidade agora é trazer todos os clientes da tabela e preencher uma ListBox com o nome de cada um. É possível programar isso com a Query?
Yes! Para isso, modificaremos um pouco a nossa instrução SQL:
1 2 |
Query1.SQL.Text := 'Select * from Clientes'; Query1.Open; |
Pronto, agora selecionamos todos os registros da tabela CLIENTES. Para que eu possa preencher uma ListBox com os nomes, será necessário executar um loop (laço de repetição) nos resultados da Query.
Observe como é bem simples. A instrução abaixo move o cursor da Query para o primeiro registro:
1 |
Query1.First; |
Em seguida, escrevemos o loop:
1 |
While not Query1.Eof do |
O loop acima assume que enquanto a Query não chegar até o último registro (Eof
– End of File), ele será executado. Dessa forma, poderemos obter o nome de cada cliente e adicionar na ListBox com o código abaixo:
1 |
ListBox1.Items.Add(Query1.FieldByName('Nome').AsString); |
Por fim, porém o mais importante, temos que mover o cursor da Query para o próximo registro:
1 |
Query1.Next; |
E depois que o loop for finalizado, fechar a Query:
1 |
Query1.Close; |
O código final ficará da seguinte forma:
1 2 3 4 5 6 7 8 9 |
Query1.SQL.Text := 'Select * from Clientes'; Query1.Open; Query1.First; While not Query1.Eof do begin ListBox1.Items.Add(Query1.FieldByName('Nome').AsString); Query1.Next; end; Query1.Close; |
Aproveitando o embalo, tome nota das seguinte funções da Query:
First
– move o cursor para o primeiro registroLast
– move o cursor para o último registroPrior
– move o cursor para o registro anteriorNext
– move o cursor para o próximo registro
Manipulando dados
Até agora vimos como utilizar a Query com um comando SELECT no banco de dados. No entanto, ela pode fazer mais do que isso. Sim, podemos inserir, atualizar e excluir registros utilizando a mesma propriedade, a SQL! A única diferença é que, ao invés do comando Open
, utiliza-se o comando ExecSQL
. Vamos aplicar isso de uma forma prática:
1 2 |
Query1.SQL.Text := 'Insert into Clientes (Codigo, Nome) Values (15, ''Andre'')'; Query1.ExecSQL; |
Pronto, nosso novo registro foi incluído. Embora seja bem simples, não podemos descartar a possibilidade de ocorrer algum erro na execução da instrução SQL. Caso algum dado esteja inconsistente, a instrução não será realizada com sucesso. Para prevenir essa possibilidade, nada melhor do que envolver as instruções da Query dentro de um tratamento de exceção:
1 2 3 4 5 6 7 |
Query1.SQL.Text := 'Insert into Clientes (Codigo, Nome) Values (15, ''Andre'')'; try Query1.ExecSQL; except On E:Exception do ShowMessage('Ocorreu um erro ao incluir o cliente: ' + E.Message); end; |
Aliás, o tratamento de exceções nunca deixou de ser uma ótima prática de programação. Antes de ir embora, quero apenas ressaltar uma observação que às vezes confunde alguns desenvolvedores:
- Para comandos SELECT, utilize o comando
Open
da Query. - Para comandos INSERT, UPDATE e DELETE, utilize o comando
ExecSQL
.
Fico por aqui, leitores!
Aguarde pelo próximo artigo sobre Query, onde comentarei sobre a passagem de parâmetros!
Abraços!
Otimo post, para aprimoração do aprendizado.
[]s
otima explicação, cmo sempre em suas explicações nos foruns, como diz um refrão de uma música ah se todos fossem igual a você que maravilha viver rssss
Sou desenvolvedor java e por necessidade de mercado de onde vivo tenho que me conceitualizar com o delphi , gostaria de saber se com o IBQuery eu consigo preparar consultas ? ou somente o UpdateSql conseguirei prepara, grato !
Olá Vinícius, tudo certo?
Vinícius, o set de componentes IBX é bastante poderoso pra trabalhar com SQL. Para realizar manutenções no banco de dados (INSERT, UPDATE, DELETE) você pode utilizar a IBQuery, enquanto pra obter um conjunto de dados (SELECT), pode-se utilizar o IBDataset ou IBTable.
Boa sorte no seu trabalho!
Olá, estou indo para uma empresa que exige o conhecimento na parte de Query, o artigo está ótimo e servirá muito para eu aprender! Parabéns, Obrigado!
Boa tarde André. Li seu artigo sobre Query e achei muito interessante. Deixe-me perguntar: Ja faz dias que estou brigando aqui com uma QUERY/DELPHI e não saio do lugar. Veja se pode me ajudar:
Tenho uma grid vinculada a uma QUERY. Tenho também varios CHECKBOXLIT, onde posso ativar varios ao mesmo tempo. Por exemplo: Tenho um CHECKLISTBOX onde o usuario pode escolher varias tipos de despesas e outro com varios fornecedores diferentes. O que eu gostaria de fazer é mostrar nessa grid o resultado do que o usuario escolher, ou seja:
se ele escolher duas, tres ou quatro despesesas diferentes, deverá ser mostrada na grid..e se na sequencia ele optar por um, dois ou mais fornecedores do checklistobox FORNECEDORES, serão mostrados.
Resuminto..Tem como fazer consulta da consulta usando uma query?
desde já agradeço a atenção.
Obrigado
Robson
Boa tarde, Robson! Em primeiro lugar, obrigado pelo comentário. Pra ficar mais fácil, vou entrar em contato com você por e-mail para que possamos conversar melhor, ok? Abraço!
Olá André, Queria saber como faço para colocar um select dentro de um loop? por aqui da erro no “open”.
Outra coisa também, como esvaziar Query para que no próximo laço de repetição o parâmetro seja criado novamente?
Desde já obrigado.
Olá, Tucker! Para facilitar, vou entrar em contato com você por e-mail. Assim podemos discutir melhor sobre a sua dúvida, ok? Obrigado pelo comentário!
EXCELENTE POST, COM ESTE GANHEI O DIA, UM ABRAÇO
VALEU MESMO.
Olá, Gilberth! Fico contente que o artigo tenha lhe ajudado. Obrigado por deixar o comentário!
Ola André, muito bom seu post esta sendo de grande aprendizado pra mim. Já trocamos alguns e-mail, meu sistema esta caminhando, você esta sendo de grande ajuda, grande abraço.
Olá, Getulio, que bom que o sistema está dando certo! Obrigado pelo comentário!
Olá André, muito bom seu post, excelente explicação, ajudou bastante na minha luta com o query hehehehehe, mas eu ainda tenho uma dúvida, talvez você possa me ajudar. O problema é o seguinte, eu tenho uma query com alguns campos, e esses são passados para uma Virtual table, até ai beleza, o problema que agora eu preciso fazer um join em outra tabela, e eu preciso que esse campo apareça na query, porém quando eu faço o join e adiciono o campo quando a aplicação inicia ele me retorna um erro dizendo que o campo não existe, se eu retiro o campo do componente a virtual table fica com o campo em questão sem valor … se você puder me dar um dica de como resolvo isso, ficaria muito grato.
Olá, Wellington. Pra ficar mais fácil, vou entrar em contato com você por e-mail, ok? Abraço!
Olá meu caro! Muito bom o artigo! Estou começando agora na programação e me ajudou bastante!
Olá, Henrique! Fico feliz que o artigo tenha lhe ajudado! Abraço!
Boa tarde André, parabéns pela postagem. Tenho uma dúvida: para linkar os campos de um formulário com os fields é melhor fazer a atribuição usando o fieldByName ou no próprio componente na propriedade DataField? Já ouvi comentários sobre o “poder” do FieldByName…
Atenciosamente…
Olá, Diego! Ótima pergunta!
A questão da utilização de componentes DBWare (ligados pela propriedade DataField) e componentes padrão, muitas vezes, é uma preferência de cada desenvolvedor. Alguns desenvolvedores preferem utilizar componentes DBWare por estes já trazerem as regras de preenchimento da tabela, como o tipo de dado e o tamanho. Outros desenvolvedores optam pelos componentes padrão e utilizam o FieldByName para preencher os dados, resultando em um número ligeiramente maior de linhas de código, porém, concedendo mais “flexibilidade” para o desenvolvedor. Ao utilizar componentes padrão, o desenvolvedor pode abrir uma transação, executar um Append no DataSet, atribuir todos os valores (como o FieldByName), executar um Post e comitar a transação, tudo em um mesmo método. Isso pode ser mais adequado ao trabalhar com padrões de arquitetura ou caso o desenvolvedor queira separar a persistência dos dados em uma classe exclusiva.
De qualquer forma, volto a dizer: cada desenvolvedor tem suas particularidades. O importante é a produtividade!
Abraço!
Boa Noite André, parabéns pela postagem. Vejo que e bastante atencioso como pessoal que posta comentário s e perguntas, parabéns pois poucos tem essa paciência. Bom gostaria também de pedir a você uma ajuda eu fiquei muito tempo sem desenvolver, fiquei parado 15 anos, agora vejo a nescidade de voltar a programar, lembro que eu fazia todo o tipo de acesso ao banco via Query so que não me lembro mais como se faz isso como se usa uma Query1 nos botoes incluir, editar gravar? pode me mandar um pequeno exemplo? uso delphi XE e firebird. Desde já agradeço. Deus te abencoe.
Olá, Malaquias! Obrigado pelo feedback!
Na página de “Exemplos” aqui do blog há alguns projetos que talvez possam lhe ajudar (como o 2º, 4º e º5):
https://www.andrecelestino.com/exemplos/
Abraço!
Ótima postagem, muito obrigado pelas informações!!! Sou desenvolvedor PHP e estou fazendo algo em Delphi no momento e me ajudou bastante este artigo.
Agradeço. Abraços!!
Olá, Tiago! Opa, que bom que artigo lhe ajudou!
Grande abraço!
podrias mandarme un ejemplo de como insertar/modificar/eliminar
usuarios de una tabla utilizando TQuery IBExpert porfaaaaa lo necesito no le entiendo bien a delphi mi lenguaje preferido es java soy total mente nuevo en delphi 🙁
Hello, DAMR!
Unfortunately, I don’t speak Spanish (although I really would like to).
Perhaps we can use English to communicate, in case you’re familiar with this language.
Anyways, thank you for visiting and commenting on the blog!
Parabéns pelo seu post, André! Suas explicações são bastante claras e objetivas. Se for possível, gostaria que você me ajudasse na identificação de um componente TQuery que implemente a função IIF, que foi originalmente implementado pela Microsoft desde o tempo do FoxPro.
Desde já agradeço a cooperação.
Um grande abraço e Suce$$o!
Vandinei
Olá, Vandinei! Obrigado pelo comentário e pelo feedback!
Valdinei, infelizmente a função IIF não está disponível no Delphi, mas há uma função semelhante, chamada IfThen. Confira a documentação dessa função nos links abaixo:
http://docwiki.embarcadero.com/Libraries/XE6/en/System.StrUtils.IfThen
http://delphi.about.com/library/rtl/blrtlIfThen.htm
Se você deseja utilizar essa função em um componente TQuery, sugiro que crie um componente personalizado, de forma que você possa adicionar suas próprias funções.
Abraço!
Então amigo programador, passo o comando sql para dentro do ADOQUERY, porém o comando tem um erro de “Truncate String”, o problema é que na linha EXECSQL, não gera uma exceção no Try Except, ou seja, não aparece o erro na tela e o usuário pensa q gravou, mas na verdade não gravou… vc sabe como tratar isso ? desde já agradeço…
Olá, Tiago, tudo bem?
Rapaz, para ser sincero, não sabia que erros no ExecSQL da ADOQuery não eram capturados no fluxo do except. É bom saber!
Tiago, a função ExecSQL fornece um retorno que é a quantidade de linhas que foram afetadas pela instrução SQL. Portanto, podemos assumir que, caso a quantidade de linhas afetadas seja igual a 0 (zero), significa que houve um erro na execução do comando:
if ADOQuery1.ExecSQL = 0 then
ShowMessage('Erro na instrução SQL.');
Talvez a sugestão acima possa lhe ajudar!
Abraço!
André, parabéns e muito obrigado por me elucidar com estes dois artigos sobre Query.
Sou um “rastejante” no Delphi gostaria de pedir uma ajuda no que se refere ao usar “Query.Pior” e o “Query.Last”: quando execute uma destas rotinas o meu sistema apresenta um erro: “Operation not allowed on a unidirectional dataset”.
Em compensação os comandos “Query.First” e “Query.Next” funcionam. Saberia me dizer o que pode ser?
Olá, Diogo, tudo bem?
Em primeiro lugar, agradeço pelo feedback sobre os artigos!
Diogo, conforme a documentação da Embarcadero, a Query é um tipo de DataSet unidirecional, ou seja, não armazena múltiplos registros em memória, impossibilitando a navegação com Prior e Last. Para navegar normalmente entre os registros de uma Query, é necessário conectá-la a um TDataSetProvider e, em seguida, conectar este TDataSetProvider em um TClientDataSet. A partir de então, basta utilizar o ClientDataSet para realizar as navegações necessárias.
Abraço!
Oi, André! Primeiro quero te dar os parabéns pelos artigos. São realmente de grande importância para nós leigos. Gostaria de pedir ajuda com um DBNavigator de um programinha simples que estou fazendo no Lazarus. Consigo conectar, aparece os registros, mas quando chega no applyUpdate, dá um erro:”EDataBaseError” no meu Data Module. Já tentei de tudo! Será que dá pra dar uma força???
Olá, Jarickson, tudo certo?
Não tenho experiência com Lazarus, mas vou tentar ajudá-lo por e-mail, ok?
Abraço!
Bom dia. Se possível, poderia me dar uma ajuda? Tenho a seguinte consulta:
E no campo da tabela: TIPOMARCACAO_PON pode ser NORMAL ou FALTA. Gostaria de aproveitar esta consulta e já contar o total de faltas de um funcionário. Tentei de várias formas e não consegui, será que você poderia dar uma ajuda?
Tentei criar uma outra consulta para contar as faltas, mas não deu certo, dá ACCESS VIOLATION, creio que por causa do ponto já estar sendo selecionado anteriormente.
Desde já obrigado pela atenção.
Olá, Adilson, tudo certo?
Você tem 2 opções:
1) Como a contagem de registros é uma função agregada, é necessário utilizar outra Query para essa finalidade, utilizado o comando COUNT.
2) Após abrir a FDQueryPonto, conte a quantidade de registros usando o comando RecordCount:
Abraço!
Olá bom dia
Sou iniciante no delphi, estou fazendo sistema basico de cadastro e consulta de ideias implantadas na empresa
‘to travado’ na tela de relatórios tentei de varias formas e não consegui, segue exemplo.
Uma tabela em acess com nome de IDEIAS, nela contem os campos DATA_IMPLANTACAO, STATUS e USINA,
a ideia era definir o intervalo do DATA_IMPLANTACAO por dois DateTimePicker, e o status e usina definidos por duas Edit’s, ai vem o grande problema, são 3 critérios de busca, queria que; caso um não fosse definido pelo usuário ou não encontrasse no banco, retornasse o resultado dos 2 demais critérios,
desde já agradeço a atenção.
Olá, Elielson, tudo bem?
Acredito que a sua necessidade está relacionada com a forma de trabalhar com parâmetros na Query.
Acesse este link para ler um artigo aqui mesmo do blog sobre esse assunto.
Com estes parâmetros, você pode definir a consulta SQL na aplicação conforme as entradas válidas do usuário, ou seja, pelas datas de implantação ou pelo status e usina. Caso as datas estejam preenchidas, executa uma consulta utilizando a coluna DATA_IMPLANTACAO como critério de busca. Por outro lado, caso o status e usina estejam preenchidos, execute a consulta considerando os campos STATUS e USINA.
Abraço!
Bom dia Colegas
Consegui acionando o parâmetro and na consulta.
Muito bom artigo André, me ajudou com algumas duvidas. Tenho prova de delphi hoje hahaha Abraço
Obrigado, Thiago!
Boa sorte na prova! 🙂
Abraço!
Olá Bom dia.
Tenho um sistema de terceiros rodando em um cliente, e o cliente usa grade. só que a impressão de etiquetas em grande não esta funcionando nos sistema, dai tenho que rodar um script SQL no banco para gerar as etiquetas e dai o cliente imprimir. Gostaria de fazer uma aplicação em Delphi onde o cliente entraria com o numero da NF-e e executaria o script sql gerando as etiquetas.
Só que não consegui agregar o script sql ao delphi e gostaria da sua ajuda, pois sou iniciante…
Obrigado
Olá, Adriano.
Para que eu possa ajudá-lo, preciso conhecer um pouco mais deste sistemas, principalmente o SGBD utilizado.
Entrarei em contato.
Olá, André.
Sou um usuário apaixonado pelo Delphi e iniciante com ferramentas de banco de dados. Gostaria de lhe parabenizar pela sua didática simples e muito rica na introdução ao uso de Query. Eu tinha muita dificuldade em entender os comandos em SQL e agora com o uso no Delphi ficou mais clara e fiquei entusiasmado em empregar estes recursos em minha aplicações que cada vez mais exigem o uso de ferramentas de banco de dados. Parabéns pela sua explicação e vou lhe solicitar outras dicas mais a frente no desenvolvimento de minhas aplicações.
Um abraço.
Júlio Bitencourt
Olá, Júlio! Peço desculpas pela demora.
Gostei bastante do seu comentário! Fico muito grato ao saber que os artigos estão lhe ajudando e agradeço também pelo feedback!
Aos poucos, você observará que é bem fácil trabalhar com bancos de dados no Delphi. Os componentes para essa finalidade já possuem uma inteligência para criar queries e manipular registros.
Coloco-me à disposição para ajudá-lo no que for necessário.
Grande abraço, Júlio!
Valeu, simples e bem explicado. Ótimo para tirar dúvidas.
Obrigado, Guaracy!
Em breve retomarei as atividades do blog para publicar mais conteúdo!
Abraço!
O Componente TSqlQuery é unidirecional, portanto não aceita que você navegue nos registros.
Exato, Carlos. Só é possível navegar em uma direção.
Olá, seus artigos e dicas me ajudam bastante, pois sou autodidata em Delphi, Firebird, dbexpress para hobby, mas com muitas dúvidas. Por isso, preciso da sua ajuda.
Boa noite, Henrique, tudo bem?
Parabéns pelo comprometimento com o seu próprio crescimento profissional.
Claro que posso ajudá-lo. Envie suas dúvidas para [email protected].
Abraço!
Ótimo artigo, me ajudou muito aqui nas minhas aplicações, era exatamente essa utilização que estava procurando.
Um belo trabalho!
Estou na correria aqui para fazer um teste de Estágio, e cara… necessitando muito de uns artigos bons como esse.
Vou procurar aqui, mas já de antemão, teria algo relacionado a DBExpress em Multicamadas? Agradeço desde já!
Olá, Fernando, boa noite!
Muito obrigado pelo feedback sobre o artigo! 🙂
No momento infelizmente não tenho nada publicado sobre multicamadas com DBX, mas está na minha pauta.
De qualquer forma, caso precise de alguma ajuda, envie um e-mail para [email protected].
Abraço!
Olá, boa tarde, André!
Obrigado pelo tutorial. Embora eu seja iniciante em Delphi, com sua forma de explicar fica muito fácil de aprender!
Abraço!
Obrigado pelo comentário, Roberto.
Esse é justamente o meu objetivo: descomplicar a programação com Delphi! 🙂
Abraço!
Boa tarde André, gostaria que me tirasse uma duvida. A utilização do método close antes do adicionar um novo SQL na query e após obter o resultado da consulta faz alguma diferença para o sistema? Já vi diversos casos em que programadores escrevem o código desta mesma forma e outros que utilizam apenas para componentes DBWare, qual sua opinião sobre isso?
Abraço!
Olá, Adailson, tudo jóia?
Não posso afirmar com certeza se faz alguma diferença, já que o componente Query de cada tecnologia de conexão possui uma implementação diferente (ADO, DBX, FireDAC…). Mesmo assim, sempre foi considerada uma boa prática fechar a Query antes de atribuir uma nova instrução SQL e/ou receber novos dados. Em algumas situações que já presenciei, o fato de você tentar abrir uma Query quando ela já está aberta resulta no erro “Cannot perform this operation on an open dataset”.
Eu sugiro que você sempre procure fechá-la com o
Close
.Abraço!
Boa noite
É possível usar For-In para percorrer uma Query e alimentar o Combobox com o campo Nome_Pessoa?
Exemplo, isto é possível?
Olá, Judeir, bom dia.
Não é possível usar o For-In dessa forma, pois a Query armazena os dados de forma tabular e é necessário navegar entre os registros para buscar o conteúdo do mesmo campo.
Se a intenção é deixar o código mais limpo, sugiro utilizar variáveis do tipo
TField
dentro do loop:Outra solução é criar um Class Helper para a Query e declarar um método que busque o valor do Field e já navegue para o próximo registro automaticamente.
Muito obrigado pelo esclarecimento e a dica.
é possivel uma dbgrid atualizar automaticamente assim que um novo registo é adicionado a uma tabela por outro user?
Boa noite, Zink.
Sim, é possível, no entanto, não é algo trivial. Para que você atualize a Grid em outro PC, é necessário realizar uma nova consulta no banco de dados.
Uma das formas é trabalhar com o componente TTimer, configurando-o para executar a cada N segundos para trazer novos registros do banco de dados. Eu, particularmente, não gosto dessa opção, pois pode causar “flickers” (tela piscando) cada vez que o Timer for executado, mesmo quando não houver novos registros.
Outra forma, mais sofisticada, é trabalhar com eventos do banco de dados. Nesse contexto, o próprio banco de dados pode “avisar” a aplicação de que houve uma mudança em uma tabela. O FireDAC fornece um componente chamado TFDEventAlerter exclusivo para trabalhar com essa opção. Porém, vale ressaltar que é necessário configurar o banco de dados para emitir esses alertas. Isso é feito de formas diferentes de acordo com o banco de dados utilizado.
Zink, independentemente da forma que você utilizar, tome cuidado com a usabilidade. Imagine, por exemplo, que o usuário está incluindo um novo registro e a Grid (DataSet) é atualizada. Neste caso, o novo registro será automaticamente cancelado, já que o DataSet receberá um novo pacote de dados.
Talvez, uma sugestão para minimizar esse risco é apresentar uma notificação de que há novos registros na tabela, questionando o usuário se ele gostaria de atualizar a Grid.
Abraço!
Eu uso adoquery com base dados access ligaçao ODBC.
Andei estudando e vi que existe o cursor location para server surge erro de bookmarks!!