lunes, 24 de septiembre de 2018

¿Cómo usar dos tablas de distintas bases de datos en la misma consulta?

Para adjuntar una tabla a un DataSet, en este caso TZQuery, y que no produzca un error, la solución que no encontré en ningún lado, la descubrí mediante el sistema de prueba y error hasta que salga. Y como suele suceder cuando no se encuentra algo en toda la web, es porque ese algo, es muy obvio y este caso no fue la excepción.

Primero establecemos la conexión con una de las dos bases de datos mediante el componente TZConnection. Luego hacemos una consulta para adjuntar la base de datos, la abrimos y la cerramos, listo, ya está adjuntada. Luego escribimos la consulta que necesitemos.

Ejemplo:

ZQ.Close;
ZQ.SQL.Text:='ATTACH DATABASE '+QuotedStr(strDB)+' AS realgestdb;';
ZQ.Open;
ZQ.Close;
ZQ.SQL.Text:='SELECT cfecha, cprovid, nombre, ccomp, realgestdb.comprob.ccomprobalias, cletracomp, '+
'cnrocomp, ccaeocai, ccai, cuit, cnetogravado, cnogravado, cimpinternos, cpercib, cperciva, ctasaiva, '+
'civa, cnetogravado1, ctasaiva1, civa1, cnetogravado2, ctasaiva2, civa2, ctotal '+
'FROM ccompras '+
'INNER JOIN cprov ON cprovid=provid '+
'INNER JOIN realgestdb.comprob ON ccomp=realgestdb.comprob.id '+
'WHERE cfecha BETWEEN '+QuotedStr(desde)+' AND '+QuotedStr(hasta)+
'ORDER BY cfecha, cprovid ;';
ZQ.Open;


Las tres primera lineas realizan el ATTACH DATABE y ya queda disponible para cualquier consulta que se realice en el mismo dataset, hasta que se des adjunte, para ello:

ZQ.Close;
ZQ.SQL.Text:='DETACH DATABASE '+QuotedStr('realgestdb')+';';
ZQ.Open;
ZQ.Close;


Es importante para adjuntar, enviar el path completo de la base de datos y entre comillas simples, para eso nada más cómodo que la función QuotedStr. En este caso strDB es una variable del tipo string que contiene el path completo de la base de datos a adjuntar. Luego con AS le establecemos un alias para luego referenciarla en las consultas SQL. El alias puede ser cualquier nombre.
Pero ojo, que para realizar el DETACH DATABASE se utiliza el Alias, no el path completo de la base de datos. Esto se debe que, al menos SQLite, permite adjuntar variar veces una misma base de datos bajo distintos Alias (AS).

La cuarta línea cierra la consulta. La quinta, cambia la consulta y para acceder al campo ccomprobalias de la tabla comprob de la base de datos adjuntada bajo el alias de realgestdb lo hacemos de la forma Alias.tabla.campo.

LazReport: cambiar el alto de una banda en tiempo de ejecución.


En este caso se trata de un reporte del libro I.V.A. y necesito cambiar el alto de la banda de los datos maestros según tengan 1, 2 o 3 discriminaciones o tasas de IVA en un mismo comprobante, para no desperdiciar espacio, entonces si un comprobante tiene un solo IVA el alto (height) será de 15, si son dos, será de 30 y si son tres será de 45 pixeles.
Como se ve en la imagen, durante el diseño del reporte se toma el máximo, será luego en run time que variará el valor de la banda MasterData1.

Para ello nos valemos del evento del reporte TfrReport OnBeginBand y su nombre lo indica todo: tareas a realizar al comienzo de la banda. Lo resolví muy simple de la siguiente manera:

procedure TFLibCompras.frRepBeginBand(Band: TfrBand);
begin
if ((Band.Name='MasterData1') and (ZQ.FieldByName('cnetogravado2').AsCurrency<>0)) then
  begin
    Band.Height:=45;
    Exit;
end;
if ((Band.Name='MasterData1') and (ZQ.FieldByName('cnetogravado1').AsCurrency<>0)) then
  begin
    Band.Height:=30;
    Exit;
  end;
if ((Band.Name='MasterData1') and (ZQ.FieldByName('cnetogravado1').AsCurrency=0)) then
  begin
    Band.Height:=15;
    Exit;
  end;
end;


El código es el que tengo funcionando y lo expongo a modo de ejemplo, la condición para establecer el alto de la banda puede ser cualquiera. También en el mismo evento podrían modificarse otros componentes del reporte.


Y así queda parte del reporte, con valores de prueba.