[Delphi] Trabalhando com parâmetros na Query

[Delphi] Trabalhando com parâmetros na QueryNo último artigo sobre Query no Delphi, eu prometi que publicaria um novo artigo abordando a passagem de parâmetros utilizando Query, não é? Bom, e como promessa é dívida, o melhor é pagar antes que me cobrem, haha.
Pessoal, esse artigo trata da criação e preenchimento de parâmetros em uma SQL de forma dinâmica, evitando fixar valores em tempo de projeto. Confira!

 

A passagem de parâmetros em uma Query é bastante útil quando é necessário atribuir valores previamente desconhecidos em um comando SQL. Em outras palavras, ao invés de criar uma SQL com valores fixos, realizamos um preenchimento dinâmico desses valores em tempo de execução do aplicativo.
Para início de nossos exemplos, considere a seguinte SQL:

SELECT * FROM CLIENTES WHERE Nome = 'Andre Celestino'

 

É um comando de seleção simples, apenas para obter os dados do cliente que possua o nome “Andre Celestino”. Observe que essa SQL pode ser atribuída normalmente a uma Query da seguinte forma:

Query1.SQL.Clear;
Query1.SQL.Add('Select * from CLIENTES where Nome = ''Andre Celestino''');
Query1.Open;

 

Ao abrir a Query, os dados do cliente “Andre Celestino” serão retornados para a aplicação, ok? No entanto, a nossa Query SEMPRE irá trazer esse único registro, já que a aplicação foi compilada com o valor fixo na SQL e não há como modificá-lo. Então temos um problema: e se o usuário quiser visualizar os dados de outro cliente?

Já sei! Basta trocar o nome no código-fonte, compilar e gerar outro executável, não é?
Não, nem pense nisso! A solução é configurar a Query para receber o valor que o usuário digitar. Considere que adicionamos um campo na tela chamado edtNome do tipo TEdit, para que o usuário possa digitar o nome do cliente no qual deseja visualizar os dados. Ao invés de manter o valor fixo, vamos modificar o código para receber o valor do campo de texto:

Query1.SQL.Clear;
Query1.SQL.Add('Select * from CLIENTES where Nome = ''' + edtNome.Text + '''');
Query1.Open;

 

Caramba, quantas aspas! É necessário tudo isso?
Sim. O nome do cliente é uma string (tipo texto), e precisa ser envolvido em aspas para que o banco de dados consiga interpretar o valor. Agora, imagine que surja a necessidade de filtrar os dados por mais dois campos do tipo texto: “Endereço” e “Cidade”. Bom, tenho certeza que você pensou na quantidade de aspas, certo? Pois é, isso realmente pode dificultar a escrita do código, além de deixar o código-fonte um tanto quanto confuso.

Eis que lhes apresento uma forma bem mais fácil de preencher uma SQL dinamicamente: através de Parâmetros.

Aaaah, até que enfim! Mas como funciona?

Simples, vamos alterar o código mais uma vez:

Query1.SQL.Clear;
Query1.SQL.Add('Select * from CLIENTES where Nome = :pNome');
Query1.ParamByName('pNome').AsString := edtNome.Text;
Query1.Open;

 

Nossa, não entendi nada!
Ok, vamos lá. Para criar um parâmetro dentro de uma Query, basta escrever o nome seguido de dois pontos (:), sem espaços conforme o exemplo acima, onde o nome do parâmetro criado é pNome. Isso significa que essa “parte” da SQL será substituída por algum valor em tempo de execução. Em seguida, após declarar o parâmetro, é necessário preenchê-lo utilizando o método ParamByName, que, neste caso, é o conteúdo digitado no campo edtNome.
Pronto! Ao rodar a aplicação, a Query irá retornar os dados do cliente cujo nome foi digitado no componente edtNome!

Só temos mais um probleminha: o registro será encontrado somente se o usuário digitar o nome completo do cliente. Isso é bem inviável, não? Para resolvermos isso, basta realizar uma busca parcial do registro, utilizando a cláusula LIKE na SQL e adicionando o símbolo de porcentagem ao nome:

Query1.SQL.Clear;
Query1.SQL.Add('Select * from CLIENTES where Nome like :pNome');
Query1.ParamByName('pNome').AsString := edtNome.Text + '%';
Query1.Open;

 

O símbolo de porcentagem, a grosso modo, permite que o banco de dados selecione todos os registros que contenham parcialmente o nome digitado pelo usuário. Sendo assim, se o usuário digitar somente “Sub”, o cliente “Andre Celestino” será encontrado. É como se você dissesse ao banco de dados: “Eu vou digitar só o começo do nome e você se vira pra encontrar os registros parecidos, haha!”.

Repare que eu utilizei o comando AsString para atribuir o valor. Este comando indica que o conteúdo que será atribuído ao parâmetro é do tipo string, ou seja, um texto. Se estivéssemos realizando uma busca pelo código do cliente (considerando que o código é do tipo inteiro), então trocaríamos o comando para AsInteger:

Query1.SQL.Clear;
Query1.SQL.Add('Select * from CLIENTES where Codigo = :pCodigo');
Query1.ParamByName('pCodigo').AsInteger := StrToInt(edtCodigo.Text);
Query1.Open;

 

Há também outras opções para atribuição de valores, como datas (AsDateTime) e valores decimais (AsFloat).
Da mesma forma que criamos parâmetros em uma instrução SELECT, eles também podem ser criados em instruções INSERT, UPDATE ou DELETE. Para exemplificar, confira o exemplo de uma inserção utilizando parâmetros:

Query1.SQL.Clear;
Query1.SQL.Add('Insert into CLIENTES');
Query1.SQL.Add('(Codigo, Nome, DataNascimento)');
Query1.SQL.Add('values (:pCodigo, :pNome, :pDataNascimento)');
 
Query1.ParamByName('pCodigo').AsInteger := StrToInt(edtCodigo.Text);
Query1.ParamByName('pNome').AsString := edtNome.Text;
Query1.ParamByName('pDataNascimento').AsDateTime := StrToDate(edtData.Text);
 
Query1.ExecSQL;

 

Simples, não?
Só pra complementar, veja que utilizei o comando Add para concatenar a instrução SQL em linhas, principalmente para evitar a necessidade de utilizar o operador “+”.

Pessoal, espero que esse artigo tenha sido útil! Os exemplos contidos nesse artigo podem ser baixados neste link, desenvolvidos em Delphi 7. Para que você possa abri-los, é necessário ter o Firebird instalado no computador, ok?
Se você baixar o exemplo, observe que utilizei um TClientDataSet para manter os registros em memória. Em um futuro não tão distante (rsrs), também publicarei um artigo sobre utilização da Query como fonte de dados.

 

Grande abraço e até mais!


 

Compartilhe!
Share on FacebookTweet about this on TwitterShare on LinkedInShare on Google+Pin on PinterestEmail this to someone

81 comentários

  1. Muito bom em batera, aproveitando a deixa, em um proximo artigo seu sobre query, fale sobre query em tempo de execução, ajuda muito, forte abraço.

  2. CARO ANDRE, TRABALHO COM DELPHI 6 COM INTERBASE. PRECISO SELECIONAR TODOS OS REGISTROS DA TABELA, MENOS OS REGISTROS QUE TENHAM O CODIGO = ‘TDE’. OS OUTROS CODIGOS PODEM APARECER. COMO EU FAÇO? TENTEI CODIGO ‘TDE’ E NÃO CONSEGUI.
    OBRIGADO, DESDE JA.

    1. Olá, Jimmy! Basicamente, bastaria utilizar a seguinte instrução SQL em uma Query:
      Select * from TABELA where Codigo <> 'TDE'
      Mesmo assim, podemos conversar por e-mail para que eu possa compreender melhor o problema!

  3. Lembrando que o usuário pode substitui os parâmetros: ASSTRING, ASINTEGER, ASFLOAT, ASDATETIME por apenas um VALUE… só não sei se o ASDATETIME será eficiente, hehe, mas geralmente dá certo.

    Abraço..hehe

  4. Boa tarde Adré!
    Tenho o delphi 2010 e não estou conseguindo atualizar os dados com está sintaxe, onde estou errando. Desde já agradeço.

    with Module.zQNivers do
    Begin
    Module.zQNivers.Close;
    Module.zQNivers.SQL.Clear;

    Module.zQNivers.SQL.ADD (‘ Update Nivers’);
    Module.zQNivers.SQL.ADD (‘ SET (A_Nome,B_Niver)’);
    Module.zQNivers.SQL.ADD (‘ WHERE A_Nome =:PNome’);
    Module.zQNivers.SQL.ADD (‘ AND B_Niver =:PData’);
    Module.zQNivers.ParamByName(‘PNome’).AsString:=ed_Nome.Text;
    Module.zQNivers.ParamByName(‘PData’).AsDateTime:=StrToDateTime(ed_Data.Text);

    Module.zQNivers.Prepare;
    Module.zQNivers.ApplyUpdates;
    Module.zQNivers.ExecSQL;

    end;
    Abraço:

    Sinval

  5. Bom dia Andre.
    Mas neste caso faltou preencher o SQL Editor para criar o parametro, ou não é necessario.

    No aguardo,

    1. Bom dia, Cristiano. Neste caso, como estamos criando o parâmetro em tempo de execução (com os dois pontos), não é necessário preencher o SQL Editor. A própria Query irá identificar os parâmetros e aguardar os valores esperados. Abraço!

  6. Andre, boa noite. Otimo site por sinal e sempre ajudando quem necessita de ajuda. Parabens.
    Tenho algumas duvidas.
    Gostaria de fazer consulta tanto com a DESCRIÇAO como pelo ARTIGO com apenas um edit, no evento onchange, sem precisar de um botao.
    Tipo eu digitando e aparece no meu grid, exemplo CAN, e no meu cadastro aparecendo ANDRE, FERNANDO, ETC. Ou por codigo tipo digito 32, e me aparece no grid 5321, 9832, etc. Consegui fazer um ou outro funcionar, mas não os dois. onde pode estar o erro? Eu tenho Adoquery chamado (Qprodutos) um datasource chamado (dsqprodutos). Minha tabela chama-se Produtos. Meus campos de artigo se chama (CADP_ARTIGOPROD) e da descriçao do produtos chama-se (CADP_DESCRPROD).Se puder nos ajudar, ficaremos gratos. Abraço, Cristiano

    1. Olá, Cristiano. Realizar uma consulta por dois campos ao mesmo tempo pode ser feito tanto pela instrução SQL quanto pela propriedade Filter. Para esclarecer melhor, entrarei em contato por e-mail. Obrigado!

  7. Alguma forma de ver o conteúdo de Module.zQNivers.SQL.

    tentei fazer e retorna erro : HWND e Tstring incompatíveis….

    1. Olá, Emerson. Você pretende ver o conteúdo da propriedade SQL com os parâmetros preenchidos? Se este for o caso, é possível apenas com uma função específica implementada manualmente.

  8. Boa tarde André,
    Estou desenvolvendo uma aplicação pequena mas estou com problemas numa select, seguinte: Tenho duas tabelas Venda e ItensVenda, a primeira tem uma PK(Comanda) e a segunda uma FK(codigo) que faz referencia a PK da primeira. Queria selecionar “N” Campos (Ex: CodProd, Produto, ValUnit, ValTot, etc) da tablela ItensVenda, onde o Codigo (da tabela ItensVenda) fosse igual a Comanda (da tabela Venda).
    Fico na expectativa da ajuda e desde já, agradeço a a sua atenção.

    1. Olá, Fábio! Obrigado por deixar o comentário!
      Essa situação que você mencionou é bastante comum no desenvolvimento de software, e uma das alternativas é utilizar parametrização com Queries.
      Para ficar mais fácil, vou entrar em contato por e-mail, ok?
      Abraço!

  9. Há poucos que disponibilizam informação de uma forma simples sem complicação e com humildade, pois geralmente vejo pessoas que querem mostrar que sabem muito e acabam colocando varias linhas sem necessidade e confundindo o leitor.
    parabéns e obrigado.

  10. Olá, com certeza vc já deve saber, mais eu achei bem interessante e se vc quiser implementar, sobre a consulta com LIKE, ele diferencia Maiúscula de minúsculo, um jeito de burlar isso é:

    Query.SQL.Clear;
    Query.SQL.Text := ‘select * from Produtos where upper(descricao) like :descricao’;
    Query.ParamByName(‘descricao’).AsString := AnsiUpperCase(‘%’ + EditConsulta.Text + ‘%’);
    Query.Open;

    Nesse caso eu usei um datasource para usar o dbgrid.

    Será que tem outro jeito de não diferenciar maiúsculo de minúscula.

    E será que tem como mostrar uma lista dos produtos sem usar o datasource.

    1. Olá, Ribamar! Tem razão, quando se usa o LIKE há essa questão da diferença entre maiúsculo e minúsculo. Eu conheço 3 formas para fazer o tratamento:
      – No banco de dados: utilizar o UPPER na SQL
      – Na aplicação: Utilizar o AnsiUpperCase (assim como você sugeriu)
      – Ajustar a propriedade CharCase da TEdit para ecUpperCase.

      A respeito do DataSource, se você estiver utilizando um TDBGrid, a utilização de um DataSource é obrigatória, já que o TDBGrid precisa deste componente para buscar os dados que serão exibidos para o usuário. Caso você não pretenda utilizar um DataSource, basta usar componentes que não sejam DB-Aware, como o TStringGrid.

      Obrigado pelo comentário!

  11. Ola gostaria de resolver esse problema uso compontente zeos e firebird 2,5, sempre da um erro tem que resetar a aplicaçào porem insere o codigo apenas ele.

    dmsgc.zqclientes.SQL.Clear;
    dmsgc.zqclientes.SQL.Add(‘Insert into clientedb’);
    dmsgc.zqclientes.SQL.Add(‘(codigoclie, rgclie)’);
    dmsgc.zqclientes.SQL.Add(‘values (:pCodigoclie, :prgclie)’);
    dmsgc.zqclientes.ParamByName(‘pCodigoclie’).AsInteger:= StrToInt(dbedit1.Text);
    dmsgc.zqclientes.ParamByName(‘pRgclie’).AsString:=dbedit2.Text;

    dmsgc.zqclientes.ExecSQL;

  12. Olá André, primeiro parabéns pelo site tem sido de grande ajuda. Estou com a seguinte dificuldade:
    Usando select * from tabela where in(1,2,3) direto no firebird obtenho o resultado da consulta sem problema, porém, quando vou usar em tempo de execução utilizando um TSimpleDataSet dá erro quando passo mais de um valor. Já coloquei pra passar os valores por string, integer e nada. Pergunto, é possível usar a clásula IN em tempo de execução no delphi e sim como faço? Desde já agradeço a a ajuda.

  13. André, obrigado pela ajuda. Sua orientação para a questão acima foi excelente, o código está funcionando perfeitamente. Agora tenho outro problema com relação ao assunto com uso de mais de uma tabela na consulta utilizando apelidos na tabela e fazendo a junção através de INNER JOIN. Dá erro de coluna desconhecida. Veja o código:

    Dmr.slqFichaMembro.SQL.Add(‘SELECT M.NOMEMEMBRO, M.IDMEMBRO, C.DESCRICAOCARGO FROM MEMBRO M’ +
    ‘INNER JOIN CARGO C ON M.CARGO_IDCARGO = C.IDCARGO’ +
    ‘WHERE M.IDMEMBRO IN’ + Parametros);

    Erro
    —————————
    Debugger Exception Notification
    —————————
    Project iebm.exe raised exception class TDBXError with message ‘Token unknown – line 1, column 120
    —————————

    O erro aparece no campo informado na clásula WHERE. Não conseguir identificar aonde está o erro.

  14. Olá André, conheci o site agora e já gostei! Ótimo artigo, obrigada por compartilhar seu conhecimento de forma clara e descontraída 🙂

  15. Boa noite André, Conheci seu site recentemente, e vejo que você tem um grande conhecimento. Desenvolvi uma aplicação muito tempo atrás em Delphi 5 e me pediram para fazer uma mudança na aplicação. Só que precisaria criar uma nova tabela e fazer algumas alterações em uma tabela existente. Usei o Dbisam. Como criar e fazer alteração via código?

    1. Olá, Wilson. Já passei por uma situação semelhante e criei um atualizador automático, ou seja, um aplicativo separado que se conecta ao banco de dados e realiza as alterações necessárias na(s) tabela(s). Após um tempo, modifiquei este aplicativo para que ele carregasse um script SQL em tempo de execução, me dispensando de gerar um novo executável para cada atualização no banco de dados do cliente.
      Obrigado por deixar o comentário. Abraço!

  16. Caro André, Parabéns pela iniciativa!
    Minha dúvida é como escrever uma query e montá-la em tempo de execução, de acordo com a utilização ou não de um parâmetro.
    Tipo. Numa consulta eu tenho diversos campos para filtro, mas os parâmetros serão utilizados de acordo com o tipo de consulta que o usuário desejará fazer.
    O intuito é usá-la num programa de estatística.
    Ex. Numa comunidade tal, quantos homens com idade entre 20 e 45 anos, moram em casa de alvenaria, ganham entre 800 e 2000 reais e possuem 03 dependentes.
    Deu pra entender?

  17. Olá,
    Estou fazendo uma aplicação em lazarus para rodar no wince, nesta aplicação eu tenho que fazer um conexão com o Postgres e SqlServer, eu já consegui fazer a busca no banco, agora eu queria saber como eu faço para transforma os resultados que eu obtive, em objetos.

  18. Olá André, estou com um problema na minha aplicação,tenho um sistema que marca o horário que o funcionário sai para o almoço e registra a hora prevista para o seu retorno. Estou tentando fazer com que o sistema avise ao operador, no momento que a hora prevista for ultrapassada, usando a hora atual do computador. Gostaria de uma orientação sua ou um código SQL ou vice-versa para resolver esse problema. Fico grato desde já, pela a sua atenção.

  19. A ideia atual que mim veio agora,era usar um despertador feito em delphi. Agora só, tenho que fazer com que esse despertador, verifique os registros(ou no banco de dados ou dbgrid)para avisar os funcionários que passaram do horário do almoço. Qualquer duvida sobre o meu projeto pode entrar em contato.

  20. Olá André boa noite, tenho lido suas publicações que por sinal são ótimas.
    Porém tenho quebrado um pouco a cabeça em um projeto que estou fazendo em Delphi 5 com banco de dados no Mysql. E eu quero acessar o banco usando os componentes: Database, Query e DataSource (é uma das exigências do projeto) dentro de um DataModule.
    Queria saber se você pode me ajudar criando um exemplo pratico de como Inserir, Consultar, Deletar e Alterar os registros no banco…
    Demais deixo um abraço ao amigo, pois suas publicações tem acrescentado muito conhecimento na minha vida.

  21. Olá André, gostei muito da publicação e me acrescentou muito. Estou com um problema e talvez você possa me auxiliar. Estou construindo um sistema em Lazarus, mas acredito que em Delphi, que também gosto muito, tenha o mesmo problema. Faço uma consulta utilizando o componente ReadOnlyQuery e TZquery, que retorna um campo do tipo texto muito extenso. Na consulta sql do pgAdmin retorna completa, mas no sistema tanto no relatório quanto em um grid ou dbgrid não retorna todos os dados, a consulta vem incompleta. A consulta retorna até um ponto. Acredito que seja alguma configuração nos objetos. Você já teve algo parecido?

    Grata, Lílian.

    1. Olá, Lilian!
      Ainda não tive a oportunidade de trabalhar com o Lazarus ou com o PostgreSQL no Delphi, mas acredito que este problema esteja relacionado à configuração das propriedades da Query que faz a consulta. Para ficar mais fácil, vou pedir mais alguns detalhes por e-mail, ok?

      Abraço!

  22. Bom dia!
    Estou com um grande problema e preciso de ajuda.
    Estou criando uma aplicação onde Faço uma pesquisa com o componente IBQuery e preciso alterar os dados dessa pesquisa com isso usei o IBQuery + IBUpdateSql. Consegui configurar os dois, porém na hora de salvar esta dando erro. Alguém sabe como funciona esses componentes?

  23. Boa tarde sou iniciante ainda em delphi.

    preciso fazer um consulta com parametros em dois registros. e depois verificar se eles existem. mas não estou conseguindo.

    //*****************************************************************************
    with DM_VENDAS.CDS_PEGA_MESA do
    begin
    close;
    FetchParams;
    Params.ParamByName(‘MESA’).AsInteger:= 2;
    Params.ParamByName(‘STATUS’).AsString:=’CONSUMINDO’;
    Open
    end;
    //*****************************************************************************

    if (dm_vendas.CDS_PEGA_MESA.Params.ParamByName(‘MESA’).AsInteger = 2) and (dm_vendas.CDS_PEGA_MESA.Params.ParamByName(‘STATUS’).AsString = ‘CONSUMINDO’) then
    begin
    ShowMessage(‘Mesa já Cadastrada’);
    end;

    se mudar o status da mesa, continua a dizer que a mesa ja existe.

    alguem poderia me ajudar por favor?

    1. Olá, Sérgio! Ao meu ver, há um equívoco no código: na comparação IF, deve-se utilizar o FieldByName, e não o ParamByName, lembrando que o ParamByName só é utilizado para injetar valores em uma instrução SQL, portanto, não deve ser utilizado em comparações.

      Abraço!

  24. Ola Andre.
    A dica eh muito boa porem sempre que uso esta tecnica recebo esta mensagem:

    Preparing statement: select * from PRODUTO
    where codprod = :consulta
    Error: *** IBPP::SQLException ***
    Context: Statement::Prepare( select * from PRODUTO
    where codprod = :consulta )
    Message: isc_dsql_prepare failed

    SQL Message : -206
    Column does not belong to referenced table

    Engine Code : 335544569
    Engine Message :
    Dynamic SQL Error
    SQL error code = -206
    Column unknown
    CONSULTA
    At line 2, column 22

    Alguma ideia por que recebo esta mensagem?

  25. Estou tentando fazer um relatório de caixa onde apareça as vendas e os recebimentos por periodo..no relatório no Report Build está OK o problema é os parametros no Delphi…o aparece as vendas no relatório se tiver recebimento e eu não quero assim! eu quero que traga vendas se tiver e se não tiver traga os recebimentos..meu codigo está assim:

    with DM.SQL_caixa do

    begin

    Close;
    SQL.Clear;
    SQL.Add(‘SELECT * FROM VIEW_PEDIDOS’);
    SQL.Add(‘WHERE DATA BETWEEN :Data_inicial AND :Data_final’);
    SQL.Add(‘AND entrasaldo = “S”‘);
    ParamByName(‘Data_inicial’).Value := FormatDateTime(‘yyy-mm-dd’, data_inicial.Date);
    ParamByName(‘Data_final’).Value := FormatDateTime(‘yyy-mm-dd’, data_final.Date);
    Open;

    with DM.SQL_Recebimento do

    begin

    Close;
    SQL.Clear;
    SQL.Add(‘SELECT * FROM parcelas_prontas’);
    SQL.Add(‘WHERE carne_data_pago BETWEEN :Data_inicial AND :Data_final’);
    SQL.Add(‘AND carne_status = “SIM”‘);
    ParamByName(‘Data_inicial’).Value := FormatDateTime(‘yyy-mm-dd’, data_inicial.Date);
    ParamByName(‘Data_final’).Value := FormatDateTime(‘yyy-mm-dd’, data_final.Date);
    Open;

    if RecordCount > 0 then
    begin
    DM.RPB_caixa.PrintReport;
    end
    else
    begin

    if Application.MessageBox(‘Não existe venda ou recebimento nesse periodo’,’Sistema de Vendas – SYSPDV’, MB_OK) = IDOK then

    end;
    end;
    end;

    como faço pra buscar os registro das 2 query?

    1. Olá, Jhonlenon, tudo certo?
      Ao que me parece, a solução para o seu caso é utilizar o comando UNION na instrução SQL. Esse comando faz a união de duas consultas separadas, resultando em um conjunto único de registros. Na prática, seria algo como:
      Select * from VIEW_PEDIDOS ...
      UNION
      Select * from parcelas_prontas

      Para ajudá-lo melhor, confira os artigos abaixo do 1KeyData e do Macoratti:

      http://www.1keydata.com/pt/sql/sql-union.php/
      http://www.macoratti.net/13/05/sql_uni1.htm

  26. Olá Boa tarde André Luiz…agradeço pela ajuda no tópico…realmente UNION foi a melhor solução…estou fazendo outro relatório interno de lançamentos Manual de credito e debito…estou querendo obter o saldo (CREDITO – DEBITO) = Saldo
    tenho uma Tabela chamada lancamentos, com os seguintes campo:

    CREATE TABLE servidormysql.lancamentos (
    id INT(11) NOT NULL AUTO_INCREMENT,
    descricao VARCHAR(200) DEFAULT NULL,
    data DATE DEFAULT NULL,
    valor DOUBLE DEFAULT 0,
    tipo CHAR(10) DEFAULT NULL,
    PRIMARY KEY (id)
    )
    ENGINE = INNODB
    AUTO_INCREMENT = 18
    AVG_ROW_LENGTH = 8192
    CHARACTER SET latin1
    COLLATE latin1_swedish_ci;

    Adicionei um TDBRadiogroup no formulario de inseri ai marco Debito ou Credito…como se trata de um relatório interno usando Report Build preciso fazer isso em campo calculado! onde me traga o saldo…também não estou conseguindo gravar o valor debito negativo no banco de dados…

    Uso o banco de dados Mysql e Delphi 2010

    Peço ajuda André…..

  27. Olá andré…..estou com um problema aqui…tenho uma view_pedidos que eu uso para trazer os itens do pedido da venda, no relatório..porém ele duplica os valores total do pedido quando tenho mais de um item na venda..isso é normal, por exemplo tenho uma venda com o numero do pedido 000654 ai tenho 4 itens
    a view traz assim

    Pedido Item QTD Valor Unidade ValorPedido
    000654 01 02 50,00 250,00
    000654 03 01 60,00 250,00
    000654 05 03 30,00 250,00

    Eu não posso agrupar pelo o numero do pedido…porque preciso de todos o itens no pedido com seus valores

    fiz com DISTINCT mais não deu certo no Report Build..ele não obedece o DISTINCT que coloco dentro da propriedade calculo

    Select sum(DISTINCT(valorpedido)) from view_pedidos where data BETWEEN ‘2015-01-01’ and ‘2015-01-01’

    tenho que somar o valorpedido sem repetir os valores

  28. Olá, André… realmente tive que criar outra view trazendo os valores total com desconto. A view pedidos ficou só para trazer os itens mesmo.

    Obrigado… até a próxima.

  29. Olá André…tenho esse escript que uso no SQL Server….mais estou desenvolvendo um sistema em Delphi e Mysql…esse select é pra trazer os banco de dados….mais não sei como fazer no Mysql…no SQL Server é esse aqui

    Select name
    From Master.sys.Databases
    Where name Not In (‘Distribution’,’Master’,’model’,’msdb’,’tempdb’,’ReportServer’,’ReportServerTempDB’)

    como converter esse script para o Mysql?

  30. Rapaz, seu post é excelente e também me ajudou muito.
    gostaria de um exemplo simples para iniciante mesmo, de um comando Sql que busque mais parâmetros tipo nome, endereço , data de nascimento.só pra eu ter uma base mesmo e entender.Um código Sql que busque com select mais de um parâmetro.
    obrigado e parabéns

    1. Olá, Gilmar, tudo bem?
      Primeiramente, gostaria de agradecê-lo pelo comentário e também pelo feedback sobre o artigo!
      Gilmar, não conheço o seu nível de conhecimento em programação, então eu acho mais fácil você iniciar as atividades de codificação e, à medida que surgir as dificuldades, você entra em contato para eu possa orientá-lo, pode ser?

      Abraço!

    2. Claro André, obrigado pela atenção.
      De imediato este seu exemplo abaixo me ajudou muito:
      Query1.SQL.Clear;
      Query1.SQL.Add(‘Select * from CLIENTES where Codigo = :pCodigo’);
      Query1.ParamByName(‘pCodigo’).AsInteger := StrToInt(edtCodigo.Text);
      Query1.Open;
      ele faz uma busca na tabela clientes onde o campo Código é passado pelo usuário no edtCodigo.text.O que preciso é acrescentar mais um campo na busca, onde o usuário digitaria por exemplo o Código no campo edtCodigo e datacadastro no campo edtDatacadastro.
      De inicico este codigo já me ajudaria muito.
      Atenciosamente,

  31. Ola, na verdade o que eu preciso é atraves de um select preencher um combobox, mas apenas com valores e sim apenas com os campos, ex: select nome, email, fone from pessoas
    no combo:
    nome
    email
    fone

    Abracos

    1. Olá, Anderson. Pelo que entendi, você precisa exibir a estrutura de uma tabela no ComboBox, e não os dados, correto?
      Bom, neste caso, a sua instrução Select será um pouco diferente. Procure por “select field names from table” no Google, acompanhado do nome do banco de dados que você está utilizando. Cada banco de dados possui uma forma diferente de retornar essas informações.

      Boa sorte. Abraço!

  32. Muito bom seu post!
    meu velho como faz para gerar ID automatico sequencial nessa query?
    estou tentando dessa forma mas retorna a mensagem: cannot perform this operation on a closed dataset.
    abaixo o que estou tentando…

    if (application.MessageBox('Deseja inserir um novo registro?', 'Inserir registro', MB_YESNO + MB_ICONQUESTION)= idyes) then
          begin
            SqlImoveis.Close;
            SqlImoveis.Refresh;
            SqlImoveis.First;
         if SqlImoveis.FieldCount = 0 then codi:=1 else
       begin
            SqlImoveis.Last;
             codi:=CdsImoveisIDIMOVEL.asinteger + 1;
       end;
            CdsImoveisIDIMOVEL.asinteger:= codi;
            SqlImoveis.Open;
          end;

    Dar uma forcinha ae meu velho! vlw obrigado

  33. eu removi o SqlImoveis.Refresh; mas mesmo assim aparece mensagem: cannot perform this operation on a closed dataset. alguma sugestao de como resolver ? vlw abraço !

    1. Carlos, acredito que o comando “First” também não é permitido quando o DataSet está fechado.
      Revise o seu código e remova todos os comandos de acesso aos dados do DataSet quando ele estiver fechado, ok?

      Abraço!

  34. ja fiz varias coisas e nada resolvido, no caso que quero é gerar ID automatico.
    tem algum exemplo ?

    1. Carlos, você pode usar o MAX na instrução SQL para obter o maior número e somar + 1:

      SQLQuery.Close;
      SQLQuery.SQL.Clear;
      SQLQuery.SQL.Text := 'SELECT MAX(IDIMOVEL) + 1 AS NovoCodigo FROM IMOVEIS';
      SQLQuery.Open;
      
      NovoCodigo := SQLQuery.FieldByName('NovoCodigo').AsInteger;

      Porém, não sou de acordo com esse tipo de solução. Isso causaria erros de integridade em aplicações Cliente/Servidor.
      Sugiro que o ID seja atribuído imediatamente antes de salvar o registro, por exemplo, através de uma Trigger no banco de dados.

      Abraço.

  35. boa tarde meu nome é cleber estou precisando uma busca parcial do registro,utilizei esse codigo
    ” utilizando a cláusula LIKE na SQL e adicionando o símbolo de porcentagem ao nome:”

    Query1.SQL.Clear;
    Query1.SQL.Add('Select * from CLIENTES where Nome like :pNome');
    Query1.ParamByName('pNome').AsString := edtNome.Text + '%';
    Query1.Open;

    ele funciona porem ele so pega o comeco do nome preciso que ele faça uma pesqusa tanto pelo começo , como no final ex
    cod
    7135-573
    digitando 7135-
    digitando -573
    que me retorne 7135-573

    1. Olá, Cleber, tudo bem?
      Para pesquisar pelo conteúdo parcial, é necessário adicionar um sinal de porcentagem no início também, ficando dessa forma:

      Query1.ParamByName('pNome').AsString := '%' + edtNome.Text + '%';

      Espero que lhe ajude!
      Abraço!

  36. Boa noite.
    Estou fazendo um projeto no delphi e estou criando o codigo automatico pela Query onde o meu professor achou melhor. mas estou tendo alguns erros sera que pode me dar uma opinia: na query eu tenho o seguinte codigo: select max(CLI_COD) as Maior
    from CLIENTE

    e no formulario:

    dtm.tblCliente.Open;
    dtm.tblCliente.Insert;
    dtm.qryClientes.Open;
    dtm.tblClienteCLI_COD.Value := dtm.qryClientes.SQL.Add('select max(CLI_COD) as Maior '+
      'from CLIENTE');
    dtm.qryClientes.Close;

    mas estou tendo erro.

    1. Boa noite, Larissa, tudo bem?
      O método “Add” da Query não tem um retorno. É uma procedure para atribuir uma instrução SQL dentro da Query, portanto, não é possível receber o valor da forma como você codificou.
      Primeiro, você precisa executar essa SQL e, em seguida, acessar o valor. Veja o exemplo:

      // fecha a Query
      dtm.qryClientes.Close;
      // limpa a propriedade SQL
      dtm.qryClientes.SQL.Clear;
      // atribui a instrução SQL
      dtm.qryClientes.SQL.Add('select max(CLI_COD) as Maior from CLIENTE');
      // abre a Query
      dtm.qryClientes.Open;
      
      dtm.tblCliente.Open;
      dtm.tblCliente.Insert;
      // acessa o valor pelo método FieldByName
      dtm.tblClienteCLI_COD.Value := dtm.qryClientes.FieldByName('Maior').AsInteger + 1;
      dtm.qryClientes.Close;

      Boa sorte no projeto!

  37. Olá André Celestino, bom dia

    Por gentileza estou tentando realizar um comando mysql pelo delphi, mas dá erro, acredito que não estou acertando realizar as separações com aspas simples e duplas. Segue abaixo o codigo da rotina

    LOAD DATA INFILE ‘C:/pasta/teste.txt’
    INTO TABLE calcados
    FIELDS TERMINATED BY ‘[TITULO]’
    LINES TERMINATED BY ‘[FIM]’
    (NOME, VALOR)
    set ID = NULL, DATADISPONIBILIZACAO = DATE(NOW()), DISPONIBILIDADE = ‘SIM’;

    Poderia me ajudar a montar esse comando no delphi, fiz da seguinte forma, mas acusa erro:

    dmDados.SQLQueryImportacao.SQL.Add(‘INTO TABLE calcados’) ;
    dmDados.SQLQueryImportacao.SQL.Add(‘FIELDS TERMINATED BY [TITULO] ‘) ;
    dmDados.SQLQueryImportacao.SQL.Add(‘LINES TERMINATED BY [FIM]’) ;
    dmDados.SQLQueryImportacao.SQL.Add(‘(NOME, VALOR)’) ;
    dmDados.SQLQueryImportacao.SQL.Add(‘set ID = NULL, DATADISPONIBILIZACAO = DATE(NOW()), DISPONIBILIDADE = “SIM”‘);

    Grato querido.

    1. Bom dia, Anselmo, tudo bem?
      Notei que a sua dúvida é um pouco mais avançada e precisa de um acompanhamento.
      Vou entrar em contato por e-mail, ok?

      Abraço!

  38. boa tarde andre,
    parabens pelo site
    andre, estou fazendo um sistema simples de cadastro de cliente e nele tem uma dbgrid com os dados.
    preciso criar uma busca neste dbgrid que ao começar a digitar vai filtrando os nomes que tem a expressao: exemplo
    JOAO, ai aparece todos os registros que tem o JOAO no nome

    estou usando um MDB do access, tenho Adoconection 1 Adotable e 1 DataSource ja tentei mas nao consigo
    voce pode me dar uma ajuda?
    obrigado

    1. Boa tarde, Márcio, como vai?
      Desculpe-me pela demora para respondê-lo.
      Para filtrar registros em um DataSet, geralmente trabalhamos com as propriedades Filter e Filtered, porém, no momento não consigo confirmar se o TADOTable atualmente suporta filtros parciais com o operador Like, mas vale a pena fazer um teste.

      Veja este tópico do Stack Overflow para tomar como base:

      http://stackoverflow.com/questions/6799234/need-help-with-delphi-and-adotable-filtering

      Abraço!

  39. André

    Estou estudando Delphi e me deparei com uma duvida

    Estou fazendo um “select “select coluna1 from tabela”

    O resultado desse select eu queria mostrar em um mesmo.

    Ele deveria retornar todas as linhas da coluna1, mas quando eu coloco memo.text := fieldbyname(coluna1).asstring só me retorna a primeira linha da coluna1 que estou pesquisando.

    Desculpa algum erro estou no celular

    1. Olá, Sanmyo, como vai?
      Para exibir os valores de todas as linhas, geralmente percorremos os registros em uma iteração (looping), como, por exemplo, com uma instrução while.
      Veja o exemplo a seguir. Para cada iteração, o valor de “Coluna” é adicionado no componente TMemo.

      // Move para o primeiro registro
      DataSet.First;
      
      // Percorre o DataSet
      while not DataSet.Eof do
      begin
        Memo.Lines.Add(DataSet.FieldByName('Coluna').AsString);
      
        // Move para o próximo registro
        DataSet.Next;
      end;

      Espero que lhe ajude.
      Abraço!

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Preencha o campo abaixo * Time limit is exhausted. Please reload CAPTCHA.