PDA

Ver la Versión Completa : varias dudas sobre consultas y refresco de datos


Giniromero
26-02-2004, 10:41:00
Hola,

Estoy usando delphi 6 e interbase 7, uso consultas sobre
las tablas mediante tIBdataset.

Tengo varias dudas, respecto a optimización del código.

1)Si tengo una tabla X, (consulta sql en TIBDataSet), que
sólo me muestra un registro por vez, y del valor que hay
en uno de los campos de ese registro, (CampodeX),
dependen los registros que se muestran en otras tantas
tablas, (también consulta sql en TIBDataSet donde
campo=:CampodeX). ¿hay alguna manera de que se
actualicen los registros que se muestran en esta tablas que
dependen de X, sin tener que abrir y cerrarlas, cada vez
que cambiemos el registro de la tabla principal X?


2)Cuando en un código como el siguiente,



var str : String;
var dbpos: TBookMark;
begin
TRY
dbPos := TbEcono.GetBookmark;
TbEcono.DisableControls;
TbEcono.Close;
TbEcono.SelectSQL.Clear;
TbEcono.SelectSQL.Add(VEconoSQL);
try
TbEcono.Open;
except
on E: Exception do begin
//guardamos en variable "str" el mensaje que
queremos se muestre
str := 'Error abriendo TbEcono con el mensaje : '
+ E.Message;
Application.MessageBox(PChar(str), 'Atención',
MB_OK);
end;
end;
FINALLY
TbEcono.GotoBookmark(dbpos);
TbEcono.FreeBookmark(dbpos);
TbEcono.EnableControls;
FrmFxMain.SpeedSaldo.Click;

END;


¿Es normal que, si esta tabla está mostrando sus datos en
un dbgrid o un campo dbedit, y al ejecutar este código, si
devuelve registros distintos a los que había inicialmente,
no se refresquen esos cambios en los dbgrid y los dbedit a
los que está conectado, poniendo los nuevos en vez de
mantener los viejos datos, a no ser que después cerremos
y abramos esta tabla?


3)¿Es normal que al añadir un procedimiento a mi
aplicación se relentice mucho la apertura del programa?

Gracias, de antemano, a tod@s por la ayuda.

Virginia

__cadetill
26-02-2004, 12:48:48
Hola Virginia


1)...¿hay alguna manera de que se
actualicen los registros que se muestran en esta tablas que
dependen de X, sin tener que abrir y cerrarlas, cada vez
que cambiemos el registro de la tabla principal X?

haciendo relaciones de maestro/detalle??? No se si es esto a lo que te referias


2)....¿Es normal que, si esta tabla está mostrando sus datos en
un dbgrid o un campo dbedit, y al ejecutar este código, si
devuelve registros distintos a los que había inicialmente,
no se refresquen esos cambios en los dbgrid y los dbedit a
los que está conectado, poniendo los nuevos en vez de
mantener los viejos datos, a no ser que después cerremos
y abramos esta tabla?

No, debería de actualizar automáticamente. Lo que no entiendo es que, si cambias la sentencia SQL, para que quieres los BookMark??? Estos te servirían si no cambiaras la sentencia SQL, pero al cambiarla, la referencia de éste seguramente no será válida


3)¿Es normal que al añadir un procedimiento a mi
aplicación se relentice mucho la apertura del programa?

aquí si que no te he entendido :(

Giniromero
26-02-2004, 15:17:41
Hola,



haciendo relaciones de maestro/detalle??? No se si es esto a lo que te referias




Si, están vinculadas las tablas mediante relaciones maestro detalle.

Lo que no entiendo es que, si cambias la sentencia SQL, para que quieres los BookMark??? Estos te servirían si no cambiaras la sentencia SQL, pero al cambiarla, la referencia de éste seguramente no será válida


Es que, aunque cambie de código, no tienen que cambiar siempre los registros, y en caso de que no cambien, me interesaba que se mantuviese en el mismo registro.
Si quitase esto, ¿se me actualizarían automática todos los TIbDataSet, mostrandome los registros relacionados con el de mi tabla principal automáticamente, sin tener que pedirles que se cierren antes de que cambie el registro esa tabla principal, y se abran después?, por que si es así, me planteo el código de otra forma.



3)¿Es normal que al añadir un procedimiento a mi
aplicación se relentice mucho la apertura del programa?

Tal vez me expliqué mal.

Quiero decir, que si es normal, que al hacer consulta SQL en la aplicación, usando en vez de a una tabla de mi base de datos, a un procedimiento de la misma, es normal que tarde tanto en abrirse la aplicación, o abrirse esa tabla.


Muchas gracias por todo,

Virginia

__cadetill
26-02-2004, 15:33:23
Hola de nuevo Virginia

1.- Pues si lo tienes en relación de maestro/detalle, deberían actualizarse los demas TIBDatasets son necesidad de un Close/Open :confused:

2.- Yo creo que la actualización o no de los componentes DataAware no tiene nada que ver con el BookMark, pero podrías pobarlo. No obstante, éstos deberían de actualizarse solitos al hacer el Open del TIBDataSet

3.- Bueno, todo depende de lo que haga ese procedimiento. Si ha de hacer muchas cosas, pues sí, pero si es algo sencillo, debería ir ligero :rolleyes:

Giniromero
26-02-2004, 16:35:21
Hola,



3.- Bueno, todo depende de lo que haga ese procedimiento. Si ha de hacer muchas cosas, pues sí, pero si es algo sencillo, debería ir ligero :rolleyes:


El procedimiento es el siguiente, el cual ya puse en otro hilo por otro tema:

CREATE PROCEDURE PROECONOPAGO
RETURNS (
CODIGO INTEGER,
NUMALU SMALLINT,
NUMGRUP SMALLINT,
FECHA TIMESTAMP,
ASIENTO INTEGER,
CONCEPTO VARCHAR(50),
IMPDEBE NUMERIC(15,2),
IMPHABER NUMERIC(15,2),
FORPAGO SMALLINT,
RECIBO VARCHAR(10),
FACTURA VARCHAR(10),
USUARIO VARCHAR(10),
TIPO VARCHAR(1),
EMPRESATXT VARCHAR(1),
CONTROL VARCHAR(1))
AS
DECLARE VARIABLE VCODIGO INTEGER;
DECLARE VARIABLE VNUMALU SMALLINT;
DECLARE VARIABLE VNUMGRUP SMALLINT;
DECLARE VARIABLE VFECHA TIMESTAMP;
DECLARE VARIABLE VASIENTO INTEGER;
DECLARE VARIABLE VCONCEPTO VARCHAR(50);
DECLARE VARIABLE VIMPDEBE NUMERIC(15,2);
DECLARE VARIABLE VIMPHABER NUMERIC(15,2);
DECLARE VARIABLE VFORPAGO SMALLINT;
DECLARE VARIABLE VRECIBO VARCHAR(10);
DECLARE VARIABLE VFACTURA VARCHAR(10);
DECLARE VARIABLE VUSUARIO VARCHAR(10);
DECLARE VARIABLE VTIPO VARCHAR(1);
DECLARE VARIABLE VPRODUCTOGRUP VARCHAR(2);
DECLARE VARIABLE VEMPRESAPRO VARCHAR(1);
DECLARE VARIABLE VCONTROL VARCHAR(1);
begin
for select CODIGO, NUMALU, NUMGRUP, FECHA, ASIENTO, CONCEPTO, IMPDEBE,
IMPHABER, FORPAGO, RECIBO, FACTURA, USUARIO, TIPO

from ECONO

order by numalu
into
:VCODIGO,:VNUMALU,:VNUMGRUP,:VFECHA,:VASIENTO,:VCONCEPTO,:VIMPDEBE,
:VIMPHABER, :VFORPAGO,:VRECIBO,:VFACTURA,:VUSUARIO,:VTIPO do
begin
select PRODUCTO from grupos where NUMGRUP =:vnumgrup into :vproductogrup ;
select EMPRESA from produ where PRODUCTO=:vproductogrup into :vempresapro;

If (:vasiento <2 AND :vimpdebe <> 0 ) Then Begin

CODIGO = :VCODIGO;
NUMALU = :VNUMALU;
NUMGRUP = :VNUMGRUP;
FECHA = :VFECHA;
ASIENTO = :VASIENTO;
CONCEPTO = :VCONCEPTO;
IMPDEBE = :VIMPDEBE;
IMPHABER = :VIMPHABER;
FORPAGO = :VFORPAGO;
RECIBO = :VRECIBO;
FACTURA = :VFACTURA;
USUARIO = :VUSUARIO;
TIPO = :VTIPO;
EMPRESATXT = :vempresapro;
CONTROL = :vcontrol;
suspend;
end
end
end


¿Esto se un procedimiento muy complicado?


1.- Pues si lo tienes en relación de maestro/detalle, deberían actualizarse los demas TIBDatasets sin necesidad de un Close/Open :confused:


Pues, por algún motivo que no termino de determinar, cuando cambio el registro principal, los registros que me tienen que mostrar el resto de las tablas, dependientes de esta, no se actualizan. Me siguen mostrando los registros para el valor anterior de la tabla principal.



2.- Yo creo que la actualización o no de los componentes DataAware no tiene nada que ver con el BookMark, pero podrías pobarlo. No obstante, éstos deberían de actualizarse solitos al hacer el Open del TIBDataSet


¿Tal vez no tenga que ver tanto con los bookmark como con los disable control?

No sé, he tenido que poner código extra que sé me relentiza la aplicación para asegurarme de cerrar y abrir despues las tablas, pero necesito solucionar esto, para que no me de problemas de lentitud.

GRacias

virginia

__cadetill
26-02-2004, 18:41:09
¿Esto se un procedimiento muy complicado?


Pues no, no parece demasiado complicado. Ahora bien, todo depende del número de registros de las tablas, de una buena definición de índices y de la velocidad de acceso (que creo recordar era el problema del otro hilo)


Pues, por algún motivo que no termino de determinar, cuando cambio el registro principal, los registros que me tienen que mostrar el resto de las tablas, dependientes de esta, no se actualizan. Me siguen mostrando los registros para el valor anterior de la tabla principal.


Pues establecer una relación maestro/detalle con los TIBDataSet no es demasiado complejo (creo recordar que lo discutimos en su día), pero básicamente es establecer la propiedad DataSource del detalle apuntando al TDataSource del maestro y poner los parámetros en la sentencia SelectSQL del detalle


¿Tal vez no tenga que ver tanto con los bookmark como con los disable control?
Prueba a quitar ambas cosas a ver que resultado optienes

Giniromero
26-02-2004, 19:55:23
Pues no, no parece demasiado complicado. Ahora bien, todo depende del número de registros de las tablas, de una buena definición de índices y de la velocidad de acceso (que creo recordar era el problema del otro hilo)


El nº de registros resultante en esta tabla es + o - 300 registros, la tabla original es muy grande, de ahí mi interes en el procedure, para reducir todo lo posible la tabla, para hacer este calculo más rápido. Lo que si es cierto es que podría intentar acotar aun más los registros resultantes, metiendo un parametro input en el que le pase el número de cliente por el propio procedure. Al principio lo tenía así, pero como me daba problemas para poner el procedure en marcha, decidí hacerlo más sencillo, y cuando ese funcionase, pasarle ese parametro.



Pues establecer una relación maestro/detalle con los TIBDataSet no es demasiado complejo (creo recordar que lo discutimos en su día), pero básicamente es establecer la propiedad DataSource del detalle apuntando al TDataSource del maestro y poner los parámetros en la sentencia SelectSQL del detalle


Si, así es como lo tengo, tuve un buen profe, :D :p no creo que vaya por ahí el problema.


Prueba a quitar ambas cosas a ver que resultado optienes

Fasle.

GRacias,

Virginia

Giniromero
27-02-2004, 17:27:18
Hola,

1)
..de una buena definición de índices..

Creo que esto lo estoy haciendo bien, pero, ¿podría alguien darme unas ideas generales de lo que se considera "una buena definición de índices", para asegurarme que no esté aquí el problema?

2) ..Prueba a quitar ambas cosas a ver que resultado optienes ..

He quitado disable controls, y bookmark, y parece que se refresca. Aunque la prueba de fuego es cuando lo pruebe en el otro centro, que como no está en la red local del servidor, si da problemas ....

3) He puesto el procedimiento almacenado, en un TIBDataSet. No le he podido definir código para el deleteSQL ni modificar, pero bueno.

el selectSQL es :

select ASIENTO, CODIGO, CONCEPTO, FACTURA, FECHA, FORPAGO, IMPDEBE, IMPHABER, NUMALU, NUMGRUP, RECIBO, TIPO, USUARIO from proECONOpago
where NUMALU =:NUMALU
order by fecha desc
el refreshSQL:

Select
CODIGO,
NUMALU,
NUMGRUP,
FECHA,
ASIENTO,
CONCEPTO,
IMPDEBE,
IMPHABER,
FORPAGO,
RECIBO,
FACTURA,
USUARIO,
TIPO
from ECONO
where
CODIGO = :CODIGO


y el insertSQL:

insert into ECONO
(CODIGO, NUMALU, NUMGRUP, FECHA, ASIENTO, CONCEPTO,
IMPDEBE, IMPHABER,
FORPAGO, RECIBO, FACTURA, USUARIO, TIPO)
values
(:CODIGO, :NUMALU, :NUMGRUP, :FECHA, :ASIENTO,
:CONCEPTO, :IMPDEBE, :IMPHABER,
:FORPAGO, :RECIBO, :FACTURA, :USUARIO, :TIPO)


La cosa es que, como ya comenté anteriormente en este mismo hilo, desde que estoy utilizando el procedimiento almacenado, tarda más en abrirse el programa, aunque, por suerte, los procedures del delphi que utilizan ese procedimiento almacenado, van más rápido que antes.

Problema, desde que utilizo este procedimiento almacenado, (en vez de una simple consulta), no sólo va más lento al abrirse, sino que me ha relentizado la busqueda de alumnos, (hay que tener en cuenta que todas las demás tablas dependen de la de alumnos). He hecho un "Trace into", para ver que es lo que daba problemas, y he descubierto que son los campos calculados de las tablas que dependen de mi tabla principal de alumnos, especialmente el tibdataset de mi procedimiento almacenado.

La cuestión es, si por un lado percibo que usando SP me mejora el tiempo de un procedimiento, pero por otro lado, ese tiempo que gano lo estoy perdiendo cada vez que cambio el alumno seleccionado de la tabla principal... (lo cual es algo muy habitual), no hay ninguna forma de mejorar el tiempo de "apertura" o "respuesta" de estos SP cuando se usan en el delphi?, ¿no hay ningún otro objeto que pueda usar más apropiado que el TIBDataSet?

Gracias por la ayuda de antemano,

Virginia

__cadetill
28-02-2004, 01:57:29
1)¿podría alguien darme unas ideas generales de lo que se considera "una buena definición de índices", para asegurarme que no esté aquí el problema?

A ver si me se explicar. Si tenemos una consulta que en el where de la misma filtramos por por 3 campos, tendriamos que hacer un índice por esos 3 campos. A mi entender (y que me corrijan si estoy equivocado) es más importante hacer un indice por los campos de filtrado que pos los campos que tengas en el Order By

He quitado disable controls, y bookmark, y parece que se refresca. Aunque la prueba de fuego es cuando lo pruebe en el otro centro, que como no está en la red local del servidor, si da problemas ....

Pues ya nos contarás a ver que tal te fueron las pruebas ;)


3) He puesto el procedimiento almacenado, en un TIBDataSet. No le he podido definir código para el deleteSQL ni modificar, pero bueno.
No estoy seguro de lo que voy a decirte, pero creo que el resultado de un SP es un conjunto de datos no modificable, es decir, como si estubieras haciendo una select sobre una vista (aunque hay motores de bases de datos que las vistas son actualizables). Por lo que no creo que te sirva de mucho utilizar un TIBDataset, quizás te funcionara mejor en un simple TIBQuery

Espero te sirva

Giniromero
01-03-2004, 10:34:06
Hola,


No estoy seguro de lo que voy a decirte, pero creo que el resultado de un SP es un conjunto de datos no modificable, es decir, como si estubieras haciendo una select sobre una vista (aunque hay motores de bases de datos que las vistas son actualizables). Por lo que no creo que te sirva de mucho utilizar un TIBDataset, quizás te funcionara mejor en un simple TIBQuery

Entonces, ¿este tipo de situaciones como la resolverías tu?, quiero decir, si tienes una tabla grande, que además sabes se va ha hacer más grande con el tiempo. Necesitas varios campos calculados, que dependen de otras tablas, y además tienes que hacer un filtrado por determinados campos, (dos o tres), y ves que todo eso, le cuenta mucho hacerlo con una consulta usando DataSet, pero igualmente necesitas poder escribir en los registros resultantes, (y por tanto no puedes usar TIbQuery).¿como lo plantearías tu?

Lo peor de todo es que desde que está instalada la primera versión de esta aplicación que utiliza interbase 7 y delphi 6, algunas veces los usuarios del programa, se quejan de que determinados campos de la aplicación, (los campos calculados que tengo que mostrar en ella), directamente no muestran nada, como si no lo calculase, entonces cierran la aplicación, y al abrirla, normalmente, vuelven a tener esos campos con su valor correspondiente.

Esto lo comento, pues, una de las cosas que estaba planteandome, por lo mismo, era crear procedimientos, con los campos ya calculados, y trabajar a partir de estos, para evitar ese problema, pero claro, si en estos no pueden guardar datos...

Por cierto, los parámetros ptInputOutput del ibstoredPro, ¿para que sirven exactamente?

Muchas gracias por todo,

Virginia

__cadetill
01-03-2004, 11:23:15
Entonces, ¿este tipo de situaciones como la resolverías tu?, quiero decir, si tienes una tabla grande, que además sabes se va ha hacer más grande con el tiempo. Necesitas varios campos calculados, que dependen de otras tablas, y además tienes que hacer un filtrado por determinados campos, (dos o tres), y ves que todo eso, le cuenta mucho hacerlo con una consulta usando DataSet, pero igualmente necesitas poder escribir en los registros resultantes, (y por tanto no puedes usar TIbQuery).¿como lo plantearías tu?

Suponiendo que tenga tazón en que no es modificable (y viendo que nadie dice lo contrario....) yo lo haría de la siguiente manera:
Utilizaría TIBDatasets pero sin ningún SP. Eso sí, super bien filtrados mediante la cláusula where!! Aunque este filtro haga que retorne 1 solo registro (tendría que ser prácticamente instantaneo esto).
Por otro lado... ¿de cuantos campos calculados estamos hablando? ¿de 3, 4, 5? Si son poquitos los calcularía en el OnCalcField del TIBDataset lanzando SQLs sobre la base de datos (que tendrían que ser también instantáneos ya que sólo han de devolver 1 registro o ninguno).

Resumiendo: filtrar el TIBDataset para que retorne el número de registros lo más pequeño posible (si puede ser 1 sólo registro) y calcular los campos calculados mediante SQLs.

Otra opción que se me acaba de ocurrir :p
Puedes usar una tabla de trabajo en la que tengas TODOS los campos que necesitas y mediante triggers actualizar las tablas maestras. Con esto te ahorras el tema de los campos calculados, pero no la de un buen filtro en el Where, ok?

Giniromero
01-03-2004, 12:30:10
... yo lo haría de la siguiente manera:

Utilizaría TIBDatasets pero sin ningún SP. Eso sí, super bien filtrados mediante la cláusula where!! Aunque este filtro haga que retorne 1 solo registro (tendría que ser prácticamente instantaneo esto).

Esto es lo que tenía antes, aunque tal vez si vuelvo a ello, quitando los bookmark y los disablecontrol, tenga menos código de cerrar y abrir tablas cada vez...


Por otro lado... ¿de cuantos campos calculados estamos hablando? ¿de 3, 4, 5? Si son poquitos los calcularía en el OnCalcField del TIBDataset lanzando SQLs sobre la base de datos (que tendrían que ser también instantáneos ya que sólo han de devolver 1 registro o ninguno).


Tengo un par de ellos, no son muchos, lo sé, pero tengo tal vez demasiado código para calcularlos. Tal vez pueda ver como reducir ese código, por que lo estoy haciendo a través del OnCalcField del TIBDataSet, igual que como tu me comentas.


Lo malo es que son estos campos calculados los que te comenté antes, algunas veces directamente les desaparecen la información a los usuarios.

Voy a ver si después de quitar lo famosos bookmark, disable controls, y reduciendo codigo para estos campos, si consigo solucionarlo.


Otra opción que se me acaba de ocurrir :p
Puedes usar una tabla de trabajo en la que tengas TODOS los campos que necesitas y mediante triggers actualizar las tablas maestras. Con esto te ahorras el tema de los campos calculados, pero no la de un buen filtro en el Where, ok?

Por si lo anterior no me funcionase, ¿a que te refieres con tabla de trabajo?¿como sería esto?

Muchas Gracias por todo,

Virginia

__cadetill
01-03-2004, 12:50:11
Tengo un par de ellos, no son muchos, lo sé, pero tengo tal vez demasiado código para calcularlos. Tal vez pueda ver como reducir ese código, por que lo estoy haciendo a través del OnCalcField del TIBDataSet, igual que como tu me comentas.

Yo suelo hacerlo como comento en este hilo (http://www.clubdelphi.com/foros/showthread.php?t=7300&highlight=oncalcfield) y no me ha fallado nunca ;)


Por si lo anterior no me funcionase, ¿a que te refieres con tabla de trabajo?¿como sería esto?

Bueno, se trataría de tener una tabla con todos los campos que necesitas (calculados y no calculados) con la que trabajarías para las altas/bajas/modicifaciones/consultas. Al ser una sola tabla, te evitas el tema de los calculados (pero si sólo son 2, casi que no vale la pena), pero como te comentaba, el tema de tener que filtrar bien los datos, no te lo ahorras. Luego, esta tabla, mediante triggers asociados a ella, se encargaría de actualizar las tablas maestras.
Otra opción que tienes usando tablas temporales es:
1.-Tienes la tabla temporal sin datos
2.-Con un SP la rellenas con los datos que quieres (las condiciones del filtro se lo pasas al SP)
3.-Lanzar una Query directamente y sin filtrar sobre la tabla temporal

La verdad no se si esta opción será rápida (no lo creo) pero bueno, por alternativas que no queden