Las Primary Keys (claves primarias) son una parte importantísima a considerar cada vez que se diseña una Base de Datos o una tabla dentro de una Base de Datos.

¿Por qué?

Porque toda fila de una tabla necesitará, más temprano o más tarde, ser identificada exactamente, sin lugar a dudas. Y esa es justamente la utilidad de la Primary Key, para eso sirve.

Una Primary Key:

  1. No puede tener valores repetidos
  2. No puede tener valores nulos

Si tuviera valores repetidos evidentemente que no servirá para identificar a una fila exactamente, ya que habría dos o más filas con el mismo identificador. Y si pudiera tener valores nulos ocurriría el mismo problema, que dos o más filas tengan valores nulos ¿y cómo identificar a una sola de ellas en ese caso? sería imposible. Por lo tanto, las Primary Keys no pueden tener ni valores repetidos ni valores nulos.

Cuando estableces una restricción de Primary Key el Firebird automáticamente crea un índice para esa restricción ¿Por qué? porque así puede muy rápidamente descubrir si el valor que le asignas a la columna establecida como Primary Key está repetido. Y si está repetido por supuesto que lo rechazará, ya que las Primary Keys no pueden tener valores repetidos.

Una Primary Key puede estar compuesta por una columna o por más de una columna lo único realmente importante a recordar es que no puede haber ni valores repetidos ni valores nulos en esa columna (o en esas columnas, si son más de una).

Un error relativamente frecuente entre los principiantes es declarar como Primary Key a una columna que sirve para otra cosa también, no se la usa solamente como Primary Key sino para algo más también.

Por ejemplo, el número del documento de identidad, el número de la Factura de venta, el número de la cuenta contable. Aunque ninguno de estos números estén repetidos no deberían usarse como Primary Key. Pueden ser usados porque no están repetidos ni son nulos, pero no deberían usarse. ¿Y por qué no deberían usarse? porque sirven para algo más. Por ejemplo el número del documento de identidad sirve para identificar a las personas y puede aparecer en muchos informes. Y esa no es la función de una Primary Key.

En general, lo mejor es que sea el propio Firebird quien le asigne sus valores a la Primary Key ya que de esa manera te asegurarás que no existan ni valores repetidos ni valores nulos. ¿Y cómo consigues eso? Mediante un un generador (también llamado secuencia) y un trigger.

Los programas administradores gráficos del Firebird (como Flame Robin, SQL Manager, etc.) hacen eso automáticamente cuando creas una Primary Key pero si no dispones de uno de esos programas o si quieres saber lo que ocurre aquí está la explicación:

  • Se crea un generador para usarlo como Primary Key. Un generador es un número (también llamado secuencia) cuyos valores son asignados por el Firebird en forma automática, no los asigna ni el programador ni el usuario sino que lo hace el propio Firebird
    • Ese generador (como todos los generadores) es mantenido afuera de todas las transacciones de los usuarios. O sea que una vez que se le asignó un valor a un generador ese valor permanece y no es cambiado aunque la transacción sea desechada
    • El programador puede cambiar el valor de un generador pero eso no es recomendable hacer porque puede causar graves daños. Lo mejor y recomendado es dejarlo al Firebird que se encargue de asignarle valores al generador
  • Se crea un trigger que se activa antes de insertarle datos a la tabla. En ese trigger se usa la función GEN_ID(). Lo que hace esa función es sumar algebraicamente a su primer argumento el número que se encuentre en su segundo argumento. Por ejemplo:
    • GEN_ID(MiNumero, 1)                   — Le sumará 1 a la variable MiNumero
    • GEN_ID(SegundoNumero, 2)      — Le sumará 2 a la variable SegundoNumero
    • GEN_ID(OtroNumero, -5)             — Le restará 5 a la variable OtroNumero
    • GEN_ID(NumeroActual, 0)          — Le sumará 0 a la variable NumeroActual
  • El valor que se le asignó al generador es asignado a la columna que se declaró como Primary Key.

Aquí está un ejemplo:

SET TERM ^ ;

CREATE TRIGGER BI_VENTAS_VEN_IDENTI FOR VENTAS ACTIVE BEFORE INSERT POSITION 0
AS
BEGIN
   IF (NEW.VEN_IDENTI IS NULL OR NEW.VEN_IDENTI = 0) THEN
      NEW.VEN_IDENTI = GEN_ID(VENTAS_VEN_IDENTI_GEN, 1);
END^

SET TERM ; ^

Fíjate en lo que está entre el BEGIN y el END^ por el resto del código no te preocupes todavía. En este caso VEN_IDENTI es la Primary Key. Lo que se le está diciendo al Firebird es lo siguiente: “si el valor que tiene VEN_IDENTI antes de la inserción en la tabla es nulo o si el valor que tiene VEN_IDENTI antes de la inserción en la tabla es cero entonces asígnale a VEN_IDENTI el valor que obtendrás cuando al generador VENTAS_VEN_IDENTI_GEN le sumes uno”

Así que si por ejemplo VENTAS_VEN_IDENTI_GEN tenía como valor 5, después de GEN_ID() tendrá 6 y el número 6 será el asignado a la columna VEN_IDENTI.

Y por lo tanto, (si es que el Firebird no encuentra algún error antes de la inserción) el valor que tendrá la columna VEN_IDENTI cuando termine la inserción será 6.

Por supuesto que los nombres de tus generadores pueden ser más cortos, no es necesario que sean tan largos como en este ejemplo.

Resumiendo:

  • Las Primary Keys cumplen un papel importantísimo en el diseño de las tablas y de las bases de datos
  • Sirven para identificar, sin equivocación posible, a cada fila de una tabla
  • No pueden tener valores repetidos
  • No pueden tener valores nulos
  • El Firebird automáticamente le crea un índice a cada Primary Key y usa ese índice para descubrir rápidamente si se quiere insertar un valor que ya existe
  • Una Primary Key puede estar compuesta por una sola columna o por varias columnas
  • No se debería usar como Primary Key a una columna que tiene otra utilidad, que sirve para algo más (como el Documento de Identidad o el Número de la Factura). La Primary Key debe servir para Primary Key y para nada más
  • Lo mejor es que sea el propio Firebird quien se encargue de asignarle valores a las Primary Keys porque eso le ahorra trabajo al programador y además le asegura que no tendrá ni valores repetidos ni valores nulos
  • Las Primary Keys pueden ser creadas automáticamete por programas de administración gráfica como Flame Robin y SQL Manager. Lo que hacen esos programas es:
    • Crear un generador
    • Crear un trigger
    • Dentro de ese trigger asignarle un valor al generador y luego el valor del generador asignarlo a la columna que se definió como Primary Key