Série da semana: Primeiros passos no Angular

Veja mais

SQL só faz pesquisa com a primeira letras

28/03/2019

29

Galera, desenvolvi um sisteminha bem simples, apenas pra cadastrar ordem de serviço para que qd precisar localizar serviço que algum cliente fez um tempo atras, apenos vou lah digito o nome do cliente ou da empresa e ele me retorna as informações dos serviço que ele fez, o talão que foi utilizado, a data e enfim... Mas qd eu digito o nome do cliente ou empresa, ele faz busca apenas com a primeira letra, se continuar digitandom, ele some e não aparece nada mesmo existindo o registro no Banco de dado. Resumindo, só faz pesquisa apenas com a primeira letras apenas, se digitar pra filtar melhor o nome ele some. Segue o código que uso. Lembrando que os componete que uso, é o IBDataBase, IBTransaction, IBDataSet e DataSource.
/code
begin
if Edit1.Text = '' then
Edit2.Enabled:=True
else
Edit2.Enabled:=False;
begin
dm.DsOs.Close;
dm.DsOs.SelectSQL.Clear;
dm.DsOs.SelectSQL.Add('SELECT * FROM CAD_OS');
if Edit1.Text <> '' then
begin
dm.DsOs.SelectSQL.Add('where EMPRESA like :empresa');
dm.DsOs.ParamByName('empresa').asString := ANSIUPPERCASE(Edit1.Text) + '%';
end;
dm.DsOs.Open;
end;
end;
//code
Responder

Post mais votado

01/04/2019

tente assim:
begin
	Edit2.Enabled := (Edit1.Text = '');
	dm.DsOs.Close;
	dm.DsOs.SelectSQL.Clear;
	dm.DsOs.SelectSQL.Add('SELECT * FROM CAD_OS');
	if Edit1.Text <> '' then
	begin
		dm.DsOs.SelectSQL.Add('where EMPRESA like :empresa');
		dm.DsOs.ParamByName('empresa').asString := ANSIUPPERCASE(Edit1.Text) + '%';
	end;
	dm.DsOs.Open;
end;


Responder

Mais Posts

Olá Valdenir,

O Código está um pouco vago, eu precisaria saber em que evento ele ocorre, e depois d alinha "Edit2.Enabled:=False;" parece que está faltando algum código, teria como repostar o código?
Responder
Olá Valdenir,

O Código está um pouco vago, eu precisaria saber em que evento ele ocorre, e depois d alinha "Edit2.Enabled:=False;" parece que está faltando algum código, teria como repostar o código?

Essa parte aqui
begin
if Edit1.Text = '' then
Edit2.Enabled:=True
else
Edit2.Enabled:=False;


existe dois Edits de pesquisa, um para empresa e outro para nome do responsavel, enquanto um esta sendo usado o outro automaticamente desabilita. Eu pensei em fazer com que a pesquisa de 'Empresa' e 'Responsáve'l fosse em apenas um edit, mas nesse caso eu preferi deixar assim.
Agora essa parte:
dm.DsOs.Close;
dm.DsOs.SelectSQL.Clear;
dm.DsOs.SelectSQL.Add('SELECT * FROM CAD_OS');
if Edit1.Text <> '' then
begin
dm.DsOs.SelectSQL.Add('where EMPRESA like :empresa');
dm.DsOs.ParamByName('empresa').asString := ANSIUPPERCASE(Edit1.Text) + '%';
end;
dm.DsOs.Open;
end;

Ela vai no evento onchange do Edit de pesquisa
Responder
Galera, alguém pode me dar uma luz de como resolver essa questão?
Responder
tente assim:
begin
	Edit2.Enabled := (Edit1.Text = '');
	dm.DsOs.Close;
	dm.DsOs.SelectSQL.Clear;
	dm.DsOs.SelectSQL.Add('SELECT * FROM CAD_OS');
	if Edit1.Text <> '' then
	begin
		dm.DsOs.SelectSQL.Add('where EMPRESA like :empresa');
		dm.DsOs.ParamByName('empresa').asString := ANSIUPPERCASE(Edit1.Text) + '%';
	end;
	dm.DsOs.Open;
end;



Eu vou tentar hj a noite, mas pelo que analisei nesse código, ele é igual ao meu, a diferença é que muda apenas a forma de habilitar e desabilitar os edit em modo de edição. O que eu preciso é que ao digitar os nome no campo de pesquisa, conforme eu for digitando os nome irem aparecendo conforme a pesquisa. Do jeito que eu fiz, ele aparece apenas a primeira letra, se eu digitar a segunda, mesmo existindo no banco de dado, a pesquisa some, não retorna nada. Só aparece qd eu digito apenas a primeira letra. Será que esse código que vc me passou ele continua filtrando de acordo com que for digitando no campo de pesquisa? vou fazer um teste hj a noite.
Responder
tente assim:
begin
	Edit2.Enabled := (Edit1.Text = '');
	dm.DsOs.Close;
	dm.DsOs.SelectSQL.Clear;
	dm.DsOs.SelectSQL.Add('SELECT * FROM CAD_OS');
	if Edit1.Text <> '' then
	begin
		dm.DsOs.SelectSQL.Add('where EMPRESA like :empresa');
		dm.DsOs.ParamByName('empresa').asString := ANSIUPPERCASE(Edit1.Text) + '%';
	end;
	dm.DsOs.Open;
end;




Deu na mesma, como imaginei, apenas mudou o tratamento dos Edits, na vdd o resultado de como os edits trabalham, continuou o mesmo, só a linha de comando que ficou mais resumido. O que eu preciso é na pesquisa, fazer com, que, conforme for digitando o respectivo nome ir aparecendo. Não é uma coisa complicada de fazer, eu acho que é algo muito simples que deixei de por nos código, é alguma coisa q ta faltando ali.
Responder
O que é o DsOS? É um datasource?

Eu sempre manipulo o clientdataset, e não o datasource.
Responder
O que é o DsOS? É um datasource?

Eu sempre manipulo o clientdataset, e não o datasource.


Não, é um DataSet, basicamente o mesmo ClientDataSet. Os componente na qual eu utilizo são esses: IBDataBase, IBTransaction, IBDataSet e DataSource.
É um detalhe simples que devo estar esquecendo ali, fazer pesquisa normalmente, digitar e o nome ir aparecendo conforme for digitado. Eu não to lembrando agora, to um pouco enferrujado. Mas no momento ele apenas aparece o resultado com a primeira letra do nome digitado, ai ele filtra vários nome com a primeira letra igual, eu preciso que ele filtro melhor conforme for digitando.
Responder
Galera, alguma idéia do que falta no meu código, alguém pode dar um luz?
Responder
Porque você não utiliza busca do registro no lugar de ficar fechando e abrindo a tabela? Talvez seja melhor, até em relação à performance.
var
  LocateSuccess: Boolean;
  SearchOptions: TLocateOptions;
begin
  SearchOptions := [loPartialKey, loCaseInsensitive];
  LocateSuccess :=dm.DsOs.Locate('EMPRESA', trim(Edit1.Text), SearchOptions);
end;

obviamente a tabela precisa ter sido aberta em um outro momento (após abrir o form, por exemplo)
Responder
Porque você não utiliza busca do registro no lugar de ficar fechando e abrindo a tabela? Talvez seja melhor, até em relação à performance.
var
  LocateSuccess: Boolean;
  SearchOptions: TLocateOptions;
begin
  SearchOptions := [loPartialKey, loCaseInsensitive];
  LocateSuccess :=dm.DsOs.Locate('EMPRESA', trim(Edit1.Text), SearchOptions);
end;

obviamente a tabela precisa ter sido aberta em um outro momento (após abrir o form, por exemplo)

A idéia é até válida, é mais ou menos isso que preciso, problema que nesse caso ele retorna apenas um registro , que eu preciso é fazer a pesquisa e aparecer todos registro com mesmo nome que digitei. O que esse código faz realmente é conforme vc vá digitando ele vai buscando conforme o que vc ta escrevendo, o problema é que as vezes existe mais de um serviço feito com a mesma empresa, no DBGrid, preciso que conforme for digitando apareça apenas todos os nomes de empresa conforme o que esta sendo digitado. Por exemplo, quero buscar uma empresa chamado "Mecânica Diesel", então no DBGrid deve aparecer todos os registro com esse nome, se essa mecânica fez mais de um serviço, preciso que apareça todos.
Responder
Ele somente posiciona no registro. Não faz qualquer filtro. E, se o resultset já estiver ordenado pelo campo utilizado na pesquisa, ao procurar a informação, os dados estarão agrupados.
Responder

05/04/2019

Wesley Aip

Olá.
Dependendo de como sua tabela foi criada, o comportamento do sql pode mudar quando se trata de Case Sensitive.
Isso se deve ao Collate utilizado.

dm.DsOs.ParamByName('empresa').asString := ANSIUPPERCASE(Edit1.Text) + '%';


Se sua empresa se chama: "Volkswagen do Brasil" por exemplo, com o ANSIUPPERCASE o sql vai entender que você está digitando "VOLKSWAGEN DO BRASIL", logo, se seu banco está preparado para diferenciar por Case Sensitive, as duas palavras são diferentes, por isso é como se a busca só encontrasse o V maiúsculo e o restante não corresponde á pesquisa.

A dica é, esqueça o delphi e monte suas queries fazendo os testes no banco primeiro.
Se seu banco está com collate case sensitive, faça a query utilizando upper ou lower nativo do sql.
Select * from Cad_Os where Upper(EMPRESA) like '% ANSIUPPERCASE(Edit1.Text) %'

Outra coisa, uma conduta que facilita drasticamente o debug de um programa é montar a query antes, e depois de pronta, atribuir ao seu objeto TQuery por exemplo:

begin
	if Edit1.Text = '' then
		Edit2.Enabled := True
	else
		Edit2.Enabled := False;
	
	strQry := 'Select * from Cad_Os';
	strQry := strQry + ' Where 1 = 1';
	
	if Edit1.Text <> '' then
		strQry := strQry + ' and EMPRESA like ''%'+ Edit1.Text +'%'''; // se quiser a busca em qualquer parte da string
		//strQry := strQry + ' and EMPRESA like '''+ Edit1.Text +'%'''; // se quiser a busca com qualquer fim
		//strQry := strQry + ' and EMPRESA like ''%'+ Edit1.Text +''''; // se quiser a busca com quelquer inicio

	if Edit2.Text <> '' then
		strQry := strQry + ' and RESPONSAVEL like ''%'+ Edit2.Text +'%'''; // se quiser a busca em qualquer parte da string
	
	dm.DsOs.Close;
	dm.DsOs.SelectSQL.Clear;
	dm.DsOs.SelectSQL.Add(strQry);
	dm.DsOs.Open;
end;


Espero que ajude!
Responder

Se sua empresa se chama: "Volkswagen do Brasil" por exemplo, com o ANSIUPPERCASE o sql vai entender que você está digitando "VOLKSWAGEN DO BRASIL", logo, se seu banco está preparado para diferenciar por Case Sensitive, as duas palavras são diferentes, por isso é como se a busca só encontrasse o V maiúsculo e o restante não corresponde á pesquisa.

A minha tabela não fiz montado com Case Sensitive, ela é bem simples. As informações adicionada no registro sempre iniciam com letras maiusculas e restante minuscula. Mas independente de como adiciono as informações no registro, tanto tudo maiuscula, miniscula ou só as iniciais, elas se comportam da mesma forma.

A dica é, esqueça o delphi e monte suas queries fazendo os testes no banco primeiro.
Se seu banco está com collate case sensitive, faça a query utilizando upper ou lower nativo do sql.
Select * from Cad_Os where Upper(EMPRESA) like '% ANSIUPPERCASE(Edit1.Text) %'


Não entendi bem essa parte, eu teria que fazer isso direto no banco, ou seja no aplicativo que monta o banco? não no próprio delphi? Pq esse código acima
ele é usado no Delphi, no sistema de busca.


Outra coisa, uma conduta que facilita drasticamente o debug de um programa é montar a query antes, e depois de pronta, atribuir ao seu objeto TQuery por exemplo:

begin
	if Edit1.Text = '' then
		Edit2.Enabled := True
	else
		Edit2.Enabled := False;
	
	strQry := 'Select * from Cad_Os';
	strQry := strQry + ' Where 1 = 1';
	
	if Edit1.Text <> '' then
		strQry := strQry + ' and EMPRESA like ''%'+ Edit1.Text +'%'''; // se quiser a busca em qualquer parte da string
		//strQry := strQry + ' and EMPRESA like '''+ Edit1.Text +'%'''; // se quiser a busca com qualquer fim
		//strQry := strQry + ' and EMPRESA like ''%'+ Edit1.Text +''''; // se quiser a busca com quelquer inicio

	if Edit2.Text <> '' then
		strQry := strQry + ' and RESPONSAVEL like ''%'+ Edit2.Text +'%'''; // se quiser a busca em qualquer parte da string
	
	dm.DsOs.Close;
	dm.DsOs.SelectSQL.Clear;
	dm.DsOs.SelectSQL.Add(strQry);
	dm.DsOs.Open;
end;


Espero que ajude!

Aqui vc colocou os dois Edits em um só. Para empresa e Responsavel, são um Edit pra cada. Mas pelo que analisei nesse código parece que ele realmente faz a busca independente de como foi gravado as informações de registro no banco, vou fazer o teste hj a noite e repasso o resultado aqui.
Responder
O Wesley tem razão. Pela query que você montou, dá a entender que você GRAVA tudo em maiúsculas, e usa o AnsiUpperCase() para garantir que encontre o que precisa. Se você grava tanto maiúsculas quanto minúsculas, o correto é transformar tudo em maiúsculas no momento da procura.
begin
    Edit2.Enabled := (Edit1.Text = '');
    dm.DsOs.Close;
    dm.DsOs.SelectSQL.Clear;
    dm.DsOs.SelectSQL.Add('SELECT * FROM CAD_OS');
    if Edit1.Text <> '' then
    begin
        dm.DsOs.SelectSQL.Add('where upper(EMPRESA) like :empresa');
        dm.DsOs.ParamByName('empresa').asString := ANSIUPPERCASE(Edit1.Text) + '%';
    end;
    dm.DsOs.Open;
end;
Responder
O Wesley tem razão. Pela query que você montou, dá a entender que você GRAVA tudo em maiúsculas, e usa o AnsiUpperCase() para garantir que encontre o que precisa. Se você grava tanto maiúsculas quanto minúsculas, o correto é transformar tudo em maiúsculas no momento da procura.
begin
    Edit2.Enabled := (Edit1.Text = '');
    dm.DsOs.Close;
    dm.DsOs.SelectSQL.Clear;
    dm.DsOs.SelectSQL.Add('SELECT * FROM CAD_OS');
    if Edit1.Text <> '' then
    begin
        dm.DsOs.SelectSQL.Add('where upper(EMPRESA) like :empresa');
        dm.DsOs.ParamByName('empresa').asString := ANSIUPPERCASE(Edit1.Text) + '%';
    end;
    dm.DsOs.Open;
end;

Muito obrigado, aquele 'upper' resolveu de letra o meu problema, no inicio como eu tinha postado, sabia que era uma coisa bem simples que tava esquecendo, pq antigamente eu mexia mais com programação, mas eu meio que dei uma parada por um bom tempo, muita coisa acabei esquecendo, mas sabia que faltava alguma coisinha que resolvia esse problema, só não lembrava o que era. Vlw muito obrigado, deu super certo.
Responder