Los triggers (desencadenantes, en castellano) son rutinas, procedimientos, código fuente, que se ejecutan en forma automática cuando se cumple alguna de estas condiciones:
- Se está insertando una nueva fila
- Se está borrando una fila
- Se está actualizando una fila
¿Para qué sirven?
- Para asegurarnos que en la tabla se guarden datos válidos y solamente datos válidos.
- Para actualizar otra tabla cuyos datos dependen de esta tabla
Los triggers pueden «dispararse»:
- Antes de la inserción, borrado, actualización
- Después de la inserción, borrado, actualización
Los triggers que se disparan antes sirven para evitar que la tabla tenga datos inválidos
Los triggers que se disparan después sirven para actualizar a otras tablas cuyos datos dependen de esta tabla
Lo peor que le podría ocurrir a una tabla es tener datos inválidos o incorrectos dentro suyo. El nombre conque se conoce a dichos datos es «basura«. Si eres un buen programador, jamás permitirás que entre basura en una tabla tuya.
En los triggers se pueden usar unas «pseudo» variables llamadas NEW y OLD.
NEW nos indica el valor que tiene una columna antes de ser insertada en la tabla.
OLD nos indica el valor que tiene actualmente la columna en la tabla. O sea el valor que está grabado en ella.
NEW y OLD son muy útiles para comparar el valor que queremos introducir en una columna con el valor que ya está guardado en esa columna.
Por ejemplo, para detectar si el nuevo precio de venta es menor que el actual precio de venta podríamos escribir:
IF (NEW.PRD_PREVTA < OLD.PRD_PREVTA) THEN
Para detectar si el nuevo precio de venta es cero o menor que cero podríamos escribir:
IF (NEW.PRD_PREVTA <= 0) THEN
Para detectar si el nombre del producto está vacío podríamos escribir:
IF (CHAR_LENGTH(TRIM(NEW.PRD_NOMBRE)) = 0) THEN
Para detectar si el código del producto es NULL podríamos escribir:
IF (NEW.PRD_CODIGO IS NULL) THEN
En el caso de encontrar algún error debes elevar una EXCEPCIÓN y así conseguirás que la fila no sea insertada ni borrada ni actualizada.
Una tabla puede tener muchos triggers, el orden en que se ejecutan viene dado por el valor de POSITION. El primer trigger que se ejecuta es el que tiene POSITION 0, luego se ejecuta el que tiene POSITION 1, luego el que tiene POSITION 2, etc.
Resumiendo:
- Los triggers son código fuente que se ejecuta automáticamente cuando se quiere:
- Insertar una nueva fila
- Borrar una fila
- Actualizar una fila
- Sirven para asegurar que en una tabla solamente se introduzcan datos válidos y para actualizar otras tablas cuyos datos dependen de esta tabla
- Los triggers pueden dispararse:
- Antes de la inserción, borrado, actualización
- Después de la inserción, borrado, actualización
- Dentro de los triggers se pueden usar dos pseudo-variables: NEW y OLD
- NEW es el valor que tendrá la columna si se realiza la inserción o actualización exitosamente
- OLD es el valor que actualmente tiene la columna
- Si se encontró un error en un trigger se debe elevar una excepción para que esa fila no sea insertada ni borrada ni actualizada
- Una tabla puede tener muchos triggers, el orden en el cual se ejecutan lo determina la variable POSITION
Artículos relacionados:
Entendiendo las excepciones | Firebird SQL
May 12, 2013 @ 12:03:09
Como distinguir el tipo de UPDATE | Firebird SQL
Jun 01, 2013 @ 12:50:08
Generando códigos dependientes | Firebird SQL
Jun 08, 2013 @ 14:35:55
El índice del blog Firebird21 | Firebird SQL
Jun 17, 2013 @ 04:46:11
Gustavo Zavala
Jun 27, 2013 @ 13:59:49
Muy buen post, muy entendible
wrov
Jun 27, 2013 @ 15:29:28
Gracias Gustavo, que bueno que te haya resultado útil.
Saludos.
Walter.
Similitudes y diferencias entre stored procedures y triggers | Firebird SQL
Jun 28, 2013 @ 22:30:46
Eric Natareno Guerra
Oct 03, 2020 @ 04:45:55
Walter, serias tana amable de ayudarme con este asunto, tengo 2 columnas de tiempo, pero estas columnas como ya se sabe son texto y yo necesito sacar la diferencia entre ellas y grabar el resultado en una tercera columna en segundos columna integer, ejemplo TIEMPOINI 01:39:40 TIEMPOFIN 01:45:20 TIEMPO = TIEMPOFIN – TIEMPOINI TIEMPO seria 340 segundos, he pensado escribir un Trigger y colocar alli esas operaciones After Update. El problema es que debo desarmar cada columna y operar los números por separado, pero no se como trabajar las variables dentro del trigger o en general en Firebird. Por atención muy agradecido. Atte, Eric Natareno Guerra
wrov
Oct 04, 2020 @ 19:56:55
Hola Eric
Aquí tienes un ejemplo de un trigger. Lo que hace es generar automáticamente el código del cliente. Toma las 2 primeras letras del nombre y luego le agrega un número de 4 dígitos. Por lo tanto el código del cliente tendrá siempre 6 caracteres.
Digamos que tienes un cliente cuyo nombre es JUAN, otro cliente cuyo nombre es JULIO, otro cliente cuyo nombre es JUSTINIANO. Los códigos serán: JU0001, JU0002, JU0003. Esos códigos no los elige el usuario sino que los genera este trigger.
CREATE TRIGGER CLIENTES_BI FOR CLIENTES
ACTIVE BEFORE
INSERT
POSITION 1
AS
DECLARE VARIABLE lcCodBus CHAR(2); -- Código buscado. Las 2 primeras letras del nombre del cliente
DECLARE VARIABLE lcUltCod TYPE OF COLUMN CLIENTES.CLI_CODIGO; -- Último código. El último código que empieza con esas 2 primeras letras
DECLARE VARIABLE lnUltNum SMALLINT; -- Último número. El número que tiene el último código
DECLARE VARIABLE lcNueNum CHAR(4); -- Nuevo número. El último número hallado + 1, para obtener el nuevo número y convertirlo a string
BEGIN
lcCodBus = LEFT(TRIM(REPLACE(NEW.CLI_NOMBRE, ' ', '')), 2); -- Las 2 primeras letras del nombre del cliente
IF (CHAR_LENGTH(TRIM(lcCodBus)) < 2) THEN
EXCEPTION E_NOMBRE_CLIENTE_MUY_CORTO; -- Si el nombre del cliente está vacío o tiene solamente una letra
lcUltCod = (SELECT
CLI_CODIGO
FROM
CLIENTES
WHERE
LEFT(CLI_CODIGO, 2) = :lcCodBus
ORDER BY
CLI_CODIGO DESCENDING
ROWS
1) ;
lnUltNum = IIF(lcUltCod IS NULL, 0, CAST(RIGHT(TRIM(lcUltCod), 4) AS SMALLINT)); -- Si no encontró el código buscado, el último número es 0
lcNueNum = LPAD(lnUltNum + 1, 4, '0'); -- Le agrega ceros a la izquierda para que en total tenga 4 dígitos
NEW.CLI_CODIGO = lcCodBus || lcNueNum; -- El nuevo código se compone por las 2 letras buscadas más un número de 4 dígitos
END;
Saludos.
Walter.
Eric Natareno Guerra
Oct 06, 2020 @ 20:49:00
Muchas gracias Walter, es lo que necesito, la estructura, como definir las variables y hasta el comando para extraer los datos que necesito. Saludos y nuevamente muchas gracias
Eric Natareno Guerra
Oct 07, 2020 @ 14:03:50
Hola Walter, de nuevo molestandote, fijate que tengo un procedimiento almacenado para actualizar una tabla, pero necesito hacer unos calculos antes de actualizar, el asunto es que declaro unas variables, pero al asignarles valor me da este error
Engine Error (code = 335544569):
Dynamic SQL Error.
SQL error code = -104.
Token unknown – line 12, column 4.
LCSEGUNDOS1.
el Stored Procedure es el siguiente
SET TERM ^ ;
ALTER PROCEDURE GRABAR_ACTIVIDAD_FIN (
VFINAL VARCHAR(8),
VTIEMPO INTEGER,
VOBSERVAC VARCHAR(100),
IDBASE INTEGER)
AS
DECLARE VARIABLE LCSEGUNDOS1 INT;
DECLARE VARIABLE LCSEGUNDOS2 INT;
DECLARE VARIABLE VINICIO CHAR(8);
BEGIN
VINICIO = (select inicio from actividad where niu = :idbase
LCSEGUNDOS1 = 1
lcSegundos2 = CAST(substring(Vfinal from 7 for 2) AS INT())
UPDATE ACTIVIDAD
SET FINAL = :VFINAL, TIEMPO = :VTIEMPO, OBSERVAC = :VOBSERVAC
WHERE NIU = :IDBASE;
END^
SET TERM ; ^
le asigne un 1 a LCSEGUNDOS1 por probar si estaba malo el comando pero no me acepta absolutamente nada, te agradezco por tu atención y tiempo Walter.
Saludos amigo
wrov
Oct 10, 2020 @ 00:44:47
Hola Eric
En Firebird no existe el tipo de datos INT, el que existe es el tipo de datos INTEGER.
Reemplaza los INT por INTEGER y vuelve a probar.
Saludos.
Walter.
Eric Natareno Guerra
Oct 10, 2020 @ 02:54:40
Cierto, gracias Walter
________________________________