bd-2006-2007-oracle triggers

21
1 Disparadores en ORACLE Disparadores en ORACLE Bibliografía Oracle® 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 Bibliograf Bibliografía Oracle Oracle® Database Database Concepts Concepts - 10g 10g Release Release 2 (10.2) 2 (10.2) (Octubre 2005) (Octubre 2005) Oracle Oracle® Database Database Application Developer's Guide Application Developer's Guide – Fundamentals 10g Fundamentals 10g Release 2 (10.2) Release 2 (10.2) ( Noviembre Noviembre 2005) 2005) Óscar scar Díaz az – Universidad del Pa Universidad del Paí s Vasco (UPV) s Vasco (UPV) Bases de Bases de Datos Datos Activas Activas Introducción Introducción PL/SQL: lenguaje de programación estructurado en bloques Bloques: unidad mínima en PL/SQL Soportan DML y DDL Anónimos / Con nombre TRIGGERS Disparadores (triggers) en Oracle: bloques de código que son implícitamente invocados cuando algo sucede Triggers vs. Procedimientos Ejecución Implícita: Disparar No admiten argumentos Aplicaciones: Restricciones (Constraints) Auditorías Informar de Eventos DECLARE optional BEGIN required EXCEPTION optional END; required / CREATE PROCEDURE Get_emp_rec (Emp_number IN Emp_tab.Empno%TYPE) AS BEGIN ----- END; / CREATE TRIGGER NombreTrigger BEFORE INSERT ON StarsIn DECLARE ….. END; / TRIGGER PROCEDIMIENTO

Upload: independent

Post on 05-Mar-2023

1 views

Category:

Documents


0 download

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