No se si es el lugar correcto, pero quería compartir y poner en "tela de juicio" mi manera de lidiar con los generadores de interbase/firebird.
El tema es que un generador se modifica cuando es llamado (siempre y cuando se le diga), pero normalmente se lo incrementa.
El caso típico del uso de los valores autoincrementados es el ID de una instancia de entidad, por ejemplo ID_CLIENTE (identificador unívoco de una fila de la tabla CLIENTE).
Se haga commit o rollback en una transacción el generador "actúa" igual, con lo que puede ocurrir el caso siguiente: Se incrementa el número de serie de una factura y luego se intenta escribir la información en las tablas correspondientes, luego sucede un error, pero el generador ya "actuó". Entonces será necesario volver al número anterior para que no quede un hueco en la secuencia de números de serie (cosa que no debe ser).
Hace poco me encontré con este problema una vez más y decidí darle una resolución diferente:
Creé un procedimiento (almacenado) en la base de datos como wrapper de un generador para el número de serie de las ventas, pero con la perticularidad que no incrementa siempre al generador, sino que recibe un parámetro "Inc" que indica el incremento que recibirá éste.
CREATE PROCEDURE nro_serie_venta (inc SMALLINT) RETURNS (nuevo_nro INTEGER) AS BEGIN nuevo_nro = gen_id(nro_serial_ven_gen, Inc); suspend; END
Nro_Serial_Ven_Gen es el generador.
En el programa llamo al wrapper con el parámetro Inc puesto a cero (0), y con eso obtengo el valor actual en el parámetro nuevo_nro sin incrementar al generador y lo guardo en una variable del programa (una variable privada del procedimiento) uso esta variable y luego del commit de la transacción de la venta, si todo sale bien, llamo de nuevo al wrapper, con el parámetro Inc puesto a uno (1).
try // Commit de la transacción venta de la base de datos desde el módulo de datos venta dmVen.trVenta.Commit; finally // Pasa el parémtro de entrada para incremento en 1 dmVen.spNumSerieVen.ParamByName('Inc').AsSmallint:= 1; // Ejecuta el procedimiento dmVen.spNumSerieVen.ExecProc; end;
Es decir que no tengo que recurrir a ningún proceso extra para volver el número para evitar el hueco, pues si el commit sale mal, no se habrá incrementado el generador.
Saludos