Sie sind auf Seite 1von 30

1

Introduccin

PL/SQL: lenguaje de programacin DECLARE optional

estructurado en bloques BEGIN required

Bloques: unidad mnima en PL/SQL EXCEPTION optional

Soportan DML y DDL


END; required
/

Annimos / Con nombre TRIGGERS


Disparadores (triggers) en Oracle: bloques de cdigo que
son implcitamente invocados cuando algo sucede
Triggers vs. Procedimientos CREATE TRIGGER
NombreTrigger
Ejecucin implcita: Disparar BEFORE INSERT ON StarsIn
DECLARE
No admiten argumentos ..
END;
Aplicaciones / TRIGGER

Restricciones (Constraints)
CREATE PROCEDURE Get_emp_rec
(Emp_number IN
Emp_tab.Empno%TYPE) AS
Auditoras BEGIN

Informar de eventos
- - - - -
END;
/ PROCEDIMIENTO
2
2
Introduccin

3 Tipos
DML/DDL (Fila/Sentencia, BEFORE/AFTER)
INSTEAD OF
SYSTEM

3
3
Estructura General de un Disparador

Evento
CREATE [OR REPLACE] TRIGGER nombre
{BEFORE | AFTER | INSTEAD OF} Temporalidad del Evento
{INSERT | DELETE | UPDATE [OF <atributo>]} ON <tabla>

[FOR EACH ROW | STATEMENT] Granularidad


Condicin
[WHEN condicin]

[DECLARE]

BEGIN
cuerpo del trigger
[EXCEPTION] Accin

END;
/
4
4
Estructura General de un Disparador. Ejemplo

CREATE OR REPLACE TRIGGER generaNuevoPedido


AFTER UPDATE OF unid_disponibles ON Inventario Evento

FOR EACH ROW Condicin


WHEN (new.unid_disponibles < new.unid_solicitadas)

DECLARE
x NUMBER; Accin
BEGIN
-- Nmero de pedidos pendientes de ese producto
SELECT COUNT(*) INTO x FROM PedidosPendientes
WHERE num_producto=:num_producto;
-- Si no hay ninguna orden, hacer el pedido
IF x = 0 THEN
INSERT INTO PedidosPendientes
VALUES (:new.num_producto, :new.cantidad_pedido, SYSDATE);
END IF;
END;
5
5
Temporalidad del Evento: AFTER / BEFORE

BEFORE
Ejecutan la accin asociada ANTES de que la
sentencia sea ejecutada
Decidir si la accin debe realizarse
Utilizar valores alternativos para la sentencia
CREATE TRIGGER NombreTrigger
BEFORE Insert ON NombreTabla .

AFTER
Ejecutan la accin asociada DESPUS de que se
haya ejecutado la sentencia
CREATE TRIGGER NombreTrigger
AFTER Insert ON NombreTabla .
6
6
Granularidad del Evento:
FOR EACH ROW / STATEMENT

A NIVEL DE FILA:
ROW TRIGGERS

Ejecutan la accin asociada tantas veces como


filas se vean afectadas por la sentencia que lo
dispara
Si ninguna fila se ve afectada, no se dispara

CREATE TRIGGER NombreTrigger


BEFORE Insert ON NombreTabla
FOR EACH ROW .

7
7
Granularidad del Evento:
FOR EACH ROW / STATEMENT

A NIVEL DE SENTENCIA:
STATEMENT TRIGGERS

Ejecutan una nica vez la accin asociada,


independientemente del nmero de filas que se
vean afectadas por la sentencia

CREATE TRIGGER NombreTrigger


BEFORE Insert ON NombreTabla
[STATEMENT]

8
8
ROW TRIGGER: ejemplo
A NIVEL DE FILA
Cuando se borre en la tabla Persona alguna persona que
se llame pepe o cuya edad sea mayor de 35 aos,
eliminar tambin dicha persona de la tabla Persona2

Persona Persona2
Cod Nombre Edad Cod Nombre Edad
C1 Mara 25 C1 Mara 25
C2 Pepe 40 C2 Pepe 40
C3 Pepe 45 C3 Pepe 45
C4 Luisa 48 C4 Luisa 48
C5 Pepe 22 C5 Pepe 22

DELETE FROM Persona Borra C3 y C4


WHERE cod in (C1,C3,C4) de Persona2
9
9
STATEMENT TRIGGER: ejemplo
A NIVEL DE SENTENCIA

Cuando se borre en la tabla socio emitir un mensaje


indicando que no se pueden borrar socios

Socio
Cod Nombre Fecha_ant
S1 Mara
S2 Pepe
S3 Pepe
S4 Luisa
S5 Pepe

DELETE FROM socio Borra 3 tuplas y se emite


WHERE nombre = Pepe un nico mensaje
10
10
Condicin
Expresa una condicin que debe cumplirse en el momento
de producirse el evento, para que la accin sea ejecutada.

WHEN persona.nombre = 'pepe' OR persona.edad > 35

Debe ser una expresin booleana y no puede contener


subconsultas
Se puede utilizar cualquier combinacin de operadores
lgicos (AND, OR, NOT) y relacionales (< <= >>== <>).
No se puede especificar una condicin para los
disparadores a nivel de sentencia (STATEMENT) ni los
disparadores INSTEAD OF

11
11
Orden de Ejecucin

Una sentencia SQL puede disparar varios TRIGGERS.


La activacin de un trigger puede disparar la
activacin de otros triggers.

1. Triggers Before (nivel de sentencia)


2. Para cada fila:
1. Trigger Before (a nivel de fila)
2. Ejecuta la Sentencia
3. Triggers After (a nivel de fila)
3. Triggers After (a nivel de sentencia)

Se compromete o se deshace toda la transaccin


El orden de ejecucin de disparadores del mismo
tipo es indeterminado
12
12
Correlation Identifiers: Valores OLD y NEW

Tipo especial de variable PL/SQL tratada como un registro de tipo


tabla_modificada%ROWTYPE
Con OLD.nombre_columna referenciamos:
al valor que tena la columna antes del cambio debido a una modificacin
(UPDATE)
al valor de una columna antes de una operacin de borrado sobre la misma
(DELETE)
al valor NULL para operaciones de insercin (INSERT)
Con NEW.nombre_columna referenciamos:
Al valor de una nueva columna despus de una operacin de insercin
(INSERT)
Al valor de una columna despus de modificarla mediante una sentencia de
modificacin (UPDATE)
Al valor NULL para una operacin de borrado (DELETE)

Condicin (WHEN .) OLD, NEW


SINTAXIS En el cuerpo del disparador :OLD, :NEW
13
13
Triggers DML

Disparados por sentencias DML:


INSERT, UPDATE o DELETE
Todas las filas o slo algunas (WHEN)

LIBROS ESTADSTICAS
ISBN GENERO TTULO GENERO TOTAL_LIBROS
100-09-89 Novela El Quijote Novela 50
----- ---- ---- Infantil 15

CREATE OR REPLACE TRIGGER UpdateEstadisticasGenero


AFTER INSERT OR DELETE OR UPDATE ON Libros DECLARE

UDDATE Estadisticas SET .


BEGIN

END UpdateEstadisticasGenero;
/
14
14
Triggers INSTEAD OF

Slo sobre VISTAS


EMPLEADO DEPARTAMENTO
DNI NOMBRE DEPARTAMENTO NOMBRE CDIGO
11111111 Jos Garca CT-1 Contabilidad - 1 CT-1
----- ---- ---- Recursos RRHH
Humanos

CREATE VIEW EmpleadoDpto as


SELECT e.nombre, d.nombre FROM Empleado E, Departamento D
WHERE E.Departamento = D.Codigo;

CREATE OR REPLACE TRIGGER InsertEmepleadoDpto


INSTEAD OF INSERT ON EmpleadoDpto
DECLARE
v_cod Departamento.codigo%TYPE;
INSERT INTO EmpleadoDpato BEGIN
VALUES (Carlos Gmez', Contabilidad-1);
SELECT codigo INTO v_cod FROM DEPARTAMENTO
ERROR en lnea 1:
ORA-01779: no se puede modificar una WHERE nombre=:NEW.nombre;
columna que se corresponde con una tabla no INSERT INTO Empleado VALUES
reservada por clave
INSERT INTO Departamento VALUES
END; 15
15
Triggers de Sistema

Disparados por eventos del Sistema o eventos


relacionados con las acciones de los Usuarios
Sistema
Arranque y parada CREATE OR REPLACE TRIGGER LogCreations
AFTER CREATE ON SCHEMA
BEGIN
Transacciones INSERT INTO LogCreates (user_id, object_type,
object_name, object_owner, creation_date)
Errores VALUES (USER, ORA_DCIT_OBJ_TYPE,
ORA_DICT_OBJ_NAME,ORA_DICT_OBJ_OWNER, SYSDATE)

Usuarios
END LogCreations;
/

Login / Logoff
Sentencias DDL: CREATE, ALTER, DROP

16
16
Funciones del Cuerpo del Disparador

Inserting, Deleting, Updating

CREATE OR REPLACE TRIGGER ejemplo


BEFORE INSERT OR UPDATE OR DELETE ON tabla
BEGIN
IF DELETING THEN
Acciones asociadas al borrado
ELSIF INSERTING THEN
Acciones asociadas a la insercin
ELSIF UPDATING(COL1)
Acciones asociadas a la modificacin
ELSIF UPDATING(COL2)
Acciones asociadas a la modificacin
END IF;
END ejemplo;
/

17
17
Elevar excepciones en el cuerpo del Disparador

RAISE_APPLICATION_ ERROR
(nro_error, mensaje); [-20000 y -20999]

CREATE OR REPLACE TRIGGER ejemplo


BEFORE DELETE ON tabla
FOR EACH ROW
BEGIN
IF tabla.columna= valor_no_borrable THEN
RAISE_APPLICATION_ERROR(-20000, La
fila no se puede borrar);
END IF;

END ejemplo;

18
18
Declaracin de Variables

CREATE...
BEFORE...
[FOR EACH ROW ...]
DECLARE
Declaracin de variables
BEGIN

nombre CONSTANT NUMBER:=valor;


nombre TIPO;
nombre nombretabla.nombrecolumna%TYPE;
nombre nombretabla%ROWTYPE;
19
19
Activar / Desactivar disparadores

Todos los disparadores asociados a una tabla:


ALTER TABLE nombre_tabla ENABLE ALL TRIGGERS
ALTER TABLE nombre_tabla DISABLE ALL TRIGGERS
(Por defecto Todos estn Activados al crearse)

Un disparador especfico:
ALTER TRIGGER nombre_disparador ENABLE
ALTER TRIGGER nombre_disparador DISABLE

Borrar un Disparador
DROP TRIGGER nombre_disparador;

20
20
Consultar informacin sobre los disparadores

Ver todos los disparadores y su estado


SELECT TRIGGER_NAME , STATUS FROM USER_TRIGGERS;

Ver el cuerpo de un disparador


SELECT TRIGGER_BODY
FROM USER_TRIGGERS
WHERE TRIGGER_NAME='nombre_disparador';

Ver la descripcin de un disparador


SELECT DESCRIPTION
FROM USER_TRIGGERS
WHERE TRIGGER_NAME= 'nombre_disparador';

21
21
Ejemplo

CREATE OR REPLACE TRIGGER Reorder SELECT Trigger_body FROM USER_TRIGGERS


AFTER UPDATE OF Parts_on_hand ON Inventory WHERE Trigger_name = 'REORDER';
FOR EACH ROW
WHEN(new.Parts_on_hand < new.Reorder_point)
TRIGGER_BODY
DECLARE --------------------
x NUMBER; DECLARE
BEGIN x NUMBER;
SELECT COUNT(*) INTO x FROM Pending_orders BEGIN
WHERE Part_no = :new.Part_no; SELECT COUNT(*) INTO x
IF x = 0 THEN FROM Pending_orders
WHERE Part_no = :new.Part_no;
INSERT INTO Pending_orders
IF x = 0 THEN
VALUES (:new.Part_no,
INSERT INTO Pending_orders
:new.Reorder_quantity, sysdate);
VALUES (:new.Part_no,
END IF; :new.Reorder_quantity, sysdate);
END; END IF;
END;

SELECT Trigger_type, Triggering_event, Table_name


FROM USER_TRIGGERS
WHERE Trigger_name = 'REORDER';

TYPE TRIGGERING_STATEMENT TABLE_NAME


---------------- -------------------- ----------------

AFTER EACH ROW UPDATE INVENTORY


22
22
Restricciones: Tablas Mutantes

Tabla mutante (mutating)

Tabla que est siendo modificada por una operacin DML

Tabla que se ver afectada por los efectos de un


DELETE CASCADE debido a la integridad referencial (hasta Oracle8i).

Las rdenes del cuerpo de un disparador no pueden:

Leer o actualizar una tabla mutante que est en la propia


declaracin del disparador a nivel de fila (ROW TRIGGER)

MUTATING TABLE ERROR RUNTIME ERROR

23
23
Tablas Mutantes: ejemplo
CREATE OR REPLACE TRIGGER trigger_asignaturas
BEFORE INSERT OR UPDATE ON asignaturas FOR
EACH ROW
DECLARE
v_total NUMBER;
v_nombre VARCHAR2(30);
BEGIN
SELECT COUNT(*)
INTO v_total
FROM asignaturas -- ASIGNATURAS est MUTANDO
WHERE DNI = :NEW.DNI;
-- comprueba si el profesor est sobrecargado
IF v_total >= 10 THEN
SELECT nombre||' '||apellidos
INTO v_nombre
FROM profesores
WHERE DNI = :NEW.DNI;
RAISE_APPLICATION_ERROR (-20000, El profesor '||
v_nombre||', est sobrecargado');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR (-20001,
Datos de profesor incorrectos');
END; 24
24
Tablas Mutantes: ejemplo

UPDATE asignaturas
SET DNI = 000000000
WHERE asignaturas_id = BD;

SELECT COUNT(*)
UPDATE section
INTO v_total
* FROM asignaturas
WHERE DNI = :NEW.DNI;
ERROR at line 1:
ORA-04091: table BD_XX.ASIGNATURAS is mutating,
trigger/function may not see it
ORA-06512: at "BD_XX.TRIGGER_ASIGNATURAS", line 5
ORA-04088: error during execution of trigger
'BD_XX.TRIGGER_ASIGNATURAS'

25
25
Tablas Mutantes: solucin

Crear 2 disparadores
En el disparador a nivel de fila (for each row)
almacenamos los datos que queremos consultar
(los que provocan el error de tabla mutante)
En el disparador a nivel de orden (statement) realizamos
la consulta
(sobre los datos almacenados en lugar de sobre la tabla)
La mejor forma de almacenar los valores es utilizar un
paquete (opcionalmente, podramos utilizar una tabla)

26
26
Tablas Mutantes: solucin

Trigger a nivel de fila:

Guardamos el DNI y el nombre del profesor en 2 variables


globales, por tanto CREAMOS UN PAQUETE

CREATE OR REPLACE PACKAGE pck_profesores AS


v_DNI_profesor profesor.DNI%TYPE;
v_nombre_profesor varchar2(50);
END;

27
27
Tablas Mutantes: Solucin
CREATE OR REPLACE TRIGGER trigger_asignaturas
BEFORE INSERT OR UPDATE ON section
FOR EACH ROW
BEGIN
IF :NEW.DNI IS NOT NULL THEN
BEGIN

pck_profesores.v_DNI_profesor := :NEW.DNI;
SELECT nombre||' '||apellidos

INTO pck_profesores.v_nombre_profesor
FROM profesores
WHERE DNI = pck_profesores.DNI;
EXCEPTION
WHEN NO_DATA_FOUND THEN
RAISE_APPLICATION_ERROR(-20001,
'This is not a valid instructor');
END;
END IF;
END;
28
28
Tablas Mutantes: Solucin

TRIGGER a nivel de sentencia


realizamos la consulta utilizando las variables globales

CREATE OR REPLACE TRIGGER trigger_asignaturas_statement


AFTER INSERT OR UPDATE ON asignaturas
DECLARE
v_total INTEGER;
BEGIN
SELECT COUNT(*) INTO v_total
FROM asignaturas

WHERE DNI = pck_profesores.v_DNI_profesor;


-- comprobamos si el profesor aludido est sobrecargado
IF v_total >= 10 THEN

RAISE_APPLICATION_ERROR (-20000, 'El profesor, '||


pck_profesores.v_nombre_profesor || ', est sobrecargado);
END IF;
END;
29
29
Tablas Mutantes: solucin

UPDATE asignaturas
SET DNI = 000000000 WHERE
asignaturas_id = BD;

UPDATE asignaturas
*
ERROR at line 1:
ORA-20000: El profesor Carlos Romero est sobrecargado
ORA-06512: at "BD_XX.TRIGGER_ASIGNATURAS_STATEMENT", line 11
ORA-04088: error during execution of trigger
'BD_XX.TRIGGER_ASIGNATURAS_STATEMENT'

30
30