En Firebird podemos tener unas variables públicas e internas llamadas generadores o secuencias. Son la misma cosa, lo que en Firebird siempre se llamó generador en el estandar SQL se denomina secuencia.

Que una variable sea pública significa que puede usarse en cualquier lugar dentro de la Base de Datos, o sea en cualquier SELECT, stored procedure o trigger. Que sea interna, significa que fuera de la Base de Datos no es conocida, no existe.

Aunque nosotros podemos cambiar el valor de un generador lo normal y lo correcto es que sea el propio Firebird quien lo cambie.

¿Para qué usar un generador?

Una de sus principales aplicaciones es para tener identificadores para nuestra Primary Key que podemos tener la seguridad 100% de que jamás se repetirán. Recordarás que las Primary Key no pueden tener valores duplicados, entonces como los generadores tampoco pueden tener valores duplicados (si se usan correctamente), son perfectos para ser usados en las Primary Key.

Ejemplo del uso de un generador:

SET TERM ^ ;

CREATE TRIGGER BI_PRODUCTOS_PRD_IDENTI FOR PRODUCTOS
       ACTIVE BEFORE INSERT
       POSITION 0
AS
BEGIN
   IF (NEW.PRD_IDENTI IS NULL OR NEW.PRD_IDENTI = 0) THEN
      NEW.PRD_IDENTI = GEN_ID(PRODUCTOS_PRD_IDENTI_GEN, 1);
END^

SET TERM ; ^

En este trigger tenemos un generador cuyo nombre es PRODUCTOS_PRD_IDENTI_GEN. La función GEN_ID() recibe a ese generador como parámetro e incrementa su valor en 1. ¿Por qué en 1? porque ese es el segundo parámetro que recibió la función GEN_ID(). Si queremos incrementarlo en 2 entonces habríamos escrito:

NEW.PRD_IDENTI = GEN_ID(PRODUCTOS_PRD_IDENTI_GEN, 2);

y así los valores del generador se incrementarían de 2 en 2.

También podríamos poner como segundo parámetro el número 0 ¿para qué nos serviría eso? para conocer el valor actual del generador. Eso significa que si escribimos:

SELECT GEN_ID(PRODUCTOS_PRD_IDENTI_GEN, 0) FROM RDB$DATABASE

podremos conocer cual es el valor actual del generador llamado PRODUCTOS_PRD_IDENTI_GEN

Y si lo deseamos, también podríamos usar un número negativo en el segundo parámetro.

Otra forma para cambiar el valor de un generador:

Además de usar la función GEN_ID() para cambiar el valor de un generador también podríamos hacerlo así:

SET GENERATOR PRODUCTOS_PRD_IDENTI_GEN TO 157;

cuando se ejecute ese comando el valor del generador PRODUCTOS_PRD_IDENTI_GEN será 157

Los generadores cuyos valores les asignó la función GEN_IDE() están afuera de las transacciones

Cuando la función GEN_ID() le asigna un valor a un generador, lo hace en su propia transacción, afuera de cualquier otra transacción que esté activa en ese momento. Eso significa que el valor asignado al generador permanece en él, no cambia, sin importar que la transacción finalice con un COMMIT o con un ROLLBACK.

Ejemplo:

El valor del generador antes de llamar a la función GEN_ID() es 211

Se llama a la función GEN_ID()

El valor del generador es ahora 212

La transacción donde se encuentra la función GEN_ID() terminó con un ROLLBACK

El valor del generador sigue siendo 212

¿Es conveniente cambiar manualmente el valor de un generador?

Depende de para que lo uses, si lo estás usando para asignarle valores a la columna que tienes definida como Primary Key la respuesta es un rotundo NO.

Podrías cambiarlo, si lo deseas, pero eso solamente podría acarrearte problemas y ningún beneficio.

¿Por qué no es conveniente cambiar el valor de un generador que se usa en una Primary Key?

Porque entonces pierdes la principal ventaja de usar un generador en la Primary Key: la seguridad 100% de que sus valores jamás se repetirán. Si disminuyes su valor, dos usuarios podrían intentar usar el mismo valor del generador y ese conflicto ocasionará pérdida de tiempo.

Pero las Primary Key tienen valores salteados, en una tabla pasaron del 226 al 231, faltan 4 números ahí.

Sí. ¿Y qué? ¿cuál es el problema con eso? Las Primary Key sirven para identificar a una fila exactamente, sin confusión posible. Que haya números faltantes no importa, mientras la Primary Key identifique exactamente a cada fila funciona perfectamente, esa es su utilidad, para eso sirve.

Pero a mí no me gusta que falten números, en los informes queda feo y a mis clientes tampoco les gusta

Estás confundiendo las cosas. Una cosa es la Primary Key y otra cosa distinta es el código de un ítem.

Mucha gente usa a los códigos como Primary Key pero eso es un error de concepto. Una Primary Key sirve para identificar a una fila internamente, en cambio un código sirve para identificar a una fila externamente.

Desde luego que en una tabla puedes tener ambos y eso es lo usual. Pero no confundas el uno con la otra.

La confusión ocurre porque el código pueden ser usado internamente y la Primary Key puede ser usada externamente, pero no deberían mezclarse. ¿Quieres relacionar una tabla con otra tabla? Usa la Primary Key. ¿Quiéres mostrarle una consulta al usuario? Usa el código. Y para que los informes queden bien bonitos como te gusta a tí y le gusta a tu cliente, esos códigos sí puedes numerarlos de 1 en 1, sin que falte ninguno.

Pero no cambies el valor de la Primary Key. Es realmente muy estúpido hacer eso. Te tomará más tiempo y solamente podrás tener problemas y ningún beneficio.

Artículo relacionado:

El índice del blog Firebird21