PDA

Ver la Versión Completa : Ayuda con una busqueda


servicomp
16-11-2009, 17:04:50
Cordial saludo

Estoy trabajando en D2007 y usando Firebird 2.1, como sistema de conexión de la base de datos estamos usado IBX (IBDatabase, IBTransaction, IbDataset y un DataSource). Creamos una Tabla pequeña para hacer los estudios de práctica usando un gestor de las tantos que recomiendan en las páginas quedando la estructura asi:

CREATE TABLE "FAMILIA"
(
"IDENTIFICACION" INTEGER NOT NULL,
"NOMBRE" VARCHAR(20) NOT NULL,
"APELLIDOUNO" VARCHAR(20) NOT NULL,
"APELLIDODOS" VARCHAR(20) NOT NULL
);

Hemos creado un procedimiento para capturar la información a esta tabla de manera manual o por software, sin usar un DBGrid, el cual me ha funcionado muy bien usando el siguiente codigo

procedure TFManual.Button2Click(Sender: TObject);
begin
Datamodule1.IBDataSet1.Append; {para insertar datos al final}
Datamodule1.IBDataSet1.FieldByName('IDENTIFICACION').AsInteger:=StrToInt(edit1.Text); {primer edit}
Datamodule1.IBDataSet1.FieldByName('NOMBRE').AsString:=Edit2.Text;
Datamodule1.IBDataSet1.FieldByName('APELLIDOUNO').AsString:=Edit3.Text;
Datamodule1.IBDataSet1.FieldByName('APELLIDODOS').AsString:=Edit4.Text;
Datamodule1.IBDataSet1.Post;
Datamodule1.IBTransaction1.CommitRetaining;
Edit1.Text:='';
Edit2.Text:='';
Edit3.Text:='';
Edit4.Text:='';
Edit1.SetFocus;
end;

Hasta el momento no hay problema, pero necesitamos que al ingresar el campo IDENTIFICACION, este sea unico, o en otras palabras, que busquemos el valor de este campo y si se encuentra, lo mostremos en pantalla para que no se repita.

Hemos tratado con este codigo usando un IBQuery, pero no se si lo estamos haciendo bien, o es la forma correcta de hacerlo, por eso solicito su colaboración para resolver esta duda.

El codigo que estamos usando es el siguiente

procedure TFBusqueda.Button2Click(Sender: TObject);
begin
IBQ1.Close;
IBQ1.open;
IBQ1.Active;
IBQ1.SQL.Add('SELECT * FROM FAMILIA WHERE IDENTIFICACION='+Edit1.Text);
IBQ1.ExecSQL;
if (IBQ1.RecordCount=0) then
begin
Application.MessageBox('No se encuentra el registro buscado','Mensaje de Busqueda',0);
IBQ1.Close;
end
else begin
Edit2.Text:=inttostr(IBQ1.FieldByName('IDENTIFICACION').AsInteger);
Edit3.Text:=IBQ1.FieldByName('NOMBRE').AsString;
Edit4.Text:=IBQ1.FieldByName('APELLIDOUNO').AsString;
Edit5.Text:=IBQ1.FieldByName('APELLIDODOS').AsString;
Edit1.Text:='';
Edit1.SetFocus;
IBQ1.Close;
end;

De antemano gracias por su colaboración

Neftali [Germán.Estévez]
16-11-2009, 17:16:47
Si queréis que ese campo sea único, posiblemente deberíais definirlo como clave primaria o asignarle un índice único. Eso aseguraría la "unicidad" y aceleraría considerablemente las búsquedas.

En cuanto al código de búsqueda, te sobran el Active y el ExecSQL; Basta con que dejes el Open para recuperar el registro.

juanelo
16-11-2009, 17:32:26
Complementando lo que dice Neftali, en los componentes IBX ya no funciona de manera "tradicional" el RecordCount, de hecho para estos componentes esa propiedad tiene cero como valor default, tendrias que ejecutar la funcion FetchAll para que te de el numero de registros, pero esto puede ser altamente ineficiente en terminos de tiempo, para eso te recomendaria mejor una sentencia del tipo:
Select count(ID) as Cuantos from Tabla where ID=:ID
Otra es como dice Neftali, agrega un indice unico y deja al manejerador y al mismo delphi te arroje el error causado por el intento de duplicar una llave.
Saludos.

servicomp
16-11-2009, 19:48:08
Amigos les cuento que si coloco una llave primaria, solo recibire la interrupción del motor de bases de datos cuando haga el Commit, lo ideal es hacer la consulta antes de continuar con la captura de los datos.

Ya tengo la consulta de mi TBIquery, pero no se si el dato esta o no debido a que el RecorCount, siempre me da el valor por defecto que es cero


Agradeciendo de antemano

juanelo
17-11-2009, 03:11:14
Complementando lo que dice Neftali, en los componentes IBX ya no funciona de manera "tradicional" el RecordCount, de hecho para estos componentes esa propiedad tiene cero como valor default, tendrias que ejecutar la funcion FetchAll para que te de el numero de registros, pero esto puede ser altamente ineficiente en terminos de tiempo, para eso te recomendaria mejor una sentencia del tipo:
Código SQL [-] (http://www.clubdelphi.com/foros/#)Select count(ID) as Cuantos from Tabla where ID=:ID

Otra es como dice Neftali, agrega un indice unico y deja al manejerador y al mismo delphi te arroje el error causado por el intento de duplicar una llave.
Saludos.
Amigos les cuento que si coloco una llave primaria, solo recibire la interrupción del motor de bases de datos cuando haga el Commit, lo ideal es hacer la consulta antes de continuar con la captura de los datos.

Ya tengo la consulta de mi TBIquery, pero no se si el dato esta o no debido a que el RecorCount, siempre me da el valor por defecto que es cero


Agradeciendo de antemano
:rolleyes:

Luis F. Orjuela
17-11-2009, 16:01:13
Hazlo así y me cuentas si te funciona.....


procedure TFBusqueda.Button2Click(Sender: TObject);
begin
IBQ1.Close;
IBQ1.Active;
IBQ1.SQL.Add('SELECT * FROM FAMILIA WHERE IDENTIFICACION=:NIT');
IBQ1.ParambyName('NIT').AsInteger:=StrtoInt(Edit1.Text);
IBQ1.Open;
IBQ1.ExecSQL;
if (IBQ1.IsEmpty) then
begin
Application.MessageBox('No se encuentra el registro buscado','Mensaje de Busqueda',0);
IBQ1.Close;
end
else begin
Edit2.Text:=inttostr(IBQ1.FieldByName('IDENTIFICACION').AsInteger);
Edit3.Text:=IBQ1.FieldByName('NOMBRE').AsString;
Edit4.Text:=IBQ1.FieldByName('APELLIDOUNO').AsString;
Edit5.Text:=IBQ1.FieldByName('APELLIDODOS').AsString;
Edit1.Text:='';
Edit1.SetFocus;
IBQ1.Close;
end;


Descripción de las siguientes instrucciones:
IBQ1.SQL.Add('SELECT * FROM FAMILIA WHERE IDENTIFICACION=:NIT');
:NIT (Es la forma en que se pasa un parámetro a un script SQL.

IBQ1.ParambyName('NIT').AsInteger:=StrtoInt(Edit1.Text);
En este punto es donde se pasa el valor al parámetro, y como el campo 'IDENTIFICACION' está definido como INTEGER, pués así es la forma, y claro, debemos hacer un cast a tu Edit1.Tex, es decir, convertirlo en entero.

Y por último :
if (IBQ1.IsEmpty) then

Se está preguntando que si la consulta anterior es vacía, en tal caso muestras tu mensaje o de lo contrario das de alta tu nuevo registro.


Un caluroso saludo..

Luis F. Orjuela
17-11-2009, 16:02:47
Quítale la instrucción:

IBQ1.ExecSQL;

Pues sobra....