Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   Usar Varios IBQuery en un IBDatabase (https://www.clubdelphi.com/foros/showthread.php?t=81548)

angel.sosa 23-11-2012 18:26:44

Usar Varios IBQuery en un IBDatabase
 
tengo un problema que no se como resolverlo.
Tengo Un IBdatabase1, un IBTransaction1, un IBQuery1, y un DataSorce1, estos dentro de un Form1, el IBQuery hace una consulta a un tabla de clientes la cual no tengo problema, pues se despliega dentro de un DBgrid. quiero dentro de esa mismo Form con una consulta de un IBQuery2 desplegar una lista de vendedores y asignarlo a un combobox.

Casimiro Notevi 23-11-2012 18:32:46

¿Y el problema?

angel.sosa 23-11-2012 18:55:36

q no tengo idea de como hacer para que yo pueda usar el otro query, es decir el query2. para ese ingrese otra IBtransaction2 apuntando al IBDatabase1.
corro el programa pero no consigo jalar los datos de esa tabla. ese el problema que no puedo hacer varios Query dentro de ese mismo Form. tengo que tener por cada consulta un Query y un Transaction, en un solo IBDatabase o uso varios por cada transaction.

con este codigo pretendo tener la lista de los vendedores es decir mi segunda consulta. pero no consigo jalar la informacion pues mi IBDatabase tiene por Default la Transaction1
Código Delphi [-]
IBTransaction2.Active := True;
IBQuery2.SQL.Clear;
IBQuery2.SQL.Add('select * from vendedores');
while not IBQuery2.Eof do
begin
  Combobox2.Items.Add(IBQuery2.Fields[0].Text);
 IBQuery2.Next;
end;
IBQuery2.Close;

Casimiro Notevi 23-11-2012 19:09:41

Puedes tener tantos ibquery como necesitas, cada uno con sus sentencias sql, y no necesitas tener otra transaction.

Código Delphi [-]
ibquery.close;
ibquery.sql.text := 'select nombre from vendedores';
ibquery.execquery;

Ya tienes todos los vendedores en el query, ahora haces lo que necesites con esos datos.

ecfisa 23-11-2012 19:18:01

Cita:

ese el problema que no puedo hacer varios Query dentro de ese mismo Form
Hola.

Sinceramente... yo tampoco veo el problema.

No hay inconveniente en hacer:
Código:

IBDatabase1 <-- IBTransaction1 <--+- IBQuery1
                                  |
                                  +- IBQuery2
                                  |
                                  +- IBQuery3
                                  ...

Y aunque lo creo innecesario, tambien podes:
Código:

IBDatabase1 <--+- IBTransaction1 <-- IBQuery1
              |
              +- IBTransaction2 <-- IBQuery2
              |
              +- IBTransaction3 <-- IBQuery3
              ...

Saludos.

angel.sosa 23-11-2012 20:12:10

pues uso este codigo al arrancar el form pero no consigo que me de informacion.
Sigue Vacio el ComboBox2, que es el q deberia darme los nombres de los vendedores.


Código Delphi [-]
//llenado de nombre de los vendedores
IBQuery2.Close;
IBQuery2.SQL.Clear;
IBQuery2.SQL.Add('select nombre from vendedores');
while not IBQuery2.Eof do
begin
  Form1.ComboBox2.Items.Add(IBQuery2.Fields[0].Text);
 IBQuery2.Next;
end;

Casimiro Notevi 23-11-2012 20:15:46

¿Pero tú has visto el código que te hemos puesto? :confused:

angel.sosa 23-11-2012 20:26:34

si Claro Casimiro. e leido lo que amablemente me responden, ya entendi que no necesito usar otra transaction y otro IBDatabase.

Del codigo lo pase a mi form, tube que modificar unas cosas porque no me dejaba ejecutarlo pero igual sigo sin ver informacion de la tabla.


Código Delphi [-]
ibquery2.close;
ibquery2.sql.text := 'select nombre from vendedores';
ibquery2.ExecSQL;

Casimiro Notevi 23-11-2012 21:01:18

Si estás usando un combobox "normal", entonces después de ejecutar el query es cuando debes pasarle los datos al mismo:

Código Delphi [-]
ibquery2.close;
ibquery2.sql.text:='select nombre from vendedores';
ibquery2.open;

while not ibquery2.eof do
begin
  combobox2.items.add( ibquery2.fieldbyname('nombre').asstring );
  ibquery2.next;
end;

angel.sosa 23-11-2012 21:40:14

OK, ya entendido. Muchisimas Gracias por la ayuda.

angel.sosa 23-11-2012 22:05:50

solo me resta ingresar 2 parametros fecha. que tengo en un Par de DateTimePiker los cuales pretendo ingresar dentro de un IBQuery3,
el problema es que el sql solo me reconoce el formato dd.mm.yyyy con el Edit2.Text y al querer sustituilo por el DataTimePiker.
me marca error "Token UKNOWn" pues al parecer mi version de DELphi solo me reconoce que le pase la fecha con punto ejemplo 23.11.2012 me manda error cuando entra 23/11/2012 pues el datatimepiker solo me arroja la fecha al leerlo con las "/"

este codigo pedazo de codigo es cuando uso el Text y si funciona.

Código Delphi [-]
IBQuery1.SQL.Add('on VE.cliente_id = cli.cliente_id  AND VE.fecha >='+Char(39)+Edit2.Text+Char(39));

lo pretendo sustituir con este codigo del DataTimePiker pero es cuando me marca el error.
el codigo es:
Código Delphi [-]
IBQuery1.SQL.Add('on VE.cliente_id = cli.cliente_id  AND VE.fecha >='+Char(39)+quotedstr(FormatDateTime('DDMMYYYY',DateTimePicker1.Date))+Char(39));

Casimiro Notevi 23-11-2012 22:27:18

Te aconsejo que uses parámetros, así nunca tendrás problemas de ese tipo, según tu ejemplo:

Código Delphi [-]
query.sql.text:='select ...... on ve.cliente_id=cli.cliente_id and ve.fecha >= :lafecha';
query.parambyname('lafecha').asdatetime := datetimepicker1.date;
query.open;

angel.sosa 12-12-2012 01:29:15

no puede adecuar tu respuesta Casimiro, pero tomando tu sugerencia, busque como resolverlo.
en realidad no pude hacer uso del método que la consulta es sumamente larga y mejor sustituí, las "." por "/". pues se me facilito de esta forma porque mi cosulta es bastante larga.

Código Delphi [-]
IBQuery1.SQL.Add('select LC.nombre_cliente, ...............................
IBQuery1.SQL.Add('ON CLI.cliente_id = C.cliente_id ');
IBQuery1.SQL.Add('inner join doctos_ve VE ');
IBQuery1.SQL.Add('on VE.cliente_id = cli.cliente_id  AND VE.fecha >='+Char(39)+(StringReplace(DateToStr(DateTimePicker1.Date),'/','.',[rfReplaceAll]))+Char(39)+' ');
IBQuery1.SQL.Add(' inner join condiciones_pago CPG ');
IBQuery1.SQL.Add('ON CPG.cond_pago_id = VE.cond_pago_id ');
IBQuery1.SQL.Add('inner JOIN vendedores ven ');
................................
perdon por no dar la solucion antes. andaba terminando el proyectito

ecfisa 12-12-2012 02:57:01

Cita:

Empezado por angel.sosa (Mensaje 451671)
no puede adecuar tu respuesta Casimiro...

Hola Angel.

Me alegra que hayas podido resolverlo y gracias por ponernos la solución.:)

Pero creo mas adecuado el modo que te sugirió Casimiro:
Código Delphi [-]
  with IBQuery1 do
  begin
    Close;
    SQL.Clear;
    SQL.Add('select LC.nombre_cliente, ...');
    SQL.Add('ON CLI.cliente_id = C.cliente_id ');
    SQL.Add('inner join doctos_ve VE ');
    SQL.Add('on VE.cliente_id = cli.cliente_id  AND VE.fecha >= :PFECHA');
    SQL.Add('inner join condiciones_pago CPG ');
    SQL.Add('ON CPG.cond_pago_id = VE.cond_pago_id ');
    SQL.Add('inner JOIN vendedores ven ');
    ParamByName('PFECHA').AsDate := DateTimePicker1.Date;
    Open;
  end;
Es mucho más seguro, entendible y menos propenso a equivocos.

Saludos.

Delphius 14-12-2012 23:02:34

Cita:

Empezado por ecfisa (Mensaje 450336)
Hola.

Y aunque lo creo innecesario, tambien podes:
Código:

IBDatabase1 <--+- IBTransaction1 <-- IBQuery1
              |
              +- IBTransaction2 <-- IBQuery2
              |
              +- IBTransaction3 <-- IBQuery3
              ...

Saludos.

Pues yo diría que esta opción es quizá más sana y segura para evitar conflictos sobre las transacciones. Por ejemplo, como cuando se tiene el error de que ya existe una transacción abierta.
Con esta forma uno puede dejar abierto varias transacciones individualmente en cuanto necesite. No está demás aclarar que tampoco es para dejarlas activas todo el tiempo, pero con esta manera si uno se es ordenado puede controlar mejor cada transacción posible de hacer en el sistema y tomar las acciones para el caso.
Pregunta: ¿Cómo le haces para detectar y discrimar cual de los tantos Datasets ligado a una única transacción es quien está en funciones y acaparando el uso de dicha transacción? ;)

Saludos,

Casimiro Notevi 14-12-2012 23:38:24

Cita:

Empezado por Delphius (Mensaje 451857)
Pregunta: ¿Cómo le haces para detectar y discrimar cual de los tantos Datasets ligado a una única transacción es quien está en funciones y acaparando el uso de dicha transacción? ;)

Código SQL [-]
ibquery3.transaction.commit;

Delphius 17-12-2012 13:09:44

Cita:

Empezado por Casimiro Notevi (Mensaje 451859)
Código SQL [-]
ibquery3.transaction.commit;

Se entiende que mi pregunta es cómo desde una transacción vas a distinguir cual de los datasets conectados a éste está es operación y haciendo uso del contexto. Se aprecia en tu código que estás haciendo lo opuesto, y lo que es peor, traspasando un mensaje por un intermedio y desobedeciendo la Ley de Demeter.
En términos reales y semánticos existen varias transacciones en una base de datos. Por tanto es natural y de esperarse que se requiera de mas de una transacción y no unicamente la de por “defecto“.

Casimiro Notevi 17-12-2012 13:18:34

Que exista más de una transacción no tiene nada que ver con el número de 'componentes Transaction'

Delphius 17-12-2012 15:42:14

Cita:

Empezado por Casimiro Notevi (Mensaje 451960)
Que exista más de una transacción no tiene nada que ver con el número de 'componentes Transaction'

Oh... claro que si. Puesto que el componente no es más que la abstracción de éstas.
El IBTransaction lo que hace es determinar si está activa alguna transacción para operar, y sólo puede atender una a la vez. Por tanto con un único componente tu aplicación sólo puede atender de a una transacción por vez. Que gracias al poder del aislamiento el componente es capaz de escuchar si hay otras transacciones, no quiere decir que no tenga que ver, sino que es necesario de esto para determinar si es una operación válida. Pero he aquí que esta capacidad sale fuera del concepto ya del módulo de datos... sino que se hace al nivel propio de la base de datos.
Que pueda escucharlas, no quiere decir que las administre a todas. Sólo puede trabajar con una y de a una por vez.
Cuando se requiere de más de una transacción activa (y los correspondientes datasets) (que hay casos en los que se requiere) no puedes administrarlas, en tu aplicación y en la capa de datos, con un único componente.

En tu ejemplo, si efectivamente dispones de un único componente para las transacciones entonces tu código puede limpiarse mejor y no hacer esos pasos intermedios de ir desde alguno de los datasets. Basta con hacer simplemente:

Código Delphi [-]
MiTransaccion.Commit;

Como he dicho, ¿Dado un componente IBTransaction, cómo puedes saber que dataset está haciendo uso y solicitando una operación?

Bien dices que si tienes, y sabes, que la operación X pasa por el dataset Y entonces puedes controlar el flujo del programa de la forma:

Código Delphi [-]
MiDataSet.Algo;

Cuando estás en una apreciación inversa, en donde por necesidad hay posiblemente más de una transacción activa (que se puede hacer), ¿Cómo vas a controlar cuál transacción y que dataset en cuestión está actuando?
Velo con un ejemplo: se ha detectado un error y la práctica indica que debe capturarse la debida excepción y actuar en consecuencia. Generalmente, cuando el contexto lo amerita se lanza una nueva excepción con la información adecuada al contexto para la siguiente capa (se lo conoce, por si no lo sabes, como el patrón "Convertir excepciones" o "Abstracción de Excepciones") (1). Puede ser de interés por tanto saber ante un error de operación, (además de dicha operación) que combinación de transacción y conjunto de datos están involucrados. Esto ayuda a aislar el problema y poder encontrar una solución más pronto.

(1) Un ejemplo de ésto sería algo como: EDatabaseError >> EContableOperationException >> ELibroDiarioException. Donde la excepción se va elevando e incorporando información adicional para el contexto... Tal es así que al final una ELibroDiarioExcepcion sabe que una operación contable no pudo efectuarse debido a un error de base datos.

Saludos,

Casimiro Notevi 17-12-2012 16:30:27

Hay una cosa clara: una gestión comercial completa con centenares de tablas, con más de cien conexiones constantes de usuarios, trabajando sin problemas... y con un solo componente TIBTransaction.
Ese es el método de trabajo que he llevado desde hace... muchos años, y nunca he tenido ningún problema, y siguen trabajando de esa forma.
En los distintos sitios que he trabajado, con distintos softwares, siempre se ha usado ese método, y todos siguen funcionando perfectamente.

Así que las "explicaciones de libro" que das... no sé si son alejadas del mundo real o, simplemente, no entiendo qué quieres decir.


La franja horaria es GMT +2. Ahora son las 12:01:50.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi