Agregando una Primary Key

6 comentarios

A veces, necesitamos importar en nuestras tablas de Firebird el contenido existente en otras tablas, quizás .DBF, Access, Paradox, etc., en las cuales no teníamos definida una Primary Key.

Recuerda que en Firebird es súper recomendable que todas las tablas tengan su correspondiente Primary Key (la única excepción son las tablas que tienen una sola fila).

Entonces, luego de crear una tabla en Firebird e importar los datos desde la otra tabla procedemos a agregarle la Primary Key (si es que en el programa de importación ya no lo habíamos hecho) con un stored procedure similar al siguiente:

CREATE PROCEDURE AGREGAR_PRIMARYKEY
AS
   DECLARE VARIABLE lnContador INTEGER;
BEGIN

   FOR SELECT TAR_IDENTI FROM TARJETAS INTO lnContador DO BEGIN
      UPDATE
         TARJETAS
      SET
         TAR_IDENTI = ROW_COUNT + 1;
   END

END;

La columna TAR_IDENTI de la tabla TARJETAS es numérica y su valor podría haber sido cero o NULL en todas las filas. Este stored procedure utiliza a la variable de contexto ROW_COUNT para conocer cual es el número de la fila que se está procesando en el FOR SELECT. Como el valor inicial de ROW_COUNT es cero se le tuvo que sumar uno para que la numeración empezara con 1.

ROW_COUNT es una variable de contexto que está disponible en los stored procedures, triggers y execute block y que nos informa la cantidad de filas que se obtuvieron con el último comando DML (INSERT, UPDATE, DELETE, o FETCH).

Cuando se usa a ROW_COUNT dentro de un FOR SELECT su valor es incrementado en cada iteración, empezando con cero.

Solamente después de ejecutar ese stored procedure con éxito podemos definir a la columna TAR_IDENTI como Primary Key, si lo hubiéramos intentado antes hubiéramos obtenido un error ya que la columna TAR_IDENTI tenía valores repetidos (un cero o un NULL en cada fila de la tabla) y en las Primary Key no pueden existir valores repetidos ni nulos.

Al finalizar el stored procedure y luego del COMMIT correspondiente nos aseguramos que la columna TAR_IDENTI no tiene valores repetidos por lo cual podemos proceder a definirla como Primary Key.

¿Cómo ejecutar este stored procedure?

Tienes 3 formas:

1. Mediante el programa ISQL.EXE que viene incluido con el Firebird:

AGREGAR_PK

(haciendo clic en la imagen la verás más grande)

2. Si usas el programa EMS SQL Manager, mediante la opción “Execute”

AGREGAR_PK2

(haciendo clic en la imagen la verás más grande)

 3. Si usas el programa EMS SQL Manager, también puedes usar el editor SQL

AGREGAR_PK3

(haciendo clic en la imagen la verás más grande)

 En estos dos últimos casos no te olvides de hacer clic sobre la opción COMMIT para que los cambios queden grabados permanentemente.

Anuncios

Como distinguir el tipo de UPDATE

1 comentario

Se puede actualizar (UPDATE) una fila de dos maneras distintas:

  • A través de un UPDATE específico a esa fila
  • A través de un ON UPDATE CASCADE que proviene de una restricción Foreign Key

Ejemplo 1. UPDATE específico

UPDATE
   PEDIDOSDET
SET
   PED_CODPRD = '1223334444'
WHERE
   PED_CODPRD = '1111111111'

Aquí, en la tabla PEDIDOSDET (detalles de pedidos) se cambió el código del producto, reemplazándose a todos los ‘1111111111’ por ‘1223334444’

Ejemplo 2. ON UPDATE CASCADE

UPDATE
   PRODUCTOS
SET
   PRD_CODIGO = '1223334444'
WHERE
   PRD_CODIGO = '1111111111'

Si la tabla PRODUCTOS está relacionada a través de una Foreign Key ON UPDATE CASCADE con la tabla PEDIDOSDET por medio de la columna PRD_CODIGO entonces todos los códigos de los productos de la tabla PEDIDOSDET que eran ‘1111111111’ ahora se cambiaron por ‘1223334444’

¿Cómo se puede distinguir si la modificación se debió a un UPDATE normal o a un UPDATE ON CASCADE?

En general, no vas a necesitar esa información, pero supongamos que por algún motivo sí necesitas conocerla. Entonces puedes hacer lo siguiente:

  1. Le agregas una columna numérica a tu tabla (en este ejemplo a la tabla PEDIDOSDET)
  2. Si es un UPDATE normal entonces incrementas en uno el valor de esa columna
  3. Ahora, en tu trigger de actualización puedes comparar si el nuevo valor es igual al viejo valor
  4. Si son iguales, se trata de un UPDATE ON CASCADE, si son distintos se trata de un UPDATE normal
  5. Le asignas a la nueva columna el valor de la vieja columna

Ejemplo 3. Distinguiendo el tipo de UPDATE

A la tabla PEDIDOSDET se le agregó la columna numérica PED_CANMOD (cantidad de modificaciones)

En el caso de un UPDATE normal se escribiría:

UPDATE
   PEDIDOSDET
SET
   PED_CODPRD = '1223334444',
   PED_CANMOD = PED_CANMOD + 1
WHERE
   PED_CODPRD = '1111111111'

En el trigger “Before Update” se escribiría:

IF (NEW.PED_CANMOD <> OLD.PED_CANMOD) THEN BEGIN     /* UPDATE normal */
   ....
ELSE     /* UPDATE ON CASCADE */
   ...
END

NEW.PED_CANMOD = OLD.PED_CANMOD

Artículos relacionados:

https://firebird21.wordpress.com/2013/05/26/entendiendo-a-las-foreign-keys/

https://firebird21.wordpress.com/2013/03/17/entendiendo-a-los-triggers/