bd-2006-2007-oracle triggers
TRANSCRIPT
1
Disparadores en ORACLEDisparadores en ORACLE
BibliografíaOracle® Database Concepts - 10g Release 2 (10.2) (Octubre 2005)
Oracle® Database Application Developer's Guide – Fundamentals 10g Release 2 (10.2) (Noviembre 2005)
Óscar Díaz – Universidad del País Vasco (UPV)Bases de Datos Activas
BibliografBibliografííaaOracleOracle®® DatabaseDatabase ConceptsConcepts -- 10g 10g ReleaseRelease 2 (10.2)2 (10.2) (Octubre 2005)(Octubre 2005)
OracleOracle®® Database Database Application Developer's Guide Application Developer's Guide –– Fundamentals 10g Fundamentals 10g Release 2 (10.2) Release 2 (10.2) ((NoviembreNoviembre 2005)2005)
ÓÓscarscar DDííazaz –– Universidad del PaUniversidad del Paíís Vasco (UPV)s Vasco (UPV)Bases de Bases de DatosDatos ActivasActivas
IntroducciónIntroducción
PL/SQL: lenguaje de programación estructurado en bloquesBloques: unidad mínima en PL/SQL
Soportan DML y DDLAnónimos / Con nombre → TRIGGERS
Disparadores (triggers) en Oracle: bloques de código que son implícitamente invocados cuando algo sucedeTriggers vs. Procedimientos
Ejecución Implícita: DispararNo admiten argumentos
Aplicaciones:Restricciones (Constraints)AuditoríasInformar de Eventos
DECLARE ▬ optional
BEGIN ▬ required
EXCEPTION ▬ optional
END; ▬ required/
CREATE PROCEDURE Get_emp_rec(Emp_number IN Emp_tab.Empno%TYPE) ASBEGIN
- - - - -END;/
CREATE TRIGGER NombreTriggerBEFORE INSERT ON StarsInDECLARE
…..END;/ TRIGGER
PROCEDIMIENTO
2
IntroducciónIntroducción
3 TiposDML/DDL (Fila/Sentencia, BEFORE/AFTER)INSTEAD OFSYSTEM
Estructura General de un DisparadorEstructura General de un Disparador
CREATE [OR REPLACE] TRIGGER nombre{BEFORE | AFTER | INSTEAD OF} Temporalidad del Evento{INSERT | DELETE | UPDATE [OF <atributo>]} ON <tabla>
CREATE [OR REPLACE] TRIGGER nombre{BEFORE | AFTER | INSTEAD OF} Temporalidad del Evento{INSERT | DELETE | UPDATE [OF <atributo>]} ON <tabla>
[WHEN condición] Granularidad[FOR EACH ROW | STATEMENT]
[WHEN condición] Granularidad[FOR EACH ROW | STATEMENT]
BEGINcuerpo del trigger
END;
BEGINcuerpo del trigger
END;
EventoEvento
CondiciCondicióónn
AcciAccióónn
3
Estructura General de un DisparadorEstructura General de un Disparador
CREATE OR REPLACE TRIGGER Control_DocenciaAFTER DELETE ON ProfesoresCREATE OR REPLACE TRIGGER Control_DocenciaAFTER DELETE ON Profesores
WHEN old.nombre LIKE ‘%Juan%’FOR EACH ROWWHEN old.nombre LIKE ‘%Juan%’FOR EACH ROW
DECLAREvar VARCHAR2(50);
BEGINSELECT a.nombre INTO var FROM Asignaturas a WHERE REF(a) = :NEW.asignatura;
DELETE FROM Asignaturas WHERE nombre = varEND;/
DECLAREvar VARCHAR2(50);
BEGINSELECT a.nombre INTO var FROM Asignaturas a WHERE REF(a) = :NEW.asignatura;
DELETE FROM Asignaturas WHERE nombre = varEND;/
EventoEvento
CondiciCondicióónn
AcciAccióónn
Temporalidad del Evento: AFTER / BEFORETemporalidad del Evento: AFTER / BEFORE
BEFOREEjecutan la acción asociada antes de que la sentencia sea ejecutada
Decidir si la acción debe realizarseUtilizar valores alternativos para la sentencia
CREATE TRIGGER NombreTrigger
BEFORE Insert ON NombreTabla ….
AFTEREjecutan la acción asociada después de que se haya ejecutado la sentencia
CREATE TRIGGER NombreTrigger
AFTER Insert ON NombreTabla ….
4
Granularidad del Evento:FOR EACH ROW / STATEMENTGranularidad del Evento:FOR EACH ROW / STATEMENT
A NIVEL DE FILA: ROW TRIGGERS
Ejecutan la acción asociada tantas veces como filas se vean afectadas por la sentencia que lo dispara
Si ninguna fila se ve afectada, no se disparaCREATE TRIGGER NombreTrigger
BEFORE Insert ON NombreTabla
FOR EACH ROW ….
Granularidad del Evento:FOR EACH ROW / STATEMENTGranularidad del Evento:FOR EACH ROW / STATEMENT
A NIVEL DE SENTENCIA: STATEMENT TRIGGERS
Ejecutan una única vez la acción asociada, independientemente del número de filas que se vean afectadas por la sentencia
CREATE TRIGGER NombreTrigger
BEFORE Insert ON NombreTabla
[STATEMENT]
5
ROW TRIGGER: ejemploROW TRIGGER: ejemplo
PersonaCod Nombre Edad
C1C2C3C4C5
MaríaPepePepeLuisaPepe
2540454822
Persona2
Cod Nombre EdadC1C2C3C4C5
MaríaPepePepeLuisaPepe
2540454822
Cuando se borre en la tabla persona alguna persona quese llame “pepe” o cuya edad sea mayor de 35 años, eliminar también dicha persona de la tabla persona2
Cuando se borre en la tabla persona alguna persona quese llame “pepe” o cuya edad sea mayor de 35 años, eliminar también dicha persona de la tabla persona2
DELETE FROM personaWHERE cod in (‘C1’,‘C3’,‘C4’)
DELETE FROM personaWHERE cod in (‘C1’,‘C3’,‘C4’)
Borra C3 y C4de persona2
STATEMENT TRIGGER: ejemploSTATEMENT TRIGGER: ejemplo
Borra 3 tuplas y se emiteun único mensaje
Socio
Cod Nombre Fecha_antS1S2S3S4S5
MaríaPepePepeLuisaPepe
......
......
......
......
......
Cuando se borre en la tabla socio emitir un mensaje indicando que no se pueden borrar socios
Cuando se borre en la tabla socio emitir un mensaje indicando que no se pueden borrar socios
DELETE FROM socioWHERE nombre = ‘Pepe’
DELETE FROM socioWHERE nombre = ‘Pepe’
6
CondiciónCondición
Expresa una condición que debe cumplirse en el momento de producirse el evento, para que la acción sea ejecutada.
WHEN persona.nombre = 'pepe' OR persona.edad > 35
Se puede utilizar cualquier combinación de operadores lógicos (AND, OR, NOT) y relacionales (< <= > >= = <>).
No se puede especificar una condición para los disparadores a nivel de sentencia (STATEMENT) ni los disparadores INSTEAD OF Debe ser una consulta SQL y no puede contener subconsultas SELECT * FROM Productos
WHERE PrecioUnidad IN (SELECT PrecioUnidadFROM DetallePedidoWHERE Descuento = 0 .25)
Orden de EjecuciónOrden de Ejecución
Una sentencia SQL puede disparar varios TRIGGERS.La activación de un trigger puede disparar la activación de otros triggers.
1. Triggers Before (nivel de sentencia)2. Para cada fila:
1. Trigger Before (a nivel de fila)2. Ejecuta la Sentencia3. Triggers After (a nivel de fila)
3. Triggers After (a nivel de Sentencia)
Se compromete o se deshace toda la transacciónEl orden de ejecución de disparadores del mismo tipo es indeterminado
7
Triggers DMLTriggers DML
Disparados por sentencias DML: INSERT, UPDATE o DELETETodas las filas o sólo algunas (WHEN)
-------------El QuijoteNovela100-09-89TÍTULOGENEROISBN
15Infantil50Novela
TOTAL_LIBROSGENERO
CREATE OR REPLACE TRIGGER UpdateEstadisticasGenero
AFTER INSERT OR DELETE OR UPDATE ON Libros
DECLARE
UDDATE Estadisticas SET ….
BEGIN
----------------------
END UpdateEstadisticasGenero;
/
LIBROS ESTADÍSTICAS
INSERT INTO EmpleadoDpatoVALUES (‘Carlos Gómez', ‘Contabilidad-1’);
ERROR en línea 1:ORA-01779: no se puede modificar una columna que se corresponde con una tabla no reservada por clave
Triggers INSTEAD OFTriggers INSTEAD OF
Sólo sobre VISTAS
-------------CT-1José García11111111
DEPARTAMENTO
NOMBREDNI
RRHHRecursos Humanos
CT-1Contabilidad - 1CÓDIGONOMBRE
EMPLEADO DEPARTAMENTO
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- - --
BEGIN
INSERT INTO Empleado VALUES …INSERT INTO Departamento VALUES …
END;
8
Triggers de SistemaTriggers de Sistema
Disparados por eventos del Sistema o eventos relacionados con las acciones de los UsuariosSistema
Arranque y paradaTransaccionesErrores
UsuariosLogin / LogoffSentencias DDL: CREATE, ALTER, DROP
CREATE OR REPLACE TRIGGER LogCreationsAFTER CREATE ON SCHEMA
BEGININSERT INTO LogCreates (user_id, object_type,object_name, object_owner, creation_date)VALUES (USER, ORA_DCIT_OBJ_TYPE,
ORA_DICT_OBJ_NAME,ORA_DICT_OBJ_OWNER, SYSDATE)END LogCreations;/
Correlation Identifiers: Valores OLD y NEWCorrelation Identifiers: Valores OLD y NEW
Tipo especial de variable PL/SQL tratada como un registro de tipo tabla_modificada%ROWTYPECon OLD.nombre_columna referenciamos:
al valor que tenía la columna antes del cambio debido a una modificación (UPDATE)al valor de una columna antes de una operación de borrado sobre la misma (DELETE)al valor NULL para operaciones de inserción (INSERT)
Con NEW.nombre_columna referenciamos:Al valor de una nueva columna después de una operación de inserción (INSERT)Al valor de una columna después de modificarla mediante una sentencia de modificación (UPDATE)Al valor NULL para una operación de borrado (DELETE)
Condición (WHEN ….) OLD, NEWEn el cuerpo del disparador :OLD, :NEWSINTAXIS
9
Correlation Identifiers: ejemploCorrelation Identifiers: ejemplo
CREATE OR REPLACE TRIGGER GenerarAutorIDBEFORE INSERT OR UPDATE ON AutoresFOR EACH ROW
BEGINSELECT id_autores INTO :new.ID FROM Tabla_IDs;UPDATE Tabla_IDs SET id_autores = id_autores + 1;
END GenerarAutorID;/
INSERT INTO autores (nombre, apellidos)VALUES ('Lolita', 'Lazarus');
INSERT INTO autores (ID, nombre, apellidos)VALUES (-7, 'Zelda', 'Zoom');
Funciones del Cuerpo del DisparadorFunciones del Cuerpo del Disparador
CREATE OR REPLACE TRIGGER ejemploBEFORE INSERT OR UPDATE OR DELETE ON tablaBEGIN
IF DELETING THENAcciones asociadas al borrado
ELSIF INSERTING THEN Acciones asociadas a la inserción
ELSIF UPDATING(‘COL1’)Acciones asociadas a la modificación
ELSIF UPDATING(‘COL2’)Acciones asociadas a la modificación
END IF;END ejemplo;/
Inserting, Deleting, Updating
10
Elevar excepciones en elcuerpo del DisparadorElevar excepciones en elcuerpo del Disparador
RAISE_APPLICATION_ ERROR(nro_error, mensaje); [-20000 y -20999]
CREATE OR REPLACE TRIGGER ejemploBEFORE DELETE ON tablaFOR EACH ROWBEGIN
IF tabla.columna= valor_no_borrable THENRAISE_APPLICATION_ERROR(-20000,‘La fila no se puede borrar’);
END IF;...
END ejemplo;
Declaración de VariablesDeclaración de Variables
nombre CONSTANT NUMBER:=valor;
nombre TIPO;nombre nombretabla.nombrecolumna%TYPE;
nombre nombretabla%ROWTYPE
CREATE...BEFORE...[FOR EACH ROW ...]DECLARE
Declaración de variablesBEGIN
11
Activar / Desactivar disparadoresActivar / 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 están Activados al crearse)
Un disparador específico:ALTER TRIGGER nombre_disparador ENABLE
ALTER TRIGGER nombre_disparador DISABLE
Consultar información sobre los disparadoresConsultar información sobre los disparadores
Eliminar un disparadorDROP TRIGGER nombre_disparador;
Ver todos los disparadores y su estadoSELECT TRIGGER_NAME , STATUS FROM USER_TRIGGERS;
Ver el cuerpo de un disparadorSELECT TRIGGER_BODYFROM USER_TRIGGERSWHERE TRIGGER_NAME='nombre_disparador';
Ver la descripción de un disparadorSELECT DESCRIPTION FROM USER_TRIGGERSWHERE TRIGGER_NAME= 'nombre_disparador';
12
EjemploEjemplo
CREATE TRIGGER Ejemplo
AFTER DELETE ON tabla1
FOR EACH ROW
WHEN ((OLD.nombre=’pepe’) OR (OLD.edad > 35))
BEGIN
DELETE FROM tabla2WHERE tabla2.cod=:OLD.cod;
END Ejemplo;
/
SELECT Trigger_type, Triggering_event, Table_name
FROM USER_TRIGGERS
WHERE Trigger_name = 'Ejemplo';
TYPE TRIGGERING_STATEMENT TABLE_NAME
---------------- ------------------------ ----------
AFTER EACH ROW DELETE tabla1
SELECT Trigger_body FROM USER_TRIGGERS
WHERE Trigger_name = 'Ejemplo';
TRIGGER_BODY
----------------------------------
BEGIN
DELETE FROM tabla2 WHEREtabla2.cod=:OLD.cod;
END Ejemplo;
/
Restricciones: tablas mutantesRestricciones: tablas mutantes
Tabla mutante (mutating)tabla que está siendo modificada por una operación DMLtabla 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 declaración del disparadorMUTATING TABLE ERROR RUNTIME ERROR
13
Tablas Mutantes: ejemploTablas Mutantes: ejemploCREATE 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;
Tablas Mutantes: ejemploTablas Mutantes: ejemplo
UPDATE asignaturas
SET DNI = ‘000000000’
WHERE asignaturas_id = ‘BD’;
UPDATE section
*
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'
SELECT COUNT(*)
INTO v_total
FROM asignaturas
WHERE DNI = :NEW.DNI;
14
Tablas Mutantes: solución Tablas Mutantes: solución
Crear 2 disparadoresEn 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, podríamos utilizar una tabla)
Tablas Mutantes: solución Tablas Mutantes: solución
Trigger a nivel de fila:guardamos el DNI y el nombre del profesornecesitamos 2 variables globales creamos un paquete
CREATE OR REPLACE PACKAGE pck_profesores AS
v_DNI_profesor profesor.DNI%TYPE;
v_nombre_profesor varchar2(50);
END;
15
Tablas Mutantes: solución Tablas Mutantes: solución
CREATE OR REPLACE TRIGGER trigger_asignaturas
BEFORE INSERT OR UPDATE ON asignaturas
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;
guardamos el DNI y el nombre del profesor
Tablas Mutantes: soluciónTablas Mutantes: solución
TRIGGER a nivel de sentenciarealizamos 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 || ', is overbooked');
END IF;
END;
16
Tablas Mutantes: soluciónTablas Mutantes: solución
UPDATE asignaturas
SET DNI = ‘000000000’
WHERE asignaturas_id = ‘BD’;
UPDATE asignaturas
*
ERROR at line 1:ORA-20000: El profesor Carlos Romero está sobrecargadoORA-06512: at "BD_XX.TRIGGER_ASIGNATURAS_STATEMENT", line 11ORA-04088: error during execution of trigger'BD_XX.TRIGGER_ASIGNATURAS_STATEMENT'
TRANSACCIONES y TRIGGERSTRANSACCIONES y TRIGGERS
Los cambios hechos en un TRIGGER deben ser comprometidos o deshechos con la transacción en la que se ejecutan
SQL> CREATE TABLE tab1 (col1 NUMBER);
Table created.
SQL> CREATE TABLE log(timestamp DATE, operacion VARCHAR2(2000));
Tabla creada.
SQL> CREATE TRIGGER tab1_trig
2 AFTER insert ON tab1
3 BEGIN
4 INSERT INTO log VALUES (SYSDATE, 'Insert en TAB1');
5 COMMIT;
6 END;
7 /
Trigger created.
SQL> INSERT INTO tab1 VALUES (1);
INSERT INTO tab1 VALUES (1)
*
ERROR at line 1:
ORA-04092: cannot COMMIT in a trigger
ORA-06512: at “BD_XX.TAB1_TRIG", line 3
ORA-04088: error during execution of trigger‘BD_XX.TAB1_TRIG'
17
TRANSACCIONES y TRIGGERSTRANSACCIONES y TRIGGERS
Se pueden utilizar autonomous transactions de manera que el TRIGGER se ejecute en su propia transacción
SQL> CREATE OR REPLACE TRIGGER tab1_trig
2 AFTER insert ON tab1
3 DECLARE
4 PRAGMA AUTONOMOUS_TRANSACTION;
5 BEGIN
6 INSERT INTO log VALUES (SYSDATE, 'Insert on TAB1');
7 COMMIT;
8 END;
9 /
Trigger created.
SQL> INSERT INTO tab1 VALUES (1);
1 row created.
EjemplosEjemplos
Dada la siguiente relación:SOCIO (num_soc, nombre, direccion, telefono)
Se desea mantener la información de los socios aunqueestos se den de baja, para lo que se crea una tablaSOCIO_BAJA, que contiene los datos de socio y la fecha de baja y que se actualizará cada vez que se borre un socio
SOCIO_BAJA (num_soc, nombre, direccion, telefono, fecha_baja)
18
EjemplosEjemplos
CREATE OR REPLACE TRIGGER borrar_socio
AFTER DELETE ON socio
FOR EACH ROW
BEGIN
INSERT INTO socio_baja
VALUES (:OLD.num_soc, :OLD.nombre,:OLD.direccion, :OLD.telefono,SYSDATE);
END borrar_socio;
/
EjemplosEjemplos
Dadas las siguientes relaciones:PRODUCTO (cod_prod, descripción, proveedor,
unid_vendidas)ALMACEN (cod_prod_s, stock, stock_min, stock_max)
1. Se desea mantener actualizado el stock del ALMACEN cadavez que se vendan unidades de un determinado producto
2. Cuando el stock esté por debajo del mínimo lanzar un mensajede petición de compra. Se indicará el número de unidades a comprar, según el stock actual y el stock maximo
3. Si el stock es menor que el mínimo stock permitido, impedir la venta
19
EjemplosEjemplos
CREATE OR REPLACE TRIGGER actualizar_almacen
AFTER UPDATE OF unid_vendidas ON producto
FOR EACH ROW
BEGIN
UPDATE almacen
SET almacen.stock = almacen.stock+ :OLD.unid_vendidas - :NEW.unid_vendidas
WHERE almacen.cod_prod_s =:NEW.cod_prod;
END actualizar_almacen;
/
1. Se desea mantener actualizado el stock del ALMACEN cadavez que se vendan unidades de un determinado producto
EjemplosEjemplos
CREATE OR REPLACE TRIGGER actualizar_almacen
AFTER UPDATE OF unid_vendidas ON producto
FOR EACH ROW
DECLARE
v_stock almacen.stock%TYPE;v_stock_a almacen.stock%TYPE;v_stock_min almacen.stock%TYPE; v_stock_max almacen.stock%TYPE;
BEGIN
SELECT stock, stock_min, stock_max INTO v_stock_a, v_stock_min, v_stock_maxFROM almacen WHERE cod_prod_s = :old.cod_prod;
v_stock := v_stock_a + :OLD.unid_vendidas - :NEW.unid_vendidas;
UPDATE almacen SET stock = v_stock WHERE cod_prod_s = :old.cod_prod;
IF (v_stock<v_stock_min) THEN
DBMS_OUTPUT.PUT_LINE ('No hay stock. Comprar:'|| v_stock_max-v_stock);
END IF;
END actualizar_almacen;
/
2. Cuando el stock esté por debajo del mínimo lanzar un mensaje de petición de compra
20
EjemplosEjemplos
CREATE OR REPLACE TRIGGER actualizar_almacen
BEFORE UPDATE OF unid_vendidas ON producto
FOR EACH ROW
DECLARE
v_stock almacen.stock%TYPE;
v_stock_a almacen.stock%TYPE;
v_stock_min almacen.stock%TYPE;
BEGIN
SELECT stock, stock_min INTO v_stock_a, v_stock_min
FROM almacen WHERE cod_prod_s = :old.cod_prod;
v_stock := v_stock_a + :OLD.unid_vendidas - :NEW.unid_vendidas;
IF (v_stock<v_stock_min)
THEN RAISE_APPLICATION_ERROR(-20001, ‘No hay unidades suficientes’);
END IF;
END actualizar almacen;
/
3. Si el stock es menor que el mínimo stock permitido, impedir la venta
EjemplosEjemplos
Dadas las siguientes relaciones:
PROFESOR (cod_prof)CLASE (cod_clase, cod_prof)
Se define la siguiente vista:
CREATE VIEW informe_profesores ASSELECT p.cod_prof, COUNT(c.cod_clase) total_clasesFROM profesor p, clase cWHERE p.cod_prof = c.cod_prof (+)GROUP BY p.cod_prof;
Se desea poder invocar sentencias del tipo:
DELETE FROM informe_profesoresWHERE cod_prof = 109;
21
EjemplosEjemplos
CREATE OR REPLACE TRIGGER borrar_informe_profesores
INSTEAD OF DELETE ON informe_profesores
FOR EACH ROW
BEGIN
DELETE FROM clase
WHERE cod_prof = :OLD.COLD_PROF;
DELETE FROM profesor
WHERE cod_prof = :OLD.COLd_PROF;
END;
Disparadores en ORACLEDisparadores en ORACLE
BibliografíaOracle® Database Concepts - 10g Release 2 (10.2) (Octubre 2005)
Oracle® Database Application Developer's Guide – Fundamentals 10g Release 2 (10.2) (Noviembre 2005)
Óscar Díaz – Universidad del País Vasco (UPV)Bases de Datos Activas
BibliografBibliografííaaOracleOracle®® DatabaseDatabase ConceptsConcepts -- 10g 10g ReleaseRelease 2 (10.2)2 (10.2) (Octubre 2005)(Octubre 2005)
OracleOracle®® Database Database Application Developer's Guide Application Developer's Guide –– Fundamentals 10g Fundamentals 10g Release 2 (10.2) Release 2 (10.2) ((NoviembreNoviembre 2005)2005)
ÓÓscarscar DDííazaz –– Universidad del PaUniversidad del Paíís Vasco (UPV)s Vasco (UPV)Bases de Bases de DatosDatos ActivasActivas