PDA

Ver la Versión Completa : Tantos TQuery como consultas deseo?


Pollo2004
22-10-2008, 20:15:39
Hola a todos nuevamente, sigo muy agradecido por toda la ayuda brindada por el foro, y deseo mucho algun dia poder colaborar de la misma manera q lo hacen ustedes.
Estoy queriendo aprender un poco de SQL y mi pregunta es esta. yo a una tabla le puedo hacer muchas consultas, pongamos un ejemplo
Tengo una tabla de productos, y quiero buscar uno, tambien quiero controlar q ningun producto tenga stock= 0 y alguna otra q ustedes se imaginen.

otro ejemplo:
O buscar un producto por nombre, o codigo, o lo q fuese, tengo q poner un TQuery para cada busqueda y activar cada query con una accion de un boton o de otro componente.

Como seria la cosa?

Sigo usando paradox 7!
Gracias!

enecumene
22-10-2008, 20:47:57
Hola, no amigo no es necesario un TQuery por cada búsqueda, con uno basta ejemplo:

if ComboBox1.Text = 'Codigo' then
begin
Query1.Close;
Query1.SQL.Clear;
Query1.SQL.Text := 'select * from tabla where codigo = '12345'';
Query1.Open;
end;
if ComboBox1.Text = 'Nombre' then
begin
Query1.Close;
Query1.SQL.Clear;
Query1.SQL.Text := 'select * from tabla where Nombre = 'Pedro'';
Query1.Open;
end;
if ComboBox1.Text = 'Producto' then
begin
Query1.Close;
Query1.SQL.Clear;
Query1.SQL.Text := 'select * from tabla where producto = 'Jabon'';
Query1.Open;
end;

en este ejemplo estoy usando un sólo Query.

Saludos.

roman
22-10-2008, 20:54:51
Yo creo que es cuestión de organización. Si vas a usar un solo query para todas las consultas, posiblemente signifique o implique que vas a tener tus consultas desperdigadas por todo el código. Puede ser preferible tener las partes limpiamente separadas.

// Saludos

ContraVeneno
22-10-2008, 20:56:33
with UnQuery do begin
If active then close;
SQL.Clear;
SQL.Add('Select LosCampos ');
SQL.Add('From UnTabla');
Case ComboBox1.ItemIndex Of Begin
0: SQL.Add('Where Codigo = :Valor ');
1: SQL.Add('Where Nombre = :Valor ');
2: SQL.Add('Where Producto = :Valor ');
end; //Case
ParamByname('Valor').AsString := UnEdit.Text;
Open;
end; //with

coso
22-10-2008, 21:26:55
q.Active := false;
q.SQL.Text := 'select * from tabla where ' + ComboBox.Text + ' = ' + QuotedStr(edit.text);
q.Active := true;

:D

AzidRain
22-10-2008, 22:10:42
Puedes hacer un solo query para consultar por uno o varios campos así:


q.SQL.Add('select * from productos where (:clave is null or clave=:clave) AND (:nombre is null or nombre like :nombre) OR (:stock is null or stock>=:stock) ');





Solo tienes que llenar los parámetros según requieras, si no llenas ninguno te va a traer todos los registros. Esta es una forma muy sencilla de hacer combinaciones de condiciones y utilizas un solo query. De esta manera podrias traer por ejemplo: todos los productos que contengan "PRO" en su nombre y que tengan stock de mas de 10.
Para ello llenamos los parametros así:


q.parambyName('nombre').AsString := '%PRO%';
q.ParamByName('stock').AsInteger := 10;

ContraVeneno
22-10-2008, 22:20:11
tómala, jejeje :D

rgstuamigo
22-10-2008, 23:55:29
Ja,jaa,jaa,ja,ja,jaa:D:D, me sorprendieron:eek:.
Esta muy bueno, es lo que necesitaba tambien......;).

Pollo2004
23-10-2008, 01:36:06
Ahora manos a la obra y analizar y probar las soluciones q brindaron para ver cual es la q mas se adecua a mi situacion.
Cualquier sugerencia por favor, estaria bueno q la sigan posteando!
Gracias, salu2!!

coso
23-10-2008, 12:04:32
te explico como trabajo yo : tengo ciertas querys generales que son las ligadas a las dbgrids. En ellas aplico los filtros necesarios etc, con nombres bien distinguibles (dmsrc.queryClientes,etc...). Para todas las otras operaciones (pasar datos de una a otra, encontrar un identificador concreto, cambiar campos relacionados etc...) entonces creo otra query correspondiente en la misma funcion en que se hace la operacion. Asi siempre tengo las querys 'visibles' mas o menos controladas. Es una manera personal, claro. Cada uno tiene la suya.

roman
23-10-2008, 16:13:42
Concuerdo con lo que comenta coso y a eso me refería. Intentar reutilizar un sólo query para todas las consultas, tarde o temprano lleva a confusión.

Otra cosa. Acabo de probar la propuesta de AzidRain, y si bien me funciona con MySQL usando las componentes MyDAC, no así con Paradox usando el BDE. La consulta marca el error de "Type mismatch in expression" tanto si le paso valor al parámetro como si no.

// Saludos

marcoszorrilla
23-10-2008, 17:05:56
Yo utilizo una opción mixta, para los casos particulares utilizo un Tquery para cada consulta incluso con campos persistentes. Pero para cosas generales como conteos, sumas, búsquedas...

Utilizo un Tquery sin campos ni contenido alguno y construyo por código el SQL que en cada momento necesito.


Un Saludo.

BlueSteel
23-10-2008, 17:28:28
Yo soy partidario de crear consultas específicas y otras generales...

por ejemplo, mis diseños tiene en un Form la opción de mostrar un registro, agregar, eliminar y actualizar....

para esos tipos de Formularios siempre utilizo 3 consultas...

Como trabajo con ADO, las pondré así

1.- AQ_Select -> con la cual realizaré una selección de todos o parte de los registros
2.- AQ_Edit -> con la cual realizaré una inserción y/o eliminación
3.- AQ_Actualiza -> con la cual realizaré una actualización de un registro


Ahora, si necesito algo más específico, pongo tantas consultas como sea necesario y reutilizandolas al máximo....(tambien me debo acordar de lo que uso...)

bueno, si me baso en lo que dije, en un sistema donde tengo Clientes, Productos, Proveedores, Vendedores, Centros de Costos, y otros similares.... si bien es información diferente, con las 3 consultas anteriores cubro todas las consultas para cada uno de los Formularios...


Bueno, al menos así lo hago yo..

Salu2:p:D

elcolo83
23-10-2008, 19:36:48
Hola a todos... Yo en mi caso ahora estoy provando una nueva forma de organizarme... vamos a ver como ve con esto...
Uso los componentes IBX y Firebird; lo que hago basicamente es crear un conjunto de componentes (TIBTransaction y TDBDataSet) por cada tabla automaticamente con la funcion CrearCompDB, el cual el mismo me genera el codigo SQL básico para editar, insertar, borrar y actualizar registros (ya que es muy tedioso hacerlo cuando tenes muchas tablas :p) cada conjunto de componentes es usado por lo modulos que editan sus datos.
Ademas tengo un modulo para busqueda simple el cual arma la consula dependiendo de la tabla que se vaya a consultar y muestra los campos en un grid, el cual abre el modulo correspondiente a la tabla que se esta consultando cuando se hace doble click en un registro del resultado...

En fin... no soy muy amigo de lo estatico y prefiero que el programa vaya armando y manipulando las consultas y componentes que se conectan segun la demanda del usuario.... Claro que hay que tener cuidado con el codigo para no consumir mas recursos de los necesarios.

La funcion que uso para crear los componentes y el codigo SQL basico


Procedure CrearCompDB(S:String; DB_: TIBDataBase);
var
TR: TIBTransaction;
DS: TIBDataSet;
I: Integer;
begin
//S es el nombre de la tabla a la cual se quiere conectar//
S:= UpperCase(S);


TR:= TIBTransaction.Create(Application);
TR.DefaultDatabase:= DB_;
TR.Name:= 'TR'+S;

DS:= TIBDataSet.Create(Application);
DS.Database:= DB_;
DS.Transaction:= TR;

DB.GetFieldNames(S, L.Lines);

DS.SelectSQL.Clear;
DS.SelectSQL.Add('Select * from '+S);

DS.InsertSQL.Clear;
DS.InsertSQL.Add('INSERT INTO '+S+' (');
for I := 0 to L.Lines.Count - 1 do
begin
if i<(L.Lines.Count-1) then
DS.InsertSQL.Add(L.Lines[i]+',')
else DS.InsertSQL.Add(L.Lines[i]+')');
end;
DS.InsertSQL.Add('VALUES (');
for I := 0 to L.Lines.Count - 1 do
begin
if i<(L.Lines.Count-1) then
DS.InsertSQL.Add(':'+L.Lines[i]+',')
else DS.InsertSQL.Add(':'+L.Lines[i]+')');
end;

DS.ModifySQL.Clear;
DS.ModifySQL.Add('UPDATE '+S+' SET');
for I := 0 to L.Lines.Count - 1 do
if L.Lines[i]<>'ID' then
begin
if i<(L.Lines.Count-1) then
DS.ModifySQL.Add(L.Lines[i]+' = :'+L.Lines[i]+',')
else DS.ModifySQL.Add(L.Lines[i]+' = :'+L.Lines[i]);
end;
DS.ModifySQL.Add('where ID= :OLD_ID');

DS.DeleteSQL.Clear;
DS.DeleteSQL.Add('DELETE FROM '+S+' WHERE ID = :OLD_ID');

DS.RefreshSQL.Add('SELECT * FROM '+S+' WHERE ID = :ID');
try
DS.Active:= True;
except
on e:exception do
ShowMessage(e.Message);
end;
DS.Name:= 'DS'+S;
DS.AfterPost:= Commit;
DS.OnPostError:= IBDataSet1.OnPostError;

DSw.DataSet:= TDataSet(Application.FindComponent('DS'+S));
DS.Active:= True;
end;



Saludos a todos

AzidRain
23-10-2008, 19:53:33
Roman en el caso del BDE, me parece que hay que construir y definir los parámetros previamante. Tanto MyDAC como Zeos hacen la conversión de tipos al vuelo y no requieren que se los definas previamente. Checalo.

roman
23-10-2008, 20:03:45
Creo que no Azid. Si quito la parte de


:param is null


funciona bien sin necesidad de definir los parámetros. El tipo de datos se determina cuando usas ParamByName(...).AsXXX

Si asigno previamente el tipo de datos, sigue marcando el error.

// Saludos

roman
23-10-2008, 20:33:50
elcolo83:

Tu idea es muy buena, pero quizá estás reinventando la rueda. Me explico:

No sé cómo funcionen los componentes IB, pero en otros similares, si pones una sentencia como esta:


select * from tabla where id = :id


en la propiedad SQL, puedes hacer inserciones, actualizaciones y supresiones sin necesidad de especificar nada más. Incluso, por ejemplo, si modificas un registro, el SQL que se genera incluye sólo los campos modificados, mientras que como lo haces, siempre se incluyen todos.

Más aún. Si sigues el truco de AzidRain y pones la sentencia


select * from tabla where id = :id or :id is null


entonces también te sirve para hacer selecciones.

Las propiedades InsertSql, UpdateSql y DeleteSql, creo que están más para casos en que se involucren varias tablas y la sentencia SQL adecuada no pueda deducirse en automático.

// Saludos

elcolo83
23-10-2008, 22:10:53
Roman


Sinceramente nunca habia provado la sentencia con los IBX, mañana lo provare... si anda, seria genial ya que eliminaria la parte del codigo que me genera el codigo sql solo dejaria las lineas que crean los componentes para que mi sistema funcione...
Muy buena data... gracias, despues te cuento como me fue :)