Triggers en PL/SQL - Universidad de Antioquia

Anuncio
Triggers en PL/SQL
Jonathan Medina Gómez
Facultad de Ingeniería
Universidad de Antioquia
Triggers (Disparadores)
● Los triggers son bloques PL/SQL que se ejecutan
de manera implícita cuando se están manipulando
(INSERT, DELETE, UPDATE) los datos de una
tabla.
● Son usados principalmente para establecer reglas
de integridad complejas y labores de auditoría.
Triggers (Disparadores) II
●
La ejecución de un trigger es transaccional, es decir, si un trigger de fila afecta n
registros y si uno solo de ellos aborta,entonces todo el proceso se cancela.
●
El orden de ejecución de los triggers es el siguiente:
1. Se ejecutan (si los* hay) los triggers BEFORE de operación.
2. Se ejecutan para cada fila:
a. (Si los* hay) los triggers BEFORE de fila.
b. Se ejecuta la operación DML correspondiente.
c. (Si los* hay) los triggers AFTER de fila.
3. Se ejecutan (si los* hay) los triggers AFTER de operación
* Si hay varios triggers con idéntica definición (a partir de Oracle 8i), el orden de
ejecución entre ellos es “aleatorio”.
Un trigger tiene asociado:
● Un Evento: se refiere a la operación que se va a
efectuar sobre la tabla (INSERT, DELETE o UPDATE).
● Un Momento: significa cuando se debe disparar el
trigger en relación con el evento. Sus posibles valores
son AFTER o BEFORE.
● Un Tipo: indica el número de veces que el cuerpo del
trigger se debe ejecutar, si por la operación en conjunto
(trigger de operación) o por cada fila procesada (trigger
de fila).
Sintaxis
CREATE [OR REPLACE] TRIGGER nombre_trigger
momento evento ON tabla
[ FOR EACH ROW [ WHEN condición de restricción] ]
bloque de PL/SQL
● Cuando el evento es UPDATE, se puede(n) especificar la(s)
columna(s) con la palabra OF (si no se especifican, el trigger se
dispara con cualquiera de las columnas de la tabla que sea
actualizada).
El bloque comienza con la palabra DECLARE o BEGIN.
Referencia a valores antes y
después de la operación
Cuando es un trigger
de fila, se puede hacer
referencia al valor de
una columna antes del
cambio por medio de :
OLD.columna y al valor
después del cambio
con :NEW.columna.
EVENTO
VALOR
ANTERIOR
VALOR NUEVO
INSERT
NULL
El insertado
DELETE
Valor antes del
borrado
NULL
UPDATE
Valor antes de la
actualización
Valor después de la
actualización
Ejemplo Trigger de operación
Sea la tabla de productos:
CREATE TABLE PRODUCTO( codigo NUMBER(6) PRIMARY KEY, precio NUMBER(6));
CREATE OR REPLACE TRIGGER control_inserción BEFORE INSERT ON producto
BEGIN
IF (TO_CHAR(SYSDATE,'DAY') IN ('SAT','SUN'))
OR (TO_NUMBER(TO_CHAR(SYSDATE,'HH24')) NOT BETWEEN 8 AND 18)
THEN
RAISE_APPLICATION_ERROR(-20506,'Sólo se pueden ingresar productos en
horario de oficina');
END IF;
END;
/
La instrucción RAISE_APPLICATION_ERROR abortará la operación de inserción
si ésta se intenta realizar en el horario no permitido.
Ejemplo Trigger de fila
Supóngase la siguiente condición en una empresa:
●
●
Ningún empleado puede ganar más que su jefe
Supóngase que los jefes se manejan en una tabla separada a la de los empleados
Sean las tablas:
CREATE TABLE jefe(
cedula NUMBER(5) PRIMARY KEY,nombre VARCHAR2(10) NOT NULL,
salario NUMBER(8) NOT NULL, secretaria VARCHAR2(10));
CREATE TABLE emp(
cedula NUMBER(10) PRIMARY KEY,
nombre VARCHAR2(10) NOT NULL,
jefe NUMBER(5) NOT NULL REFERENCES jefe,--Clave foránea
salario NUMBER(8) NOT NULL);
Ejemplo Trigger de fila (II)
CREATE OR REPLACE TRIGGER el_jefe_gana_mas BEFORE INSERT ON emp
FOR EACH ROW
DECLARE
salario_jefe jefe.salario%TYPE;
BEGIN
SELECT salario INTO salario_jefe
FROM jefe WHERE cedula = :NEW.jefe;
IF salario_jefe < :NEW.salario THEN
RAISE_APPLICATION_ERROR(-20505,'Un empleado no puede ganar más que su
jefe');
END IF;
END;
/
Ejercicios:
Considerar lo siguiente:
●
●
●
Si a un empleado le actualizan su salario, que éste no vaya a quedar más
alto que el de su jefe.
Si a un empleado le cambian de jefe no le vayan a asignar uno que gane
menos que él.
Si a un jefe le bajan el salario se debe verificar que no quede más bajo
que el de alguno de sus subordinados.
¿Puede una persona figurar al mismo tiempo tanto en la tabla de empleados
como en la de jefes?
¿Cómo manejar el despido de jefes? ¿Qué hacer
con sus subordinados?
La cláusula WHEN
Sirve para agregar una condición adicional para activar el trigger
• Para referirse a NEW y a OLD no se usan los dos puntos dentro de la
condición de WHEN
Ejemplo. Sean las tablas:
CREATE TABLE producto(
codigo NUMBER(3) PRIMARY KEY,precio NUMBER(4));
CREATE TABLE auditoria(
usuario VARCHAR2(20),cuando DATE,
producto NUMBER(6));
Ejemplo WHEN
Usando WHEN
Sin usar WHEN
CREATE or REPLACE TRIGGER
quien_baja_precio
BEFORE UPDATE OF precio ON
producto FOR EACH ROW
WHEN (new.precio < old.precio)
BEGIN
INSERT INTO auditoria
VALUES(USER, SYSDATE,old.codigo);
END;
/
CREATE or REPLACE TRIGGER
quien_baja_precio
BEFORE UPDATE OF precio ON
producto FOR EACH ROW
BEGIN
IF :new.precio < :old.precio THEN
INSERT INTO auditoria
VALUES(USER, SYSDATE,
:old.codigo);
END IF;
END;
/
Conclusión: WHEN evita el uso de un IF explícito dentro del código.
Ejercicio: Guardar el precio “viejo” y nuevo del producto.
Descargar