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)
-   -   Registros en en bloques de 100 o mas... (https://www.clubdelphi.com/foros/showthread.php?t=68603)

Jose Roman 23-06-2010 18:28:49

Registros en en bloques de 100 o mas...
 
Hola a todos...

Bueno tengo delphi 2007, Zeos y Firebird 2.1.

Mi pregunta es, como tengo muchos registros y al hacer un select * se bloquea o demora mucho al tratar de hacer post cuando he realizado un insert, mi pregunta es como puedo hacer un select de 100 registros y que si uno le da next en el registro 100 pase al siguiente bloque de registros y no me bloquee esto, en caso contrario de que no se pueda me gustaria entonces saber que sugerencias tienen.

Gracias de antemano.

Casimiro Noteví 23-06-2010 18:42:33

Primero de todo, no hagas " select * " !!! ;)
Pon un filtro para traerte sólo los registros que necesites.

Luego puedes usar " select first 100 ... "

AzidRain 23-06-2010 19:14:48

Código SQL [-]
select * from tabla limit 0,100

te trae los 100 primeros registros, después solo modificas el query de acuerdo con la centana que quieras ver:
Código SQL [-]
 select * from tabla limit 101,100

Y así sucesivamente

Caro 23-06-2010 19:29:45

Hola, que yo sepa limit no existe en Firebird, pero se podría usar skip y first:

Código Delphi [-]
  Select First 100 * From (Select Skip 100 * From tuTabla)

donde el 100 del skip la primera ves sería 0 y cada ves que presiones Next aumentas en 100, osea utilizas una variable la cual vas incrementando....

Saluditos

AzidRain 23-06-2010 19:40:54

Que feo, tener que hacer un subquery para algo así. Por cierto el query que tiene el skip le va a salir a razón de lo mismo pues digamos que tienes 10 mil registros y los quieres ver de 100 en 100. En ese query te va a traer 9900 registros inicialmente, lo que casi es lo mismo que traer todos, curiosamente la consulta de los últimos registros será más rápida que la de los primeros pues cada vez iran quedando menos. Aunque funciona, no me parece muy óptimo que digamos.

Casimiro Noteví 23-06-2010 20:01:36

Se puede hacer así:

Código SQL [-]
Select First 100 Skip 200 * From tuTabla
Select First 100 Skip 300 * From tuTabla
Select First 100 Skip 400 * From tuTabla

etc...

Caro 23-06-2010 20:35:24

Cita:

Empezado por AzidRain (Mensaje 368168)
Que feo, tener que hacer un subquery para algo así.

Si tienes una mejor solución porque no la pones, como dije Limit no existe en Firebird y por lo menos yo, no he encontrado ninguna función que se asemeje a Limit.

Cita:

Empezado por AzidRain (Mensaje 368168)
Por cierto el query que tiene el skip le va a salir a razón de lo mismo pues digamos que tienes 10 mil registros y los quieres ver de 100 en 100. En ese query te va a traer 9900 registros inicialmente, lo que casi es lo mismo que traer todos, curiosamente la consulta de los últimos registros será más rápida que la de los primeros pues cada vez iran quedando menos. Aunque funciona, no me parece muy óptimo que digamos.

Si, reconozco que no es optimo lo que puse y sería mucho mejor hacerlo con una sola consulta como lo puso Casimiro.

egostar 23-06-2010 21:05:22

:rolleyes:

Código SQL [-]
select * from tabla limit 101,200

Código SQL [-]
select First 100 Skip 100 * from tabla

Sería interesante ver el tiempo de respuesta de cada motor......

Saludos

Jose Roman 23-06-2010 21:20:14

Gracias a todos, interesante haber generado un debate asi, pero hare ensayo a ver como me va.

Casimiro Noteví 23-06-2010 21:25:50

Pongo una pruebecita:

Base de datos firebird 1.5 de 495 Mbytes
Tabla tbLineasMovimientosAlmacen con 35 campos y 396.964 registros

Flamerobin en linux ubuntu 8.04

Select con todos los campos:
select first 100 skip 100 * from TBLINEASMOVIMIENTOSALMACEN

Resultado:
PLAN (TBLINEASMOVIMIENTOSALMACEN NATURAL)
Executing...
Done.
406 fetches, 0 marks, 0 reads, 0 writes.
0 inserts, 0 updates, 0 deletes, 0 index, 200 seq.
Delta memory: 1144 bytes.
Total execution time: 0,370s
Script execution finished.

AzidRain 23-06-2010 21:28:34

No te molestes caro, en todo caso no es culpa tuya sino del motor. Yo comento únicamente lo que pienso respecto a las diferencias entre motores, como se ve cada uno tiene un pie de donde cojear.

La solución de casimiro es la equivalente al "limit" que yo sugerí y como dice Jose Román, al final el ganador es él pues tiene mucha información para continuar con su proyecto.

Egostar apunta algo interesante, desgraciadamente las diferencias en rendimiento no la sve uno mas que en tablas con millones de registros lo que por lo que he visto en el foro solo se da en unos pocos caso, casi siempre se trata aquí de proyectos de unos cuantos miles de registros. Donde algunos milisegundos no hace ninguna diferencia.

rgstuamigo 24-06-2010 22:28:24

Pues :rolleyes: qué puedo decir?... Pareciera que es un tema de nunca acabar lo raro es que con tanto tiempo trabajando con delphi no se hayan dado cuenta que Delphi cuenta con un tremendo componente, precisamente para evitar y solucionar ese tipo de problemas que comenta nuestro amigo Jose Roman, que al propósito ya es la segunda vez que está preguntando lo mismo.;), en esa ocacion le comenté las potencialidades del Componente TClientDataSet, supongo que quizás no se convenció de mi respuesta en aquella ocasión :o :D
De todas manera cada uno saque sus concluciones, al fin y al cabo cada uno decide la forma de trabajar ;).
Saludos...:)

Casimiro Noteví 24-06-2010 22:52:21

¿Pero el TClientDataSet necesita tener todos los datos en memoria o pueden ser leídos poco a poco?

rgstuamigo 24-06-2010 22:57:21

Pues para eso precisamente tiene la propiedad PacketRecords donde se puede definir la cantidad de registros que traerá desde el servidor.;)
Si quieres más información, pues en el otro hilo en cuestion he puesto algunos enlaces muy pero muy interesantes. ;)

Casimiro Noteví 24-06-2010 23:31:13

No había leído el otro hilo "ayuda con consulta" :)
Los Tclientdataset los he usado alguna vez como tablas temporales en memoria, sé que son muy potentes, vi un video de ¿jachguate? donde se explicaban cosas muy interesantes.
Pero, es que son tantas cosas para aprender, no da tiempo, todavía me siento un inútil analfabeto e inculto, puede que dentro de otros 25 años haya aprendido lo básico :)

Casimiro Noteví 24-06-2010 23:34:12

Cita:

Los componentes ClientDataSet tienen una propiedad llamada PacketRecord la cual determina cuandos registros se van a almacenar en memoria. Por defecto tiene configurado -1 lo que significa que se van a cargar todos los registros en la tabla. Como eso no me interesa en el listado general del formulario principal lo que vamos a hacer es poner esta propiedad a 100.

Por eso he ordenado la lista por el campo ID descendentemente para que se vean sólo los últimos 100 registros insertados. Una de las cosas que más me gustan de los componentes ClientDataSet es que se trae los 100 últimos registros y desconecta la tabla y la transacción quitándole trabajo al motor de bases de datos. Si el usuario que maneja el programa llega hasta el registro número 100 el propio componente conecta automáticamente con el servidor, se trae otros 100 registros y vuelve desconectar.
IMPRESIONANTE :eek:

rgstuamigo 24-06-2010 23:45:08

Así es Casimiro... la verdad es que el ClientDataSet es uno de los componentes más robustos que he encontrado entre los componentes que vienen con Delphi ;), por lo cual me di cuenta que para que nuestra aplicacion esté bien diseñada es necesaria dividirla en capas, tal cual como menciona el autor de la página donde extraiste ese párrafo anterior.;)

AzidRain 25-06-2010 00:14:58

Mas que potente este componente es de los mas subutilizados de Delphi el detalle es que encontramos muchos tutoriales e informaciones distintas para cada utilización, pero no hay un compendio que abarque todo lo que este componente puede hacer, muchos nos quedamos nomas con la idea de que nos sirve para hacer entre otras cosas tablas en memoria, pero como se ve hay mucho todavía por explorar.

Jose Roman 25-06-2010 17:42:13

Bueno ya hice lo que me han propuesto y sale perfecto, solo tengo una problema, alguien se le ocurre como controlar los registros, es decir:

he hecho algo al llegar al registro numero 100 y pasa perfectamente al siguiente registro, pero tengo problemas al dar clic en el boton PRIOR del DBNavigator. Si alguien me corrige lo realizado o me da una idea mejor gracias.

Nota: lo hice con 10 registros para ver mas rapido lo que pasa.

Código Delphi [-]
procedure TwConsigna.bsSkinDBNavigator1Click(Sender: TObject;
  Button: TbsNavigateBtn);
begin
  zqReg.Open; // Query que da el numero de registros
  if Button in [nbLast,nbFirst] then
  begin
    zqConsi.Close;
    zqConsi.SQL.Clear;
    zqConsi.SQL.Add(MiSQL);
    zqConsi.SQL.Add('ORDER BY ID_CG DESC');
    if Button = nbLast then
    begin
      zqConsi.ParamByName('R').Value := zqRegCOUNT.Value - 9;
      zqConsi.Open;
      zqConsi.Last;
    end else
    begin
      zqConsi.ParamByName('R').Value := 0;
      zqConsi.Open;
    end;
  end else
    if Button = nbNext then
    begin
      if (zqConsi.Eof) and (Bloque < (zqRegCOUNT.Value div 10)) then
      begin
        Inc(Bloque,10);
        zqConsi.Close;
        zqConsi.ParamByName('R').Value := Bloque;
        zqConsi.Open;
      end;
    end else
      if Button = nbPrior then
        if (zqConsi.Bof) and (Bloque > 0) then
        begin
          Dec(Bloque,10);
          zqConsi.Close;
          zqConsi.ParamByName('R').Value := Bloque;
          zqConsi.Open;
          zqConsi.Last;
        end;
  zqReg.Close;
end;
// Bloque variable que determina en que bloque de registro esta


La franja horaria es GMT +2. Ahora son las 10:47:58.

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