Curso de PL/SQL Pág 1 de 5

Anuncio
Curso de PL/SQL
9.2.2 CREACION DE TRIGGERS ROW
Como ya hemos dicho, los triggers 'row' se ejecutan una vez para
cada registro afectado por la sentencia DML que lo disparó. Es decir: si
realizamos un UPDATE de varios registros, el código del trigger se ejecuta
una vez para cada registro modificado. Este tipo de triggers se usa mucho
para realizar acciones automatizadas como pueden ser, por ejemplo,
cálculos de importes acumulados, etc... o acciones automatizadas derivadas
de la actualización y/o borrado de registros, como por ejemplo al
modificar un campo de domiciliación bancaria de un cliente, cambiar los
recibos pendientes de remesar de ese cliente para que se giren por el
nuevo banco.
Disponemos, además, de los valores “viejo” y “nuevo” de cada campo
de cada registro que se ve afectado para poder interactuar y/o decidir qué
acciones realizamos dentro del cuerpo del disparador.
La sintaxis de un trigger a nivel de registro es:
CREATE [OR REPLACE] TRIGGER nombre_trigger BEFORE|AFTER evento
ON nombre_tabla [REFERENCING OLD AS nombre_viejo | NEW AS nombre_nuevo]
FOR EACH ROW
[WHEN condicion]
bloque PL/SQL ;
La clausula REFERENCING especifica (si es incluye) los “prefijos”
para utilizar los valores viejos y nuevos de los campos del registro
actual que queramos usar en el cuerpo del trigger. Si no la escribimos,
estos prefijos son por defecto :OLD y :NEW
Evidentemente la clausula FOR EACH ROW especifica que éste es un
trigger a nivel de registro (“para cada registro”).
La clausula WHEN especifica una restricción del trigger. La
condición es evaluada por cada registro para determinar si se ejecuta el
cuerpo del trigger para ese registro o no.
Vamos a ver un ejemplo de este tipo de triggers:
Crearemos un trigger que nos auditará las inserciones, borrados y
modificaciones en la tabla empleados. Ya vimos el mismo ejemplo pero sin
importar cuantas inserciones/borrados/actualizaciones se habían realizado
(trigger statement). Simplemente grabábamos un registro de auditoría de
que se había realizado una acción.
Esta vez, grabaremos un registro de auditoría para cada registro
afectado y además guardaremos los valores “viejo” y “nuevo” de los campos.
Algo muy útil para seguir el rastro de cuando, quién y qué se ha hecho en
nuestra tabla ¿a que si?.
Pág 1 de 5
Curso de PL/SQL
CREATE OR REPLACE TRIGGER audita_emp_valores
AFTER INSERT OR UPDATE OR DELETE ON empleados
FOR EACH ROW
DECLARE
v_usuario VARCHAR2(50);
v_accion VARCHAR2(15);
v_codigo empleados.codigo%type;
BEGIN
--- Recuperamos el usuario de sistema operativo
--- Ojo!! hay que tener permisos para hacer SELECT sobre la
--- tabla v$session
SELECT osuser INTO v_usuario
FROM v$session
WHERE audsid = USERENV('SESSIONID');
--- Determinamos que acción es y qué codigo
--- de empleado debemos grabar
IF INSERTING THEN
v_accion := 'INSERCION';
v_codigo := :new.codigo ;
ELSIF DELETING THEN
v_accion := 'BORRADO';
v_codigo := :old.codigo ;
ELSIF UPDATING THEN
v_accion := 'MODIFICACION';
v_codigo := :old.codigo ;
END IF;
--- Finalmente insertamos el registro de auditoría
--INSERT INTO AUDIT_EMP_DETALLE(usuario, fecha, accion, codigo,
nombre_viejo, nombre_nuevo,
dni_viejo, dni_nuevo,
depart_viejo, depart_nuevo,
salario_viejo, salario_nuevo,
fecha_alta_vieja, fecha_alta_nueva,
jefe_viejo, jefe_nuevo)
VALUES (v_usuario, sysdate, v_accion, v_codigo,
:old.nombre, :new.nombre, :old.dni, :new.dni,
:old.departamento, :new.departamento,
:old.salario, :new.salario,
:old.fecha_alta, :new.fecha_alta,
:old.jefe_viejo, :new.jefe.nuevo);
EXCEPTION
WHEN OTHERS THEN
RAISE_APPLICATION_ERROR(-20400, 'Error al insertar auditoría.
Empleado: '||to_char(v_codigo));
END;
/
Pág 2 de 5
Curso de PL/SQL
Unas puntualizaciones a tener en cuenta en este código:
–
Determinar el código de empleado a grabar (v_codigo) es debido a que si
estamos insertando, el valor :old.codigo es NULL ya que no existía
antes. Por el contrario si estamos borrando, el valor :new.codigo es
NULL. En el caso de modificación grabamos el viejo porque al ser clave
primaria NO se puede modificar, así que nos da igual cual grabar. En
caso de haber desactivado las constraints para modificarlo (hay usuarios
muy avanzados que te montan la de Dios en un momento), tendremos
auditado el codigo viejo y en el registro de la base de datos el valor
del nuevo.
– Al no poner la clausula REFERENCING OLD AS ni el NEW AS, se toman por
defecto :old y :new. Podríamos haber especificado otros nombres.
– La clausula FOR EACH ROW es la que determina que el trigger es “para
cada registro”.
– Hay quien dirá que crear tablas de auditoría duplicando los campos de
cada tabla es tarea demasiado costosa. Cierto. Pero hay otras opciones.
Podemos crear las tablas de auditoría iguales a las originales,
añadiéndoles sólo los campos “usuario, fecha y accion” y grabar dos
registros de auditoría para cada acción en lugar de uno. El primero con
los valores “viejos” y el segundo con los valores “nuevos”. Unicamente
tendremos que modificar el INSERT del trigger del ejemplo y añadir otro
INSERT más. Es más, sólo en el caso de una actualización haría falta
grabar dos registros. En una inserción y en un borrado nos basta con un
registro de auditoría ya que en el primer caso no tenemos valores
“viejos” y en el segundo no tenemos valores “nuevos”.
Dejo como ejercicio el modificar el trigger anterior para que haga
lo que acabamos de comentar.
Por último, podemos (como hemos dicho antes) condicionar un trigger
row mediante la clausula WHEN. ¿Para qué es esto?. Muy sencillo. Hemos
comentado que una sentencia DML que afecta a un grupo de registros,
provocará la ejecución del código del trigger para cada uno de esos
registros. Pues con la clausula WHEN podemos excluir algunos de ellos
mediante una (o varias) condiciones.
En el ejemplo anterior, podríamos sólo auditar las acciones sobre un
empleado (pongamos por caso: 'Pepito Pérez' cuyo codigo es el 45)
simplemente poniendo:
CREATE OR REPLACE TRIGGER audita_emp_valores
AFTER INSERT OR UPDATE OR DELETE ON empleados
FOR EACH ROW
WHEN (new.codigo=45 OR old.codigo=45)
IMPORTANTE: Daros cuenta que los calificadores
prefijados con dos puntos en la clausula WHEN.
“new”
y
“old”
no
van
Pág 3 de 5
Curso de PL/SQL
9.3 CONCEPTOS FINALES SOBRE TRIGGERS
Vamos a ver algunas cosas para terminar con triggers, como puede ser
las diferencias entre trigger y procedimiento almacenado, triggers de BD y
triggers de aplicación, cómo activar o desactivar un trigger y, por
supuesto, cómo borrarlos.
Diferencias entre trigger y procedimientos almacenados
–
–
La sintaxis, por supuesto. CREATE TRIGGER y CREATE PROCEDURE.
Los triggers se llaman de forma ímplicita (el usuario provoca su
disparo de forma transparente) y los procedimientos almacenados
se llaman de forma explícita (el usuario los invoca directamente)
– Las sentencias COMMIT, ROLLBACK y SAVEPOINT no están permitidas
dentro del cuerpo de un trigger. Dentro de un procedimiento
almacenado sí.
– Aunque haya algún error de compilación al crear el trigger, éste
se crea (en estado “no válido”, mejor dicho: “desactivado”).
Diferencias entre trigger de BD y trigger de aplicación
–
–
–
–
–
Un trigger de BD es ejecutado por acciones desde cualquier
herramienta de la BD o de aplicación. Un trigger de aplicación
sólo se ejecuta dentro de dicha aplicación.
El trigger de BD es ejecutado por una sentencia SQL de
manipulación de datos. Un trigger de aplicación puede ser
ejecutado mediante la navegación entre campos, presionando una
tecla, o mediante otras acciones (eventos).
Dos clases de triggers de BD: Statement y row. Los trigger de
aplicación no distinguen.
Durante la ejecución de un trigger de BD, ante un fallo, se
realiza un ROLLBACK sobre la sentencia que disparó el trigger. Si
el trigger es de aplicación debemos controlar nosotros dónde y
hasta dónde hacer un ROLLBACK mediante código.
Un trigger de BD se ejecuta bajo el dominio de seguridad del
autor del trigger. Un trigger de aplicación se ejecuta bajo el
dominio de seguridad del usuario conectado a la BD mediante la
aplicación. (Detalle sutil pero de mucha importancia).
Activar y desactivar triggers de base de datos
Un trigger de base de datos puede estar activado ó desactivado.
Cuando se crea por primera vez, y si no hay ningún fallo de compilación,
se activa automáticamente.
Con ALTER TRIGGER nombre_trigger DISABLE
desactivamos el trigger “nombre_trigger”.
|
ENABLE
activamos
ó
Con ALTER TABLE nombre_tabla DISABLE | ENABLE ALL TRIGGERS activamos
ó desactivamos TODOS los trigger de la tabla “nombre_tabla”.
Con ALTER TRIGGER nombre_trigger COMPILE recompilamos un trigger y
lo activamos si la compilación es correcta.
Borrar triggers de la base de datos
Como era de esperar: DROP TRIGGER nombre_trigger
Pág 4 de 5
Curso de PL/SQL
Resumiendo: La implementación
añaden muchas características:
–
–
–
–
–
–
de
triggers
de
base
de
datos
nos
Seguridad: Los triggers permiten el acceso a tablas según el valor de
los datos
Auditorías: Los triggers “siguen” los valores de las operaciones de
datos sobre las tablas. Los motores de BD que tiene características de
auditoría, normalmente “siguen” las operaciones de datos sobre las
tablas.
Integridad de datos: Con los trigger podemos implementar reglas
complejas de integridad adicionalmente a las que posea la BD.
Replicación de tablas: Mediante trigger podemos replicar de forma
síncrona las tablas deseadas.
Datos derivados: Mediante triggers de BD podemos implementar el cálculo
de datos derivados en tablas, permitiendo así una actualización
automática de dischos datos.
Control
de
eventos:
Los
triggers
controlan
eventos
de
forma
transparente.
10. AGRADECIMIENTOS
Como siempre a mi mujer por su paciencia, a los usuarios del foro de
hackxcrack por su interés y sus opiniones y, finalmente, a mi sobrina Alba
que, con tres meses y medio, ya apunta un “interés” por todo lo
tecnológico (todo lo quiere coger, jejeje)
11. BIBLIOGRAFIA
Introducción al PL/SQL – Oracle Corp.
Desarrollo de aplicaciones con PL/SQL, Volúmenes I y II – Oracle Corp.
Apuntes de los cursos de Certificación Oracle – Jorge Navarrete.
PL/SQL User's Guide and Reference - Oracle Corp.
Using Oracle 8 – Tiger.
Este manual puede ser distribuido y/o reproducido total o parcialmente en
cualquier medio siempre y cuando se cite al autor y la fecha abajo
citadas:
Jorge Navarrete Olmos
[email protected]
Abril de 2004
Valencia
Pág 5 de 5
Descargar