Ir al contenido


Foto

auntoincrement con firebird


  • Por favor identifícate para responder
2 respuestas en este tema

#1 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 15 agosto 2014 - 04:18

Intento utlizar una tabla de firebird que contiene un campo autoincrementado mediante un trigger.
Todo funciona a la perfección, pero cuando intento hacer que funcione el campo como debe, no hay respuesta.
En Delphi, todo es muy simple, solo se le dice cual es el campo a automatizar, cual es el trigger y listo, pero el componente TSqlQuery de Lazarus no cuenta con esas propiedades.
Según leí, es posible que no se haya cargado toda la información desde la base de datos (un bug de Lazarus)
Además, leí que se debe llamar al generador desde un procedimiento para así asignar manualmente el nuevo valor del campo. Cosa que no me parece muy práctica.

¿alguien sabe como hacerlo funcionar?, sin tener que usarlo manualmente.



delphi
  1. CREATE TABLE GENERO (
  2.     ID_GEN "cod_small" NOT NULL,
  3.     NOM_GEN "vchar20" NOT NULL,
  4.     NOMC_GEN "vchar12");
  5.  
  6. /* Primary keys definition */
  7. ALTER TABLE GENERO ADD CONSTRAINT PK_GENERO PRIMARY KEY (ID_GEN);
  8.  
  9. SET TERM ^ ;
  10.  
  11. /* Trigger: AI_ID_GEN */
  12. CREATE TRIGGER AI_ID_GEN FOR GENERO ACTIVE
  13. BEFORE INSERT POSITION 0
  14. AS
  15. BEGIN
  16.   IF (NEW.ID_GEN IS NULL) THEN
  17.       NEW.ID_GEN = GEN_ID(ID_GEN_GEN, 1);
  18. END
  19. ^
  20.  
  21. SET TERM ; ^


  • 0

#2 Sergio

Sergio

    Advanced Member

  • Moderadores
  • PipPipPip
  • 1.092 mensajes
  • LocationMurcia, España

Escrito 16 agosto 2014 - 04:18

Debes usar generadores en firebird: Los generadores generan secuencias de codigos unicos, justo para lo que comentas, con la ventaja de que trabajan en unas transacciones espciales: si desde una transaccion obtienes el codigo 2 y 3 para unas inserciones, y en otra transaccion concurrente se pide otro generador, se obtiene el 4 aunque la primera transaccion no se haya commiteado aún... vamos, que no fallan nunca!

http://www.firebirds...ratorguide.html

La idea es: creas un generador, le das un valor incial, y en un trigger OnInsert haces algo como My_Id:= Generator(IdDeMiTabla, 1) y listo, ids unicos siempre.

La unica cosa a tener en cuenta es que si en una transaccion pides un id al generador y luego no haces commit, ese id se descarta, con lo que no obtienes siempre la secuencia completa de ids, puedes terminar con "saltas" de ids pedidos y no usados.

Pero, al asignar el id en la grabacion final, te olvidas de obligar a ponerlo en la ficha, si lo ponen pues lo grabas, pero si llega un null al trigger, se rellenara solito con un id valido.
  • 0

#3 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 mensajes
  • LocationMisiones, Argentina

Escrito 16 agosto 2014 - 12:57

Muchas gracias Sergio, todo eso lo conozco, aún así lo agradezco sobre todo por lo completo y conciso de tu explicación.
El tema es que quería evitar el uso de un método llamado por evento.
Te explico mejor, aunque por lo visto la solución es esa (utilizar el evento OnInsert).
El caso es que en Delphi con el componente TIBDataSet solo basta con decirle cuál es el método generador de la base de datos y cuál es el campo que recibirá el valor generado y se terminó el asunto.
Propiedad GeneratorField

Mientras que con Lazarus, el componente TSQLQuery no posee esas propiedades y al parecer se debe capturar un evento (OnInsert) para poder asignar el valor al campo que deberá recibirlo.

Mi problema no es la generación de los autoincrementales, triggers, etc. sino usarlos con TSQLQuery de una manera transparente como con Delphi. Eso es todo, pero parece ser que Lazarus requiere un paso más.
Quizá es confuso el hecho de haber puesto las líneas de DDL. Lo hice precisamente para que aquel que lea, vea que en eso no hay error (me equivoqué).

También aclaro sobre lo que me comentas que es así como lo dices para el caso de varios accesos al trigger, la posible existencia de huecos en caso de no hacerse el post, o en caso de error. El tema es que los autoincrementales son solo eso, y no se suponen valores seriales como por ejemplo el de la numeración de una factura.
También el problema de los huecos se soluciona en parte, capturando el evento OnPost, que asegura que el trigger sea llamado cuando ya sea algo seguro (aun así quedaría por solucionar el problema de huecos por errores).
Por otro lado algunos sugieren el uso de la función Max o Count de SQL, pero esto es ineficiente, ya que depende del tamaño de la tabla para dar una respuesta.

Seguiré buscando o si no agrego las líneas de código y listo. Pues la verdad es más capricho que otra cosa. ;)

Saludos.  (b)



  • 0




IP.Board spam blocked by CleanTalk.