PDA

Ver la Versión Completa : Seleccionar registros que comiencen por un valor string


Pedro-Juan
29-06-2012, 13:52:16
Hola a tod@s

Delphi7, Interbase, Zeos. Controles externos a Delphi AlphaControls.

Estoy intentando hacer una consulta para que se muestre en un DBGrid el resultado a medida que se teclea en un Edit. Cuando lo que se busca tiene que estar contenido en el campo, todo va bien, pero si lo que se requiere es que sólo seleccione los registros que comienzan con lo tecleado en el Edit, la cosa no sale.

Tengo esto en el OnChange del Edit:

procedure TF_Main.sEdit_BuscarTitChange(Sender: TObject);
var cCadena: String;
nChar: Integer;
begin
cCadena := Trim(F_Main.sEdit_BuscarTit.Text);
nChar := Length(cCadena);

if (F_Main.sRG_BuscarTit.ItemIndex = 0) then begin
end;

//Que el texto esté contenido (funciona bien)
if (F_Main.sRG_BuscarTit.ItemIndex = 1) then begin
if (F_Main.sEdit_BuscarTit.Text <> '') then begin
DM_Libros.Q_TITULOS.Close;
DM_Libros.Q_TITULOS.SQL.Clear;
DM_Libros.Q_TITULOS.SQL.Add('Select * From TITULOS');

//Mayúsculas/minúsculas
if (F_Main.sCheckB_MayMinBuscarTit.Checked) then begin
cCadena := '%' + cCadena + '%';
DM_Libros.Q_TITULOS.SQL.Add('Where (NomTit like :cCadena)');
DM_Libros.Q_TITULOS.Parambyname('cCadena').AsString := cCadena;
end
else
DM_Libros.Q_TITULOS.SQL.Add('where UPPER(NomTit) like ''%' + AnsiUpperCase(cCadena) + '%''');

DM_Libros.Q_TITULOS.Open;
end
else //.........
end;

//Que el campo comience con el texto introducido (no funciona)
if (F_Main.sRG_BuscarTit.ItemIndex = 2) then begin
if (F_Main.sEdit_BuscarTit.Text <> '') then begin
DM_Libros.Q_TITULOS.Close;
DM_Libros.Q_TITULOS.SQL.Clear;
DM_Libros.Q_TITULOS.SQL.Add('select * from TITULOS where SUBSTR(NomTit, 1, :nChar) = :cCadena');
DM_Libros.Q_TITULOS.Parambyname('nChar').AsInteger := nChar;
DM_Libros.Q_TITULOS.Parambyname('cCadena').AsString := cCadena;
DM_Libros.Q_TITULOS.Open;
end
else //.........

//También lo he probado con estas opciones:
DM_Libros.Q_TITULOS.SQL.Add('Select * From TITULOS SUBSTRING(NomTit,1,nChar) = :cCadena');
DM_Libros.Q_TITULOS.SQL.Add('Select * SUBSTRING(NomTit,1,nChar) = cCadena From TITULOS');
DM_Libros.Q_TITULOS.SQL.Add('select * from TITULOS (where NomTit = substring(cCadena FROM 1 FOR strlen(cCadena)))');

//Sustituir nChar por un número, con y sin los dos puntos, sin Parambyname, no funciona

//He declarado esto en la BD:
DECLARE EXTERNAL FUNCTION SUBSTR
CSTRING(80) CHARACTER SET ISO8859_1,
SMALLINT,
SMALLINT
RETURNS CSTRING(80) CHARACTER SET ISO8859_1 FREE_IT
ENTRY_POINT 'IB_UDF_substr' MODULE_NAME 'ib_udf';

//Ninguna de ellas funciona
end;
end;


Yo de SQL algo menos de lo justito y lo que he encontrado en el foro no me funciona, así que no soy capaz de solucionar el asunto.

Muchas gracias de antemano y un saludo.

roman
29-06-2012, 16:20:34
No veo que le pongas comodín a la consulta como en el primer caso:


// contiene cCadena
cCadena := '%' + cCadena + '%';

// Comienza con cCadena
cCadena := cCadena + '%';


// Saludos

Pedro-Juan
29-06-2012, 18:30:44
Hola, roman, muchas gracias, no funciona.

En el mensaje Dubugger Exception Notification dice ... Invalid token The SQL: select * from TITULOS where SUBSTRING(NomTit, 1, ?) = ?;'. Process ...

Ahora lo tengo así:


if (F_Main.sRG_BuscarTit.ItemIndex = 1) then begin
if (F_Main.sEdit_BuscarTit.Text <> '') then begin
cCadena := cCadena + '%';
DM_TitAnd_PUIP.Q_TITULOS.Close;
DM_TitAnd_PUIP.Q_TITULOS.SQL.Clear;
DM_TitAnd_PUIP.Q_TITULOS.SQL.Add('select * from TITULOS where SUBSTR(NomTit, 1, :nChar) = :cCadena');
DM_TitAnd_PUIP.Q_TITULOS.Parambyname('nChar').AsInteger := nChar;
DM_TitAnd_PUIP.Q_TITULOS.Parambyname('cCadena').AsString := cCadena;
DM_TitAnd_PUIP.Q_TITULOS.Open;
end
else ActualizarQueryTitulos;
end;


También he probado lo mismo con SUBSTRING:


DM_TitAnd_PUIP.Q_TITULOS.SQL.Add('select * from TITULOS where SUBSTRING(NomTit, 1, :nChar) = :cCadena');


Pero no funciona, ni con las otras opciones. Parece que los signos "?" del mensaje de error indiquen que no reconoce las variables, pero no lo sé.

Seguiré probando y buscando...

Gracias.

roman
29-06-2012, 19:14:20
Es algo extraño el error, pero lo cierto es que ahora que veo con más detalle, noto que estás usando el operador = en lugar de like como debería ser. Además, lo del substring no es necesario.

Veamos. Fíjate que en tu primer caso (que el campo contenga un texto determinado) tienes una consulta así (obviando la parte de mayúsculs/minúsculas):


select * from TITULOS where (NomTit like :cCadena)


Y que busque el texto contenido lo logras rodeando de comodines el parámetro:


ParamByName('cCadena').AsString := '%' + cCadena + '%':


Ahora bien, para el segundo caso (que el campo comience con un texto determinado) tu consulta puede ser la misma:


select * from TITULOS where (NomTit like :cCadena)


La diferencia está al sustituir el parámetro. Ahí sólo usas el comodín final:


ParamByName('cCadena').AsString := cCadena + '%':


Con esto no deberías tener problema.

// Saludos

Pedro-Juan
29-06-2012, 20:04:15
Muchas gracias roman, ya funciona. Ha quedado así:


if (F_Main.sCheckB_MayMinBuscarTit.Checked) then begin
cCadena := cCadena + '%';
DM_TitAnd_PUIP.Q_TITULOS.SQL.Add('Where (NomTit like :cCadena)');
DM_TitAnd_PUIP.Q_TITULOS.Parambyname('cCadena').AsString := cCadena;
end
else
DM_TitAnd_PUIP.Q_TITULOS.SQL.Add('where UPPER(NomTit) like ''' + AnsiUpperCase(cCadena) + '%''');


Qué claro cuando se sabe! :)

Un saludo.