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)
-   -   FireBird + Delphi 7 (https://www.clubdelphi.com/foros/showthread.php?t=68833)

AzidRain 09-07-2010 19:32:45

Para el amigo mcs, tienes razón es más sencillo, intuitivo y legible atacar las tablas tal como tu lo mencionas, al final cuando haces por ejemplo:
Código Delphi [-]
tabla.open;
tabla.append;
tabla.fieldbyName('micampo').AsString := 'valor';
tabla.post;

El componente que usas en realidad convierte todo eso en un insert (aunque tú no lo veas), lo mismo sucede cuando haces tabla.edit; el componente hará un "update table".

En ambos casos no hay ninguna ventaja apreciable en velocidad haciéndolo mediante la forma que mencionas o la que dice caral. Eso sí, hay que cuidarse de nunca de los nuncas hacer un "select * from tabla" sin ponernle un filtro para editar un solo registro pues entonce sí que tendras problemas de lentitud, pues te traeras todo de un jalón.

La gran ventaja de hacerlo como dices es que no tienes que revolver SQL directamente con tu código, lo que lo hace más legible.

Yo utilizo ese esquema para hacer CRUD (que es lo que más ocupa uno en entornos administrativos) y me ha funcionado sin ningún problema. También uso el esquema de caral cuando se trata de procesos tipo batch que no son interactivos.

Al final de cuentas cualquiera de los 2 métodos es correcto siempre y cuando estén bien aplicados y soportados, cualquiera va a ser lento si se basa en un mál concepto o diseño.

Caral 09-07-2010 19:42:48

Hola
A mi escaso entender:
Esto:
Código Delphi [-]
tabla.open;
.............
Es exactamente lo mismo que esto:
Código Delphi [-]
Select * from Tabla

En otras palabras, te traes todo el contenido de la tabla, te guste o no.
Por lo tanto; Es mas simple, SI?, tal vez, pero no es mejor que hacer el edit, insert, ect directamente al campo sin traer nada extra.

Repito: a Mi pequeño, muy pequeño entender.
Saludos

Casimiro Notevi 09-07-2010 20:15:33

Cita:

Empezado por Gimli (Mensaje 369842)
¿cual es el mejor componente para usar firebird desde delphi7? que permita usar las caracteristicas que usan la Ttables con paradox, para que la migracion de los programas no sea traumatica

Los componentes IBX que te ha indicado Caral y también los FIBplus, ambos son de acceso directo. Luego hay varios con "intermediario" como ZeosLib, que tienen una buena pinta también.

Cita:

Empezado por Gimli
Y segundo punto, es firebird una base de datos fiable, rapida y estable

Eso ya lo contesté antes, es muy muy muy fiable, es muy muy muy rápida y es muy muy muy estable.

Cita:

Empezado por Gimli (Mensaje 369843)
Anteriormente usaba paradox pero las tablas se estropeanban... a veces con el uso o por que el cliente apagaba mal el equipo, luego cambie a pervasive que es mas robusta pero consume bastantes recursos y para aplicaciones que tengan que estar en red local con tablas con miles o millones de registros es lentisima

Precisamente son dos puntos fuertes de Firebird, está pensada para que no exista problema antes una desconexión de la misma, sea por imprudencia, corte de electricidad, etc.
Igual que está preparada para trabajar con grandes cantidades de datos sin que baje de rendimiento

Cita:

Empezado por Gimli
¿La habeís probado con una base de datos en red con más de 5 puestos atacandole simultaneamente?
¿Como se comporta con tablas con miles de registros? ¿busca y filtra rapido por cualquier campo?

¿5 puestos?, ¿miles de registros?, eso es una broma para firebird. Como ejemplo, uno de mis clientes mantiene alrededor de 500 conexiones todo el día, son unos cien equipos con varios programas que atacan la misma base de datos. El tamaño de la base de datos es superior a los 20 Gigas y los registros no se cuentan por miles, sino por decenas de millones.
Las bases de datos de casi todos mis clientes están por encima de 500 Megas y las conexiones están alrededor de 50 (de media).

Cita:

Empezado por Gimli
El uso que le quiero dar es para todos los casos, pues si funciona bien migraria todas las aplicaciones (con el tiempo) a esta base de datos, y unas aplicaciones son de almacenamiento masivo de datos,
otras prima la velocidad, otras la respuesta en red a los terminales conectados

Perfecto, está pensada para todo eso.

Cita:

Empezado por Gimli
¿Como se comporta con tablas con miles de registros? ¿busca y filtra rapido por cualquier campo?

Ahí es donde entra la parte que le toca al programador, usa sentencias sql eficientes y verás que da igual tener una tabla con un registro o con un millón.

Además debes recordar que con Firebird puedes usar servidores con una amplia variedad de sistemas operativos, puedes instalarlo desde los más pequeños equipos hasta los superordenadores más grandes que existen, ya que funciona en linux (es su entorno natural).
Además es libre y gratis.

Por cierto, aunque me gusta mucho Firebird, yo tampoco descartaba PostgreSQL de la lista.

movorack 09-07-2010 20:19:48

Cita:

Empezado por Caral (Mensaje 369870)
Hola
A mi escaso entender:
Esto:
Código Delphi [-]
tabla.open;
.............
Es exactamente lo mismo que esto:
Código Delphi [-]
Select * from Tabla

En otras palabras, te traes todo el contenido de la tabla, te guste o no.
Por lo tanto; Es mas simple, SI?, tal vez, pero no es mejor que hacer el edit, insert, ect directamente al campo sin traer nada extra.

Repito: a Mi pequeño, muy pequeño entender.
Saludos

Casi nunca uso el TTable o sus decendientes... por lo general uso un query para evitar traerme todos los registros.

Código SQL [-]
select * from tabla where id = :id

y luego hago las modificaciones en ese registro...

Código Delphi [-]
  Query1.edit;
  ...
  Query1.post;

igual trabaja para las inserciones.

Otra opinión no sobra... :D

Casimiro Notevi 09-07-2010 20:26:18

Cita:

Empezado por movorack
select * from tabla where id = :id
y luego hago las modificaciones en ese registro...

Es lo más sensato.

Caral 09-07-2010 20:38:27

Hola
Bueno, como diria mi amigo Egostar: Depende, depende....
Si hablamos de los componentes (y por eso mencione que SI depende de ellos) en el caso de los IBQuery esto no se puede hacer, envia un hermoso error ya que no permiten hacer ediciones, inserciones etc....
Para esto se usarian los IBDataset, que en tal caso lo hacen algo diferente.
Por otro lado:
Me extraña que un programador con la esperiencia de AzidRain diga abiertamente que es lo mismo y que no afecta en la velocidad traer todos los registros con un Table.Open para hacer un edit, inser u otro y que ademas es mas simple.
No se, pero la idea es darle a las personas la solucion optima, la mas apropiada y no la mas simple que dara problemas a la larga.
Saludos

Delphius 09-07-2010 20:41:14

Ya que se admiten consejos, si me lo permiten... aquí va otro:
Jamás de los jamases se debe emplear asterisco. ¡Es una práctica tediosa e ineficiente! Es algo que hay que erradicar... ¡DI NO a *!

El uso del asterisco obliga al motor realizar dos consultas previas sobre las tablas del sistema: la primera para extraer los campos de dicha tabla, la segunda para pre armar la consulta definitiva. Luego recién se lanza la consulta que se ha elaborado.

Es mucho más liviano y práctico indicar los campos EXTRICTAMENTE NECESARIOS que lanzar un select *. Si admito que es muy molesto e incómodo cuando la tabla tiene demasiados campos, pero en definitiva lo que habría que preguntarse es: ¿Es necesario suministrar todos los campos? Si es un si pues ni modo, a enlistarlos. Si la funcionalidad a la que estamos por brindar soporte no requiere devolver todos los campos... ¿Qué sentido tiene el *?

Otra posibilidad que cabría poner en discusión cuando la cantidad de campos es alta es la de preguntarse si estará bien normalizada. Encontrar un adecuado equilibrio entre la normalización y desnormalización es tanto un arte como una ciencia.

;)

Saludos,

Casimiro Notevi 09-07-2010 20:51:08

El uso de tablas sólo puede ser factible usarlo con las que tienen pocos registros, por ejemplo:
tbTiposIVA que va a tener menos de 5 registros.

Delphius 09-07-2010 21:06:59

Cita:

Empezado por Casimiro Notevi (Mensaje 369889)
El uso de tablas sólo puede factible usarlo con las que tienen pocos registros, por ejemplo:
tbTiposIVA que va a tener menos de 5 registros.

¿ 5 tipos de IVA? Allá... porque por este lado de la tierra los políticos se inventan uno por día. Son capaces de hasta sacar impuesto hasta por el O2 que consumimos... y para hacerlo más chungo... los cálculos del impuesto estarán basados en O2/hora. :D:(

Saludos,

Casimiro Notevi 09-07-2010 22:00:45

Bueno, he dicho 5, pero hay 3 tipos:

El normal: 18% (antes del 1 de julio era del 16% :mad:)
El reducido: 8% (antes del 1 de julio era del 7% :mad:)
El superreducido: 4% (este no ha cambiado) :)
El exento: 0% (este es el mejor) :D

mcs 09-07-2010 23:42:48

Cita:

Empezado por AzidRain (Mensaje 369867)
Para el amigo mcs, tienes razón es más sencillo, intuitivo y legible atacar las tablas tal como tu lo mencionas, al final cuando haces por ejemplo:

Código Delphi [-]
tabla.open;
tabla.append;
tabla.fieldbyName('micampo').AsString := 'valor';
tabla.post;





El componente que usas en realidad convierte todo eso en un insert (aunque tú no lo veas), lo mismo sucede cuando haces tabla.edit; el componente hará un "update table".

En ambos casos no hay ninguna ventaja apreciable en velocidad haciéndolo mediante la forma que mencionas o la que dice caral. Eso sí, hay que cuidarse de nunca de los nuncas hacer un "select * from tabla" sin ponernle un filtro para editar un solo registro pues entonce sí que tendras problemas de lentitud, pues te traeras todo de un jalón.

La gran ventaja de hacerlo como dices es que no tienes que revolver SQL directamente con tu código, lo que lo hace más legible.

Yo utilizo ese esquema para hacer CRUD (que es lo que más ocupa uno en entornos administrativos) y me ha funcionado sin ningún problema. También uso el esquema de caral cuando se trata de procesos tipo batch que no son interactivos.

Al final de cuentas cualquiera de los 2 métodos es correcto siempre y cuando estén bien aplicados y soportados, cualquiera va a ser lento si se basa en un mál concepto o diseño.


Esto es lo que me refería!

Por otra parte, diría que en las IBDAC un table.open no equivale a un SELECT * FROM loquesea;. Lo tendría que mirar con detalle (las IBDAC traen un monitor para ver exactamente que comandos SQL se ejecutan)...

egostar 09-07-2010 23:53:49

Cita:

Empezado por mcs (Mensaje 369906)
Esto es lo que me refería!

Por otra parte, diría que en las IBDAC un table.open no equivale a un SELECT * FROM loquesea;. Lo tendría que mirar con detalle (las IBDAC traen un monitor para ver exactamente que comandos SQL se ejecutan)...

Perdón, pero un Table.Open de cualquier componente, traé SI ó SI todos los campos de la tabla es decir
Código SQL [-]
SELECT * FROM tabla
, puedes limitar el número de registros a través de un filtro. Eso es lo que Caral está comentando desde un inicio, con el Query puedes seleccionar los campos que realmente necesitas ahorrando tiempo y recursos.

Saludos

Casimiro Notevi 10-07-2010 00:37:09

Cita:

Empezado por egostar (Mensaje 369908)
Perdón, pero un Table.Open de cualquier componente, traé SI ó SI todos los campos de la tabla es decir Código SQL [-]SELECT * FROM tabla

, puedes limitar el número de registros a través de un filtro. Eso es lo que Caral está comentando desde un inicio, con el Query puedes seleccionar los campos que realmente necesitas ahorrando tiempo y recursos.

Saludos

Más claro no se puede decir :)

El sistema de tablas está bien cuando son relativamente pocos registros, pero según vayan aumentando cada vez será más lento abrir la pantalla donde está esa tabla y cada vez tardará más en insertar un registro. Ni que decir tiene que si hay muchísimos registros en la tabla entonces ya ni siquiera será operativo y se tendrá que hacer el cambio y olvidar el uso de ttable.

El uso de ttable es el típico de los mensajes "mi programa iba muy bien pero últimamente tarda mucho en acceder y en grabar los datos, formateé el disco y reinstalé el windows, pero sigue igual de lento, cada vez más, ¿será un fallo del firebird?" :D

Casimiro Notevi 10-07-2010 00:49:04

Para muestra un botón, el siguiente código corresponde a la propiedad tablename del componente tztable de los componentes zeoslib:

Código Delphi [-]
procedure TZAbstractTable.SetTableName(const Value: string); 
begin 
  if FTableName <> Value then 
  begin 
    FTableName := Value; 
    if Value <> '' then 
      SQL.Text := Format('SELECT * FROM %s', [FTableName]) 
    else SQL.Text := ''; 
  end; 
end;

Caral 10-07-2010 00:59:59

Hola
Por eso digo, no hay que ser un maestro para saber algo tan básico.
Seguir insistiendo en que un table.open es eficiente o que es lo mismo que hacerlo por SQL, es perder el tiempo.
Me sigue extrañando que AzidRain defienda lo indefendible y que ademas mcs insista en esto sin conocimiento alguno, notable.
Soy novato, pero hay mas principiantes.:):p
Saludos

Casimiro Notevi 10-07-2010 01:23:10

Por eso las originales FreeIB Components no traían componente TTable, porque querían primar la velocidad y eficiencia. Después, las siguientes herencias creadas a partir de las FreeIB que han querido seguir siendo eficientes tampoco han traído ese componente, como FIBL, FIBplus, etc.
Sin embargo, Borland sí añadió una TIBTable en las IBX, heredadas, como todos sabemos, de FreeIB, seguramente por hacerlo más cómodo a los que venían de usar paradox o access.
Cita:

Empezado por IBX
SQL := TStringList.Create;
SQL.Text := 'select ' + {do not localize}
QuoteIdentifier(DataBase.SQLDialect, FTableName) + '.*, ' {do not localize}
+ 'RDB$DB_KEY as IBX_INTERNAL_DBKEY from ' {do not localize}
+ QuoteIdentifier(DataBase.SQLDialect, FTableName);
if Filtered and (Filter <> '') then
begin
SQL.Text := SQL.Text + ' where ' + Filter; {do not localize}
bWhereClausePresent := True;

Que como se puede observar también usa, obviamente, un " select * ".
Luego, los MDO (Mercury Database Objects), que no heredaron de FreeIB, sino que decidieron heredar de IBX, también lleva un TTable, que el código parece el mismo de las IBX:
Cita:

Empezado por MDO
SQL := TStringList.Create;
SQL.Text := 'select ' + {do not localize}
QuoteIdentifier(DataBase.SQLDialect, FTableName) + '.*, ' {do not localize}
+ 'RDB$DB_KEY as IBX_INTERNAL_DBKEY from ' {do not localize}
+ QuoteIdentifier(DataBase.SQLDialect, FTableName);
if Filtered and (Filter <> '') then
begin
SQL.Text := SQL.Text + ' where ' + Filter; {do not localize}
bWhereClausePresent := True;

Bueno, no parece, es que es el mismo código :)

Y ya no sigo con esto, creo que está claro el tema.

mcs 10-07-2010 11:31:16

Hola otra vez!

Soy tozudo como una mula, y seguía con mi idea que los IBDAC no podían estar TAN mal programados.

Y teneis CASI LA RAZON! En las IBDAC, los componentes que uso en el curro y que he recomendado al comapñero Gimli, un table.open se traduce en:
Código:

SELECT COUNT(*) FROM table;
SELECT * FROM table;

O sea, que no sé si puede haber algo más ineficiente... Muchas gracias por participar en este debate, y por haberme hecho dudar. Debido a esto, me he animado a hacer la prueba... :)

Saludos,

Marc

Casimiro Notevi 10-07-2010 17:41:10

Cita:

Empezado por mcs (Mensaje 369928)
[..] Soy tozudo como una mula, y seguía con mi idea que los IBDAC no podían estar TAN mal programados.

No es que estén mal programados, es que no hay otra forma de hacerlo. Ten en cuenta que, por ejemplo, en una tabla dbf, hay una cabecera donde indica la estructura de los datos, la longitud que ocupa cada registro y el total de registros, entre otros. Si quieres ir al último registro sólo tienes que avanzar el puntero (UltimoRegistro*OcupacionDeCadaRegistro). Que quieres ir al registro 1000, pues multiplicas 1000*OcupacionDeCadaRegistro y posicionas el puntero en ese lugar del fichero.
Pero una base de datos relacional no tiene nada que ver con una tabla plana. En una RDBMS hay registros (y campos) con longitud variable, no existe un primer registro y un último registro, todo depende del orden con el que los queramos presentar. No podemos ir al último registro porque no sabemos cual es, ¿el último ordenado por fecha, por código, por nombre, etc.?, cuando hacemos un select traemos sólo unos pocos registros, por ejemplo, si los presentamos en un dbgrid normalmente serán justos los que quepan en pantalla, luego se irán trayendo los siguientes según avanzamos en el dbgrid, y si le damos "ir al final" entonces se traerá todos los registros.
Son filosofías muy distintas de trabajo.

Cita:

Empezado por mcs
Código:

SELECT COUNT(*) FROM table;
SELECT * FROM table;


¿Por qué IBDAC hace eso?, está claro, para que "parezca" que es una tabla "normal", primero cuenta los registros que hay, además lo hace muy ineficientemente (el asterisco), podría usar uno sólo de los campos que tenga índice, sería mucho más rápido. Y una vez que sabe cuantos registros hay, o sea, ha tenido que ir hasta el último campo para traérselos todos, es ahora cuando hace un select de todos los campos, otra vez el *, y sigue la ineficiencia elevada al cuadrado :D

Pero, repito, no es que esté mal programado, es que si quieres simular una tabla plana con un RDBMS no tienes otra solución.
La otra solución es hacer lo mismo que FreeIB, FIBL, FIBplus, etc. ¡¡¡no tener componente TTable!!! :)

Estas cosas se aprende estudiando bastante en profundidad las bases de datos, su código fuente, descubres cosas curiosas, trucos interesantes y algunos fallos tremendos. Las bases de datos son una de mis aficiones, me gusta inspeccionar cómo están hechas, hace muchos años hice un sistema de bases de datos como el de los dbf, al que añadí control multiusuario para red local. Y años más tarde hice otro sistema de gestión de bases de datos (un sistema Btree+) también con control de bloqueos, multiusuario, red, journaling, etc. en lenguaje C, lo utilicé en algunos proyectos propios y la verdad es que funcionaban muy bien estable y muy rápido.
Lástima que los perdí en un disco defectuoso, estoy hablando de la época 1990 a 1995, ya ha llovido :)

Delphius 10-07-2010 19:22:50

Cita:

Empezado por Casimiro Notevi (Mensaje 369945)
No es que estén mal programados, (...)

Estas cosas se aprende estudiando bastante en profundidad las bases de datos, su código fuente, descubres cosas curiosas, trucos interesantes y algunos fallos tremendos. Las bases de datos son una de mis aficiones, me gusta inspeccionar cómo están hechas, hace muchos años hice un sistema de bases de datos como el de los dbf, al que añadí control multiusuario para red local. Y años más tarde hice otro sistema de gestión de bases de datos (un sistema Btree+) también con control de bloqueos, multiusuario, red, journaling, etc. en lenguaje C, lo utilicé en algunos proyectos propios y la verdad es que funcionaban muy bien estable y muy rápido.
Lástima que los perdí en un disco defectuoso, estoy hablando de la época 1990 a 1995, ya ha llovido :)

¡Hey! Cuidado con mi apellido... ¡que no tiene nada de malo el tener una mente cuadrada! :D:D:D

Veo amigo que te gusta mucho el tema de bases de datos, yo todavía no me animé a ver el code de Firebird... por empezar no se de C (y C++, ahora Firebird se ha portado a este) y el tema de los árboles B+ me suena un tantito a chino :p y que decir de snapshots... al concepto lo entiendo... la pregunta es ¿Y técnicamente, como se lo programa? :eek:

¿Haz considerado meterte bien de lleno en aportar tus conocimientos formando parte oficial de Firebird Proyect?

Saludos,

Casimiro Notevi 11-07-2010 00:04:21

Cita:

Empezado por Delphius (Mensaje 369953)
[..] ¿Haz considerado meterte bien de lleno en aportar tus conocimientos formando parte oficial de Firebird Proyect?

Sí, lo he pensado algunas veces, y estoy convencido de que puedo colaborar en algunos apartados, pero tendría que dedicarle muchísimo tiempo y dedicación para conocer a fondo el código del mismo, por lo que surgen varios problemas respecto a eso:

Código Delphi [-]
while NecesitoGanarmeLasHabichuelas do
begin
  if getTiempoParaConocerEnProfundidadElProyecto then
    ColaborarEnProyecto('xxx');
end;

function getTiempoParaConocerEnProfundidadElProyecto:boolean;
begin
  result := false;
  if Jubilado or HerenciaRecibida or GanadoLoteria then
    result := true;
end;

Por si fuese poco, el inglés y yo estamos peleados :)


p.d. Evidentemente, dedicándole el suficiente tiempo y dedicación, no sólo yo podría colaborar, también cualquiera de vosotros.


La franja horaria es GMT +2. Ahora son las 16:21:46.

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