Está en la página 1de 21

TRIGGERS DE BASE DE DATOS

Un disparador define una acción que la base de datos debe llevar a cabo

cuando se produce algún suceso relacionado con la misma. Los

disparadores (triggers) pueden utilizarse para completar la integridad

referencial, también para imponer reglas de negocio complejas o para

auditar cambios en los datos. El código contenido en un disparador,

denominado cuerpo del disparador, está formado por bloques PL/SQL.

La ejecución de disparadores es transparente al usuario.


En un ambiente distribuido se deben aplicar triggers para controlor los

siguientes aspectos:

• La integridad referencial entre las tablas que se encuentran en sitios

diferentes

• La relación de los predicados de fragmentanción complejos

definidos sobre las tablas propietarias que no pueden controlar con

restricciones de chequeo
Triggers para controlar la integridad referencial entre sitios

Se requiere de un trigger en la tabla para controlar

• Que no se puedan eliminar registros que poseen referencias en la

tabla detalles

•Que no se pueda eliminar la clave primaria de los registros que ya

poseen referencias en la tabla detalles


Se requiere de un trigger en la tabla detalles para controlar:

• Que no se pueda insertar registros que no posean una referencia

válida a la clave primaria de algún registro de la tabla maestra

•Que solo se pueda actualizar la clave foránea de los registros con

valores que hagan referencia a la clave primaria de algún registro

existente en la tabla maestra.


Para crear un disparador (trigger) en una tabla, el usuario con el que

accedamos a Oracle deberá ser propietario de la misma, teniendo así el

privilegio ALTER para la tabla ó ALTER ANY TABLE. Además, dicho

usuario, debe disponer del privilegio CREATE TRIGGER.


Existen varios tipos de TRIGGERS, dependiendo del tipo de transacción

de disparo y el nivel en el que se ejecuta el disparador (trigger):

1.- Disparadores de nivel de fila: se ejecutan una vez para cada fila

afectada por una instrucción DML. Los disparadores de nivel de fila se

crean utilizando la cláusula for each row en el comando create trigger.


2.- Disparadores de nivel de instrucción: se ejecutan una vez para cada

intrucción DML. Por ejemplo, si una única intrucción INSERT inserta

500 filas en una tabla un disparador de nivel de instrucción para dicha

tabla sólo se ejecutará una vez. Los disparadores de nivel de instrucción

son el tipo predeterminado que se crea con el comando create trigger.


3.- Disparadores Before y After: puesto que los disparadores son

ejecutados por sucesos, puede establecerse que se produzcan

inmediatamente antes (before) o después (after) de dichos sucesos.


4.- Disparadores Instead Of: puede utilizar INSTEAD OF para indicar

a Oracle lo que tiene que hacer en lugar de realizar las acciones que

invoca el disparador. Por ejemplo, podría usar un disparador INSTEAD

OF en una vista para gestionar las inserciones en una tabla o para

actualizar múltiples tablas que son parte de una vista.


5.- Disparadores de esquema: puede crear disparadores sobre

operaciones en el nivel de esquema tales como create table, alter table,

drop table, audit, rename, truncate y revoke. Puede incluso crear

disparadores para impedir que los usuarios eliminen sus propias tablas.

En su mayor parte, los disparadores de nivel de esquema proporcionan

dos capacidades: impedir operaciones DDL y proporcionar una seguridad

adicional que controle las operaciones DDL cuando éstas se producen.


6.- Disparadores en nivel de base de datos: puede crear disparadores

que se activen al producirse sucesos de la base de datos, incluyendo

errores, inicios de sesión, conexiones y desconexiones. Puede utilizar

este tipo de disparador para automatizar el mantenimiento de la base de

datos o las acciones de auditoría.


Creating DML Triggers
• Create DML statement or row type triggers by using:

CREATE [OR REPLACE] TRIGGER trigger_name


timing
event1 [OR event2 OR event3]
ON object_name
[[REFERENCING OLD AS old | NEW AS new]
FOR EACH ROW
[WHEN (condition)]]
trigger_body

• A statement trigger fires once for a DML statement.


– A row trigger fires once for each row affected.
• Note: Trigger names must be unique with respect to other
triggers in the same schema.
Trigger Timing
• When should the trigger fire?
– BEFORE: Execute the trigger body before the
triggering DML event on a table.
– AFTER: Execute the trigger body after the
triggering DML event on a table.
– INSTEAD OF: Execute the trigger body
instead of the triggering statement. This is
used for views that are not otherwise
modifiable.
• Note: If multiple triggers are defined for
the same object, then the order of firing
triggers is arbitrary.
Trigger-Firing Sequence
• Use the following firing sequence for a
trigger on a table when a single row is
manipulated:
DML statement
INSERT INTO departments
(department_id,department_name, location_id)
VALUES (400, 'CONSULTING', 2400);

Triggering action BEFORE statement


trigger

… BEFORE row trigger


AFTER row trigger
AFTER statement trigger
Trigger-Firing Sequence
• Use the following firing sequence for a
trigger on a table when many rows are
manipulated:
UPDATE employees
SET salary = salary * 1.1
WHERE department_id = 30;

BEFORE statement trigger


BEFORE row trigger
AFTER row trigger
...
BEFORE row trigger
AFTER
... row trigger
AFTER statement trigger
Trigger Event Types and Body
• A trigger event:
– Determines which DML statement causes the
trigger to execute
– Types are:
• INSERT
• UPDATE [OF column]
• DELETE
• A trigger body:
– Determines what action is performed
– Is a PL/SQL block or a CALL to a procedure
Creating a DML Statement
Trigger
Application
EMPLOYEES table
INSERT INTO EMPLOYEES...;

SECURE_EMP trigger

CREATE OR REPLACE TRIGGER secure_emp


BEFORE INSERT ON employees BEGIN
IF (TO_CHAR(SYSDATE,'DY') IN ('SAT','SUN')) OR
(TO_CHAR(SYSDATE,'HH24:MI')
NOT BETWEEN '08:00' AND '18:00') THEN
RAISE_APPLICATION_ERROR(-20500, 'You may insert'
||' into EMPLOYEES table only during '
||' business hours.');
END IF;
END;
Testing SECURE_EMP

INSERT INTO employees (employee_id, last_name,


first_name, email, hire_date,
job_id, salary, department_id)
VALUES (300, 'Smith', 'Rob', 'RSMITH', SYSDATE,
'IT_PROG', 4500, 60);
Creating a DML Row Trigger

CREATE OR REPLACE TRIGGER restrict_salary


BEFORE INSERT OR UPDATE OF salary ON employees
FOR EACH ROW
BEGIN
IF NOT (:NEW.job_id IN ('AD_PRES', 'AD_VP'))
AND :NEW.salary > 15000 THEN
RAISE_APPLICATION_ERROR (-20202,
'Employee cannot earn more than $15,000.');
END IF;
END;
/
Using OLD and NEW Qualifiers

CREATE OR REPLACE TRIGGER audit_emp_values


AFTER DELETE OR INSERT OR UPDATE ON employees
FOR EACH ROW
BEGIN
INSERT INTO audit_emp(user_name, time_stamp, id,
old_last_name, new_last_name, old_title,
new_title, old_salary, new_salary)
VALUES (USER, SYSDATE, :OLD.employee_id,
:OLD.last_name, :NEW.last_name, :OLD.job_id,
:NEW.job_id, :OLD.salary, :NEW.salary);
END;
/
Implementing an Integrity Constraint
with a Trigger
UPDATE employees SET department_id = 999
WHERE employee_id = 170;
-- Integrity constraint violation error
CREATE OR REPLACE TRIGGER employee_dept_fk_trg
AFTER UPDATE OF department_id
ON employees FOR EACH ROW
BEGIN
INSERT INTO departments VALUES(:new.department_id,
'Dept '||:new.department_id, NULL, NULL);
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
NULL; -- mask exception if department exists
END;
/
UPDATE employees SET department_id = 999
WHERE employee_id = 170;
-- Successful after trigger is fired

También podría gustarte