Disparadores - Trigger 1 Disparadores (triggers - T) • Definición Disparadores (triggers) Originales de Sybase SQL Server. • Elementos de un T – No forman parte de SQL2 (SQL92) – Pero sí de SQL3 • Tipo de T según cuando se dispare Procedimientos que ejecuta de manera implícita el • Estado de una T SGBD como respuesta a un evento • Acoplamiento o Consideración de T • Combinación de T – Base fundamental de las Bases de Datos Activas Por ejemplo: • Algoritmos y modelos de Ejecución – Cuando hay menos de X productos en stock, hacer un nuevo pedido • Uso de las T – Si el producto caduca hoy avisar almacén para que lo retiren – Cuando sean las 17:00h hacer copia de seguridad de la BD Elementos de un disparador Disparadores son ECA: Evento + Condición + Acción Evento: – Suceso que causa que se dispare un trigger • INSERT, UPDATE, DELETE • Oracle (además: CREATE, ALTER, DROP, LOGON, LOGOFF, STARTUP, SHUTDOWN, SERVERERROR) Condición: – Expresión booleana que debe ser TRUE para que se dispare el trigger realmente. La acción no se ejecuta si la expresión se evalúa a FALSE o Unknown. Acción: – Procedimiento que se debe ejecutar cuando se dispare el trigger. • Oracle: PL/SQL, Java, Llamada a procedimiento en C • SQL Server: Transact-SQL • No admiten instrucciones de control de transacciones Sintaxis: Disparadores en SQL3 CREATE TRIGGER <identificador> {AFTER | BEFORE | INSTEAD OF} {INSERT | DELETE | UPDATE [OF <atributo> ?} ON <tabla> [FOR EACH ROW | STATEMENT? [REFERENCING OLD AS <nombre> NEW AS <nombre>? [REFERENCING OLD_TABLE AS <nom> NEW_TABLE AS <nom> ? [WHEN <condición> ? <bloque de acciones sobre la base de datos> o <llamada a un procedimiento almacenado> o <llamada a una función externa> DROP TRIGGER <identificador> REPLACE TRIGGER <identificador> <lo mismo que create> Disparadores. Primer ejemplo Disparadores. Primer ejemplo Evento: CREATE TRIGGER: Nombre del T o regla activa. Ej CREATE TRIGGER NuevoPedido – Se modifican las existencias de la tabla productos (a menos) Condición: AFTER: Regla que se activará despues de que tenga lugar el evento (E) ON: Tabla o relación asociada al E. Por ej, ON Producto – Hay menos unidades que el mínimo (x) Acción: UPDATE OF: Atributos actualizables para los E Upadate. Por ej, UPDATE OF unidades WHEN: Condición (C) a verificar después de activarse el T. Por ej, WHEN New.unidades < X – Hacer un nuevo pedido de aquellos productos que tienen menos unidades que X. FOR EACH ROW: Se activara una vez para cada una tuplaque afecte al T. BEGIN ... END: La Acción (A) a emprender. Por ej, BEGIN INSERT INTO ... END CREATE TRIGGER NuevoPedido AFTER UPDATE OF unidades ON Producto E WHEN NEW.unidades < X C FOR EACH ROW BEGIN INSERT INTO PEDIDO CrearNuevoPedido A VALUES (:OLD.código, X, today ()) ... END DBD 2006-2007 NEW y OLD: Permite referenciar a la tupla insertada y eliminada por el T. Por ej, Old.código EJ. CREATE TRIGGER NuevoPedido AFTER UPDATE OF unidades ON Producto WHEN New.unidades<X FOR EACH ROW BEGIN INSERT INTO PEDIDO VALUES ( Old.código, X, today()) ... END Disparadores - Trigger Disparadores: Tipos CREATE TRIGGER <nombre del T.> {AFTER | BEFORE | INSTEAD OF} {INSERT | DELETE | UPDATE [OF <atributo>?} ON <tabla> 2 Comparación BEF-AFT-INS Antes Create trigger T T INSERT... BEFORE insert ON Cuenta Según cuando se ejecutan la acción: – BEFORE trigger • Se ejecuta la acción antes de que se realice la operación que desencadena el evento – Antes de insertar, borrar, modificar... – AFTER trigger • Se ejecuta después de que se realice la operación que desencaden a el evento – Después de insertar, borrar, modificar... – INSTEAD OF trigger EnviarMensaje() Despues INSERT... Create trigger T EnviarMensaje() En lugar de INSERT... Create trigger T INSTEAD OF insert ON Cuenta T EnviarMensaje() INSERT INTO Cuenta VALUES (...) • Se ejecuta en lugar de la operación que desencadena el evento – En lugar de insertar, borrar, modificar Disparadores inmediatos y vistas BEFORE y AFTER – Sólo para tablas de base – NO para vistas • si se inserta en una vista y la tabla de base subyacente tiene un trigger BEFORE o AFTER, entonces sí se dispara. INSTEAD OF – Para vistas • Es una manera transparente de modificar vistas no modificables. T AFTER insert ON Cuenta Disparadores: Tipos CREATE TRIGGER <identificador> {AFTER | BEFORE | INSTEAD OF} {INSERT | DELETE | UPDATE [OF <atributo>?} ON <tabla> [FOR EACH ROW | STATEMENT ? Según el nivel • EACH ROW (A nivel de fila) – Se dispara el trigger una vez por cada una de las tuplas afectadas por la sentencia que desencadena el evento • Insertar 5 tuplas: ?se dispara 5 veces • Modificar 0 tuplas: ?no se dispara • Se pueden usar los valores NEW y OLD para referenciar a los cambios a realizar a la BD. • Si se sabe cuál es la operación asociada a una inserción en una tupla, se puede indicar en un trigger la operación asociada. Disparadores: Tipos CREATE TRIGGER <identificador> {AFTER | BEFORE | INSTEAD OF} {INSERT | DELETE | UPDATE [OF <atributo> ?} ON <tabla> [FOR EACH ROW | STATEMENT ? Según el nivel • EACH ROW (A nivel de fila) • STATEMENT Se dispara el trigger una vez por cada sentencia que desencadena el evento (sin tener en cuenta las tuplas afectadas ni la transacción en que se encuentren) • Insertar 5 tuplas: ?se dispara 1 vez el trigger. • Modificar 0 tuplas: ?se dispara 1 vez el trigger. • Se pueden usar las tablas NEW_TABLE y OLD_TABLE para referenciar a los cambios que se realizan a la BD (SQL Server: INSERTED, DELETED) DBD 2006-2007 • STATEMENT (A nivel de Sentencia) Comparación ROW-STAT Create trigger T BEFORE update ON Cuenta FOR EACH ROW Mensaje() T Update T Update Update modifica 2 tuplas Create trigger T BEFORE update ON Cuenta STATEMENT Mensaje() T Update Update Disparadores - Trigger 3 Combinaciones de triggers Renombrar a OLD y NEW BEFORE statement trigger – Antes de ejecutarse la operación que desencadena el evento se ejecuta la acción del trigger. BEFORE row trigger – Antes de modificar cada una de las filas afectadas por la operación que desencadena el evento y antes de comprobar las reglas de integridad se ejecuta la acción del trigger (éstos no bloquean la fila). AFTER row trigger – Después de modificar cada una de las filas afectadas por la operación que desencadena el evento y las reglas de integridad asociadas, se ejecuta la acción del trigger para la fila actual (éstos bloquean la fila) AFTER statement trigger – Se ejecuta la acción del trigger después de ejecutar la operación que desencadena el evento y después de aplicar las restricciones diferidas. CREATE TRIGGER <identificador> {AFTER | BEFORE | INSTEAD OF} {INSERT | DELETE | UPDATE [OF <atributo>?} ON <tabla> [FOR EACH ROW | STATEMENT ? [REFERENCING OLD AS <nombre> NEW AS <nombre>? [REFERENCING OLD_TABLE AS <nom> NEW_TABLE AS <nom> ? FOR EACH ROW REFERENCING OLD AS <nombre> NEW AS <nombre> - Es posible renombrar las tuplas OLD y NEW STATEMENT REFERENCING OLD_TABLE AS <nom> NEW_TABLE AS <nom> - Es posible renombrar las talbas OLD y NEW Estado de triggers Sintaxis: Disparadores en SQL3 Una regla o trigger, por medio de su nombre, se puede: CREATE TRIGGER <identificador> {AFTER | BEFORE | INSTEAD OF} {INSERT | DELETE | UPDATE [OF <atributo>?} ON <tabla> [FOR EACH ROW | STATEMENT ? [REFERENCING OLD AS <nombre> NEW AS <nombre>? [REFERENCING OLD_TABLE AS <nom > NEW_TABLE AS <nom > ? [WHEN <condici ón> ? – Activar / ENABLE • Se puede disparar • Por defecto (Consultar SGBD) – Desactivar / DISABLE • No se puede disparar La condiciones pueden ser: • Bloque de acciones sobre la base de datos • Llamada a un procedimiento almacenado • Llamada a una función externa Consideración o Acoplamiento – Eliminar / DROP Nota: Se podrían agrupara para facilitar las acciones anteriores . Sintaxis: ALTER TRIGGER <identificador> {ENABLE | DISABLE} DROP TRIGGER <identificador> Consideración o Acoplamiento Acoplamiento Inmediato (INMEDIATE) Cuando se deber realizar la acción activada. La condición se evalúa dentro de la misma transacción que la del • Antes del evento / BEFORE evento que la desencadena y se hace inmediatamente • Despues del evento / AFTER • Simultaneamente al evento / INSTEAD OF • BEFORE: Se evalúa la condición antes de la ejecución de la operación • AFTER: Se evalúa la condición después • INSTEAD OF: Se evalúa la condición en lugar de realizar la operación Acoplamiento diferido (DEFERRED) La acción se realiza en la misma transacción o en una nueva • Consideración Inmediata / INMEDIATE • Consideración Diferida / DEFERRED • Consideración Separada / DETACHED DBD 2006-2007 – La condición se evalúa al final de la transacción que contenía l a operación desencadenadora. En este caso puede haber muchos triggers esperando a evaluar su condición. Acoplamiento separado (DETACHED) – La condición se evalúa dentro de una transacción separada nacida de la transacción desencadenadora. Disparadores - Trigger 4 Acoplamiento inmediato Acoplamiento diferido comienzo de transacción Uso: restricciones de integridad complejas diferidas comienzo de transacción ejecución acción ¿condición? ¿condición? final de transacción Uso: restricciones de integridad complejas que requieren una comprobación inmediata Acoplamiento Inmediato (INMEDIATE) La condición se evalúa dentro de la misma transacción que la del evento que la desencadena y se hace inmediatamente final de transacción Acoplamiento diferido (DEFERRED) La condición se evalúa al final de la transacción que contenía l a operación desencadenadora. En este caso puede haber muchos triggers esperando a evaluar su condición. Acoplamiento separado Ejemplo Uso: restricciones de integridad complejas diferidas comienzo de transacción subtransacción ¿condición? ejecución acción ejecución acción fin subtransacción final de transacción CREATE TRIGGER Ejemplo BEFORE DELETE OR INSERT OR UPDATE OF salario, primas ON TablaEmpleado FOR EACH ROW WHEN salario > 10000 BEGIN ... IF DELETING THEN ... END IF; IF INSERTING THEN ... END IF; IF UPDATING(salario) THEN ... END IF; … END Acoplamiento separado (DETACHED) La condición se evalúa dentro de una transacción separada nacida de la transacción desencadenadora. Ejemplo: BEFORE statement Evitar que los fines de semana los empleados cambien los datos de otros empleados o de ellos mismos Ejemplo: BEFORE statement CREATE TRIGGER Ejemplo BEFORE DELETE OR INSERT OR UPDATE OF suSalario Eventos: ON TablaEmpleado – Insertar, borrar o modificar Tabla Empleado • DELETE OR INSERT OR UPDATE ON TablaEmpleado Condición: – Es fin de semana DAYOFWEEK(TODAY())=‘Sat’ OR DAYOFWEEK(today())=‘Sun’ Acción: – Enviar mensaje de error DBD 2006-2007 WHEN DAYOFWEEK(today())=‘Sat’ OR DAYOFWEEK(today())=‘Sun’ Procedimiento_ChivatoAlJefe() Disparadores - Trigger 5 Ejemplo: BEFORE row Ejemplo: AFTER row CREATE TRIGGER nuevoPedido BEFORE INSERT ON Pedido FOR EACH ROW PEDIDO (nomCli, códigoProd, fecha, cantidad, importe) WHEN True PRODUCTO (códigoProd, fabricante, existencias) BEGIN REPVENTAS (nomCli, ventas) UPDATE RepVentas SET Ventas = Ventas + :NEW.importe WHERE Repventas.nomCli = :NEW.nomCli; Al Introducir un nuevo depósito con saldo negativo se deja el depósito con saldo 0 y se crea un préstamo nuevo con capital=saldo deudor insert UPDATE Producto SET Existencias = Existencias - :NEW.cantidad WHERE Producto.códigoProd = :NEW.códigoProd END Depósito Ejemplo: AFTER row update Depósito insert Préstamo ¿Saldo<0? Ejemplo: AFTER row CREATE TRIGGER saldoDeudor AFTER INSERT ON Depósito FOR EACH ROW WHEN New.saldo<0 DEPÓSITO (numCuenta, nomSucursal, nomCliente, saldo) BEGIN PRÉSTAMO (numCuenta, nomSucursal, nomCliente, saldo) UPDATE Depósito SET saldo = 0 WHERE numCuenta = :NEW.numCuenta; Evento – Introducir un nuevo depósito – FOR INSERT ON Depósito Condición – New.saldo<0 Acción – Dejar saldo a 0 (UPDATE... INSERT INTO Préstamo – Crear un nuevo préstamo (INSERT... VALUES(:NEW.nomSucursal, :NEW.numCuenta, :NEW.nomCliente, :NEW.saldo) END Ejemplo: AFTER row Ejemplo: AFTER row Al modificar el saldo de un depósito y dejarlo con saldo negativo se deja el depósito con saldo 0 y se crea un préstamo nuevo con capital = saldo deudor o se añade el saldo deudor al préstamos existente Evento – Modificar el saldo de un depósito – FOR UPDATE OF saldo ON Depósito Condición update update – New.saldo<0 Depósito Acción Depósito ¿Saldo<0? – Dejar saldo a 0 (UPDATE... insert Préstamo – Si existe préstamo, UPDATE Préstamo – Si no, Crear un nuevo préstamo (INSERT... DBD 2006-2007 Disparadores - Trigger 6 Ejemplo: datos derivados Ejemplo: AFTER row CREATE TRIGGER saldoDeudor AFTER UPDATE OF saldo ON Depósito FOR EACH ROW WHEN New.saldo<0 BEGIN UPDATE Depósito SET saldo=0 WHERE numCuenta = :New.numCuenta; IF EXISTS (SELECT * FROM Préstamo WHERE numCuenta = :New.numCuenta) THEN UPDATE Préstamo SET saldo = saldo + :New.saldo WHERE numCuenta = :New.numCuenta; ELSE INSERT INTO Préstamo VALUES(: New.numCuenta, :New.nomSucursal, :New.nomCliente, :New.saldo) END IF Regla de negocio: – El presupuesto en personal de los departamentos es la suma de los sueldos de todos sus empleados – Los empleados pueden aparecer temporalmente sin adscripción BD – Empleado (dni, nombre, sueldo, numDpto, dniDeSuJefe) – Departamento (núm, nombreD, presupuesto, dniDelDirector) Eventos importantes: – Contratar empleados (insertar empleados) – Cambiar el salario de uno o más empleados (modificar) – Reasignar un empleado de un depto a otro (modificar) – Despedir empleados (borrar empleados) END Ejemplo: datos derivados Evento: Ejemplo: datos derivados CREATE TRIGGER añadirEmpleados – Contratar nuevos empleados – INSERT ON Empleado Condición – El empleado nuevo está adscrito a un departamento – New.numDepto IS NOT NULL BEFORE INSERT ON Empleado FOR EACH ROW WHEN New.numDpto IS NOT NULL UPDATE Departamento SET presupuesto = presupuesto + :New.sueldo Acción – Actualizar presupuesto personal de ese departamento Ejemplo: datos derivados Evento: – Cambiar el salario de uno o varios empleados – UPDATE OF sueldo ON Empleado Condición – El empleado nuevo está adscrito a un departamento Acción – Actualizar presupuesto personal de ese departamento DBD 2006-2007 WHERE num = :New.numDpto Ejemplo: datos derivados CREATE TRIGGER cambiarSueldoEmpleados AFTER UPDATE OF sueldo ON Empleado FOR EACH ROW WHEN New.numDpto IS NOT NULL UPDATE Departamento SET presupuesto = presupuesto + :New.sueldo :Old.sueldo WHERE num = :New.numDpto Disparadores - Trigger 7 Ejemplo: datos derivados Evento: Ejemplo: datos derivados – Cambiar la adscripción de uno o más empleados de un depto a otro CREATE TRIGGER reasignarEmpleados AFTER UPDATE OF numDpto ON Empleado FOR EACH ROW – UPDATE OF numDpto ON Empleado BEGIN UPDATE Departamento SET presupuesto = presupuesto + :New.sueldo Condición – No hay WHERE num = :New.numDpto UPDATE Departamento Acción – Actualizar presupuesto personal del departamento origen – Actualizar presupuesto personal del departamento destino SET presupuesto = presupuesto - :New.sueldo WHERE num = :Old.numDpto END Ejemplo: datos derivados Evento: Ejemplo: datos derivados CREATE TRIGGER añadirEmpleados – Despedir empleados AFTER DELETE ON Empleado – DELETE ON Empleado FOR EACH ROW Condición WHEN Old.numDpto IS NOT NULL – El empleado estaba adscrito a un departamento Acción UPDATE Departamento SET presupuesto = presupuesto - :Old.sueldo WHERE num = :Old.numDpto – Actualizar presupuesto personal de ese departamento Ejemplo: INSTEAD OF CREATE VIEW EmpleadosConDepto AS SELECT Empleado.nombre, Departamento.nombreD FROM Empleado INNER JOIN Departamento ON numdpto=num Ejemplo: INSTEAD OF Con esta vista sólo se puede reasignar empleados a otros departamentos que ya existen. Cualquier otra operación se debe ignorar (ignorar para simplificar, error sería más conveniente). Evento – UPDATE OF nombreD ON EmpleadosConDepto Esta vista, ¿Es modificable? ¡NO! (join, sin claves, etc.) Condición – El nombre del nuevo departamento existe ya – EXISTS (SELECT * FROM Departamento WHERE Departamento.nombreD=New.nombreD) El ABD puede considerar cómo se deben interpretar las inserciones en la vista y aplicarlo mediante un trigger INSTEAD OF DBD 2006-2007 Acción – Localizar el código del departamento nuevo – Asignar el código de ese departamento al empleado Disparadores - Trigger Ejemplo: INSTEAD OF CREATE TRIGGER actualizarVista INSTEAD OF UPDATE OF nombreD ON EmpleadosConDepto WHEN EXISTS (SELECT * FROM Departamento WHERE nombreD=New.nombreD) FOR EACH ROW DECLARE elCódigoDpto NUMBER; BEGIN SELECT num INTO : elCódigoDpto FROM Departamento WHERE nombreD = :New.nombreD UPDATE Empleado SET numDpto = :elCódigoDpto WHERE nombre = :New.nombre END 8 Algoritmo de ejecución Dada una operación P a realizar sobre la base de datos • Ejecutar los BEFORE statement triggers de las tablas afectadas por P • Para cada fila afectada por la operación – Ejecutar BEFORE row triggers – Bloquear, efectuar operación sobre la fila y comprobar posibles restricciones de integridad (no se libera el bloqueo hasta que se acaba la transacción) – Ejecutar AFTER row triggers • Comprobar restricciones de integridad intertabla • Ejecutar los AFTER statement triggers de las tablas afectadas por P Modelo de ejecución Modelo de ejecución • Dimensiones – ¿Cuántas instancias de regla se disparan? • todas – ¿Qué ocurre si se produce un evento durante la ejecución de una regla? • Proceso recursivo • Procesos anidados – ¿Cuándo se evalúa la condición (acción) respecto al evento (condición)? (modo de acoplamiento) • inmediato, diferido, separado Usos de los disparadores • Conservar integridad de datos más allá de la int. Ref. – Prevenir transacciones inválidas – Otras restricciones de integridad • Restricciones de integridad referencial entre tablas de una BD distribuida • Otras RI que no se pueden representar con los métodos normales – NOT NULL, UNIQUE, PRIMARY KEY, FOREIGN KEY, CHECK – DELETE CASCADE, UPDATE CASCADE, DELETE SET NULL... • Asegurar el cumplimiento de reglas de negocio complejas • Mantener datos derivados – – – – – En otras tablas actualizados (totales...) Generación automática de columnas derivadas Mantener réplicas síncronas de tablas Mantenimiento de vistas materializadas (vistas almacenadas) Modificar datos de las tablas de base DBD 2006-2007 • Oracle y SQL Server – ¿Cuántas instancias de reglas se disparan? • todas (orden indeterminado) – ¿Qué ocurre si se produce un evento durante la ejecución de una regla? • proceso recursivo (máximo 32) – ¿Cuándo se evalúa la condición respecto al evento? • inmediato – ¿Qué ocurre si se produce un error durante la ejecución de una regla? • todo el proceso es invalidado Usos de los disparadores • Auditar ciertos eventos aparte de los que ofrece el SGBD – Crear un “log” con eventos que nos interesen – Recoger estadísticas de actualización a las tablas • Llamar a sistemas externos al SGBD – Otras aplicaciones asociadas al SGBD – Informar a otras aplicaciones sobre eventos sobre la BD • Notificar situaciones de los datos a usuarios – Enviar e-mail, mensaje al móvil, busca. Disparadores - Trigger 9 Inconvenientes Ventajas • SGBD centraliza y aplica las reglas de negocio – Se reducen los programas de aplicación • BD más compleja – Más complejidad en el diseño, implementación y administración de las BD • Hay que incluir la lógica de los disparadores – Funcionalidad oculta • Una operación sencilla puede tener efectos laterales – El usuario no tiene control sobre todo lo que ocurre en la BD – Pueden existir dos triggers que se contradigan • Sobrecarga del sistema – El sistema tiene que evaluar las condiciones de los triggers para cada operación con la BD • Menos eficiencia, cuantos más triggers, peor • No se garantiza la terminación – SQL Server + Oracle (máximo 32 anidamientos) Disparadores en otros sistemas SQL3 Oracle MSSQL Informix Ingres Rdb Interbase opción before Sí Sí Sí Sí sí Sí Sí opción after Sí Sí Sí Sí Sí Sí Sí opción instead_of Sí No Sí No No No No condición Sí Sí Sí Sí Sí Sí No row triggers Sí Sí No Sí Sí Sí Sí ref. old/new Sí Sí No Sí Sí Sí Sí statement triggers Sí Sí Sí Sí No No No ref. old/new table Sí No Sí No No No No prioridades Sí No No No No No Sí disparo en cascada Sí Sí Sí Sí Sí Sí Sí profundidad cascada infinito 32 32 61 20 infinito ? DBD 2006-2007