Sei sulla pagina 1di 15

DisparadoresDisparadores dede PL/SQLPL/SQL

DISPARADORESDISPARADORES

n

Bloques de PL/SQL nominados con las secciones:

– declarativa

– ejecutable

– manejo de excepciones

n

Almacenados en la BD (diccionario de datos: user_triggers).

n

Tipos de Disparadores:

LMD sobre tablas

– Disparadores INSTEAD OF sobre vistas

– Disparadores del sistema sobre la BD o el Esquema.

n

Se ejecuta de manera implícita ante eventos:

LMD sobre tablas (Insert, Delete, Update)

– LDD (Create, Alter, Drop) (Actualizado con Oracle 9i)

– Operaciones de la BD (ServerError, Logon, Logoff, Startup,

Shutdown) (Actualizado con Oracle 9i)

Disparadores en

PL/SQL

2

DISPARADORES:AplicacionesDISPARADORES:Aplicaciones

 

n

Restricciones de Integridad complejas.

IMPORTANTE: no se deben usar para garantizar el cumplimiento de las RI a nivel de esquema !!! (el esquema ha de contener toda la semántica que permita sin utilizar disparadores)

n

Auditoría: registro de los cambios realizados y quién los realizó

n

Aviso automático a otros programas de llevar a cabo una determinada acción

n

Actualización en cascada

Disparadores en

3

PL/SQL

DISPARADORES:UtilizaciDISPARADORES:Utilizacióónn

 

n

Identificador único para cada elemento.

n

Tamaño del disparador: no superar los 32K.

n

Operaciones en el cuerpo del disparador: LMD.

n

No disparadores recursivos: agotan memoria.

n

Compilación cada vez que se ejecutan: más lentos.

Disparadores en

4

PL/SQL

DISPARADORES:SintaxisDISPARADORES:Sintaxis

n

Creación: (se activan al crearlos)

CREATE [OR REPLACE] TRIGGER <nombre_disparador> {BEFORE | AFTER} evento ON referencia_tabla [ FOR EACH ROW [WHEN condición_evento]] cuerpo_disparador;

n

Eliminación:

DROP TRIGGER nombre_disparador;

n

Activación/Desactivación:

ALTER TRIGGER nombre_disparador {DISABLE | ENABLE};

ALTER TABLE nombre_tabla {ENABLE | DISABLE} ALL TRIGGERS;

Disparadores en

PL/SQL

5

DISPARADORES:ComponentesDISPARADORES:Componentes (1)(1)

n

Nombre disparador:

Siguen las mismas normas de nomenclatura que otros identificadores en la BD

n

Replace:

Se utiliza para sobreescribir un disparador existente

n

Before/After:

Instante de ejecución del disparador con respecto al evento

n

Evento:

– Tipo de orden DML sobre una tabla que provoca la activación del disparador {INSERT | DELETE | UPDATE [OF <lista de columnas>]}. La lista de columnas sólo tiene sentido en el evento UPDATE

Disparadores en

PL/SQL

6

DISPARADORES:DISPARADORES: ComponentesComponentes (2)(2)

n

Nivel:

– FOR EACH ROW: disparadores con nivel de fila. Se activan una vez por cada fila afectada por el evento

– FOR EACK STATEMENT: disparadores con nivel de orden. Se activan sólo una vez (antes o después de la orden).

n

When: Sólo tiene sentido a nivel de fila. La condición se evalúa (true o false). No se pueden utilizar consultas anidadas.

Disparadores en

PL/SQL

7

DISPARADORES:DISPARADORES: ComponentesComponentes (3)(3)

n Cuerpo: bloque PL/SQL con las siguientes restricciones:

– Un disparador no puede emitir ninguna orden de control de transacciones (COMMIT, ROLLBACK o SAVEPOINT)

– Ningún procedimiento o función llamada por el disparador puede emitir órdenes de control de transacciones.

– No puede contener ninguna declaración de variables LONG o LONG RAW

– Restricciones en tablas a las que se puede acceder (Tablas Mutantes)

– No puede modificar las columnas de clave primaria

Disparadores en

PL/SQL

8

 

RegistrosRegistros ::oldold yy ::newnew

 

n

Un disparador con nivel de fila se ejecuta en cada fila en la que se produce el suceso.

n

:old y :new son registros que nos permiten acceder a los datos de la fila actual

n

Tipo de los registros:

nombre_tabla%ROWTYPE;

 
 

Suceso

:old

:new

INSERT

NULL

Nuevos valores

UPDATE

Valores almacenados

Nuevos valores

DELETE

Valores almacenados

NULL

 

Disparadores en

 

9

PL/SQL

 
 

EjemploEjemplo ::oldold yy ::newnew

 

create sequence sec_estudiante start with 2;

create table estudiante ( codigo number(2) primary key ); CREATE OR REPLACE TRIGGER t_estudiante_B BEFORE INSERT ON estudiante FOR EACH ROW BEGIN

 

SELECT sec_estudiante.nextval INTO :new.codigo FROM dual; END t_estudiante;

n

NOTAS:

 

se ignoran los valores que se introducen como código de estudiante --> se inserta el siguiente de la secuencia

 

Disparadores en

 

10

PL/SQL

 

INSERTING,INSERTING, DELETINGDELETING YY UPDATINGUPDATING

n Predicados de los disparadores (booleanos), empleadas para determinar qué operación se está realizando en un disparador.

CREATE OR REPLACE TRIGGER Cambios

BEFORE INSERT OR DELETE ON Alumnos FOR EACH ROW

DECLARE

Cambio_tipo CHAR(1);

BEGIN

/* Usa ‘I’ para INSERT y ‘D’ Para DELETE */ IF INSERTING THEN

Cambio_tipo := ‘I’; ELSE

Cambio_tipo := ‘D’; END IF; END Cambios;

Disparadores en

PL/SQL

11

TablasTablas MutantesMutantes

QuQuéé sonson

 

n

Tablas que están siendo modificadas por una operación DML (INSERT, DELETE, UPDATE):

– En un disparador, la tabla sobre la que está definido

– Tablas que serán actualizadas como consecuencia de la integridad referencial (P.e.: DELETE_CASCADE)

 

Disparadores en

13

PL/SQL

EnEn loslos disparadoresdisparadores (1)(1)

 

n

A nivel de FILA, dentro del cuerpo de un disparador, no puede existir:

lecturas o modificaciones de tablas mutantes

cambio de clave primaria, claves ajenas o claves alternativas de las tablas que restringen (el resto de las columnas sí se pueden cambiar)

– EXCEPCIÓN: no se dan las tablas mutantes en los disparadores con nivel de fila BEFORE INSERT

n

A nivel de SENTENCIA no existen problemas de tablas mutantes

EXCEPCIÓN: si disparador se activa como consecuencia de un BORRADO EN CASCADA (problemas de tablas mutantes)

 

Disparadores en

14

PL/SQL

EnEn loslos disparadoresdisparadores (2)(2)

 
 

TIPO DE DISPARADOR

ERROR DE TABLA MUTANTE

 

BEFORE INSERT ROW

NO 1

AFTER INSERT ROW SI

BEFORE INSERT STATEMENT

NO

AFTER INSERT STATEMENT BEFORE DELETE ROW AFTER DELETE ROW

NO

SI

SI

BEFORE DELETE STATEMENT AFTER DELETE STATEMENT BEFORE UPDATE ROW

NO 2

NO 2

SI

AFTER UPDATE ROW

SI

BEFORE

UPDATE

NO

STATEMENT AFTER UPDATE STATEMENT

NO

 

1 Siempre que la inserción que provoque la activación del disparador sea una inserción simple (se inserte una única fila). 2 Siempre que el disparador no se active como consecuencia de un borrado en cascada. En ese caso, aparecerá también un error de tabla mutante.

Disparadores en

15

PL/SQL

EjemploEjemplo (1)(1)

 

n “Una zona tiene uno o varios departamentos y un departamento trabaja en una o ninguna zona”.

 
ZONA (Cod_Zona, Nom_Zona) BC/MC
ZONA (Cod_Zona, Nom_Zona)
BC/MC
 

DEPARTAMENTO (Cod_Dep, Presupuesto, Cod_Zona)

CREATE SEQUENCE Secuencia_Departamento START WITH 100000 INCREMENT BY 1;

Disparadores en

16

PL/SQL

EjemploEjemplo (2)(2)

CREATE TABLE Zona ( Cod_Zona NUMBER(6) CONSTRAINT pk_zona PRIMARY KEY, Nom_Zona VARCHAR2(40) NOT NULL

);

CREATE TABLE Departamento ( Cod_Dep NUMBER(6) CONSTRAINT pk_departamento PRIMARY KEY, Presupuesto NUMBER(8) NOT NULL, Cod_Zona NUMBER(2) NOT NULL CONSTRAINT fk_departamento_zona REFERENCES Zona(Cod_Zona) ON DELETE CASCADE

);

Disparadores en

17

PL/SQL

EjemploEjemplo 11 (1)(1)

n EJEMPLO 1:

CREATE OR REPLACE TRIGGER Disparador1 AFTER INSERT ON Zona FOR EACH ROW BEGIN INSERT INTO Departamento VALUES

(Secuencia_Departamento.NEXTVAL, 10000000, :new.Cod_Zona); END Disparador1;

/

Operación:

INSERT INTO Zona VALUES (1, ‘CENTRO’);

Disparadores en

18

PL/SQL

EjemploEjemplo 11 (2)(2)

n EJEMPLO 1. Comentarios:

– La versión Oracle 8i arregla este problema de tabla mutante (NO DA ERROR).

n Ahora Oracle produce un error al realizar una consulta para comprobar si existe una Zona con ese Cod_Zona al insertar en Departamento.

– Versiones anteriores: Error de tabla mutante

n

La tabla departamento referencia a la tabla zona (FK).

n

Cada vez que se inserta un nuevo dato en la tabla departamento, Oracle controlaba la integridad referencial (el código Departamento.Cod_Zona ha de existir en la tabla Zona --> Realiza una lectura de la tabla Zona, que está mutando !!)

n

NOTA: Si en lugar de realizar una inserción en la tabla departamento, se hubiera realizado una selección, no habría dado error de tabla mutante.

Disparadores en

PL/SQL

19

EjemploEjemplo 22 (1)(1) n EJEMPLO 2: CREATE OR REPLACE TRIGGER Disparador2 AFTER INSERT ON Departamento
EjemploEjemplo 22 (1)(1)
n EJEMPLO 2:
CREATE OR REPLACE TRIGGER Disparador2
AFTER INSERT ON Departamento FOR EACH ROW
DECLARE
Var Departamento%ROWTYPE;
BEGIN
UPDATE Zona SET Nom_Zona='U' WHERE Cod_Zona=:new.Cod_Zona;
END Disparador2;
/
Operación:
INSERT
INTO
Departamento
VALUES
(Secuencia_Departamento.NEXTVAL,
20000000, 1);
Disparadores en
20
PL/SQL

EjemploEjemplo 22 (2)(2)

 

n

EJEMPLO 2. Comentario:

– No existe error de tabla mutante: la tabla departamento referencia a la tabla zona, por lo que no se pueden modificar sus claves, pero sí se pueden modificar las demás columnas.

– En el caso de que el disparador fuese BEFORE insert row, no existiría error de tabla mutante ni siquiera si se modifican sus claves.

Disparadores en

21

 

PL/SQL

EjemploEjemplo 33 (1)(1)

 

n

EJEMPLO 3:

Creación de una tabla independiente a las anteriores:

CREATE SEQUENCE Secuencia_Mensaje START WITH 100000 INCREMENT BY 1;

 

CREATE TABLE Mensaje_Departamento ( Cod_Mensaje NUMBER(6) CONSTRAINT pk_error PRIMARY KEY, Cod_Dep NUMBER(6) NOT NULL, Tipo VARCHAR2(255) NOT NULL, Fecha DATE NOT NULL

);

Disparadores en

22

 

PL/SQL

EjemploEjemplo 33 (2)(2)

 

n

EJEMPLO 3. Disparador:

 

CREATE OR REPLACE TRIGGER Disparador3 AFTER INSERT ON Departamento FOR EACH ROW BEGIN

 

INSERT INTO Mensaje_Departamento VALUES

(Secuencia_Mensaje.NEXTVAL, elevado', SYSDATE); END Disparador3;

:new.Departamento,

'Presupuesto

/

Operación:

 

INSERT

INTO

Departamento

VALUES

(Secuencia_Departamento.NEXTVAL,

70000, 1);

 

Disparadores en

 

23

 

PL/SQL

EjemploEjemplo 33 (3)(3)

 

n

EJEMPLO 3. Comentarios:

 

– No existe error de tabla mutante: la tabla mensaje_departamento es independiente de la tabla departamento.

 

Disparadores en

 

24

 

PL/SQL

EjemploEjemplo 44 (1)(1)

n EJEMPLO 4:

CREATE OR REPLACE TRIGGER Disparador4 BEFORE DELETE ON Departamento FOR EACH ROW DECLARE Var Zona%ROWTYPE;

BEGIN SELECT * INTO Var FROM Zona WHERE Cod_Zona=:old.Cod_Zona; END Disparador4;

/

Operación1: DELETE FROM Departamento WHERE Cod_Zona=1;

Operación2: DELETE FROM Zona WHERE Cod_Zona=1;

Disparadores en

PL/SQL

25

EjemploEjemplo 44 (2)(2)

n EJEMPLO 4. Comentarios:

Operación 1: No da error de tabla mutante: departamento referencia a la tabla zona, que sí se puede consultar, ya que no está mutando.

Operación 2:

n

La versión Oracle 8i arregla el problema de tabla mutante (mismo caso que el ejercicio 1).

n

Versiones anteriores de Oracle: Da error de tabla mutante, ya que, al borrar en la tabla zona (tabla mutante), se borran todas las las tuplas de la tabla departamento que referencian a la zona borrada. Esto activa el disparador4 de departamento, que consulta la tabla zona, que en este caso sí esta mutando.

Disparadores en

PL/SQL

26

EjemploEjemplo 55 (1)(1)

n EJEMPLO 5:

CREATE OR REPLACE TRIGGER Disparador5 AFTER DELETE ON Departamento

DECLARE Var Zona%ROWTYPE;

BEGIN SELECT * INTO Var FROM Zona WHERE Cod_Zona=1; END Disparador5;

/

Operación 1: DELETE FROM Zona WHERE Cod_Zona = 1;

Operación 2: DELETE FROM Departamento WHERE Cod_Zona = 1;

Disparadores en

PL/SQL

27

EjemploEjemplo 55 (2)(2)

n EJEMPLO 5. Comentarios:

– Operación 1:

n

Versión Oracle 8i: No existe error de tabla mutante.

– En el caso que en el cuerpo del disparador se consulte exactamente las tuplas que se están borrando, dará error el disparador indicando que “no se encuentran datos”.

n

Versiones anteriores: Error de tabla mutante.

– Al borrar de la tabla zona, se desencadena un borrado en cascada en la tabla departamento (ambas tablas mutantes), y al mismo tiempo intenta leer de la tabla zona.

– Operación 2: NO hay error.

n Al borrar de la tabla departamento no se desencadena ningún borrado en cascada (sólo borra de la tabla departamento)

Disparadores en

PL/SQL

28

ModificaciModificacióónn enen CascadaCascada (1)(1)

n EJEMPLO 6:

CREATE OR REPLACE TRIGGER Modificacion_Cascada BEFORE UPDATE OF Cod_Zona ON Zona FOR EACH ROW

BEGIN UPDATE Departamento SET Cod_Zona = :new.Cod_Zona WHERE Cod_Zona = :old.Cod_Zona; END Modificacion_Cascada;

/

Operación:

UPDATE Zona SET Cod_Zona = 2 WHERE Cod_Zona = 1;

Disparadores en

PL/SQL

29

ModificaciModificacióónn enen CascadaCascada (2)(2)

n EJEMPLO 6. Comentarios:

– Oracle 8i: Error de restricción única.

n Se intenta modificar la tupla en Zona, pero como hay tuplas en Departamento que hacen referencia a las tuplas de Zona que se est án borrando, surge el error de restricción única (FK).

– Oracle versiones anteriores: Error de tabla mutante.

n La tabla departamento, que referencia a la tabla zona (FK), al modificarse, se han de comprobar las restricciones de integridad (consultar zona, que está mutando).

Disparadores en

PL/SQL

30