5 triggers

37
Triggers-Disparadores

Upload: rsmaster69

Post on 29-Nov-2015

100 views

Category:

Documents


7 download

TRANSCRIPT

Triggers-Disparadores

• Clase especial de procedimiento almacenado que se ejecuta automáticamente (se “dispara”) cuando se produce un evento especifico.

• Se ejecuta siempre que se intenta modificar los datos de una tabla que el trigger protege: realizar un INSERT, UPDATE o DELETE.

• No es posible evitar su ejecución.• Los triggers se definen para una tabla específica,

denominada tabla del trigger.

• Mysql no soporta multiples triggers para una misma accion en una misma tabla…aun.

• Los eventos pueden ser las sentencias INSERT, DELETE, UPDATE que modifican los datos de una tabla.

• Los triggers se pueden ejecutar antes (BEFORE) y/o después (AFTER) de que sean modificados los datos.

• Los triggers tienen dos palabras clave, OLD y NEW que se refieren a los valores que tienen las columnas antes y después de la modificación.

• Los INSERT permiten NEW, los DELETE sólo OLD y los UPDATE ambas.

• Sintaxis:

• No es posible invocar directamente los triggers, que tampoco pasan ni aceptan parámetros.

• Gran herramienta para controlar reglas de negocio más complejas que una simple integridad referencial.

• Ojo: el usuario no espera que el trigger le devuelva registros luego de agregar o modificar información. (no lo hace).

• INSERT

• Aplicar reglas de negocio…???• Validacion de datos.

• Las personas que se registren en la BD universidad deben ser mayores de 18 años.

• Cómo seria la condicion?

• Before insert o after insert??

Condicion a para validar:

IF ((datediff(curdate(),fecha_nacimiento))/365)<18 THEN…

Qué se debe hacer o no hacer al cumplirse esta condicion???

DELIMITER $CREATE TRIGGER insert_persona BEFORE INSERT ON personaFOR EACH ROWBEGINdeclare fecha date;set fecha=new.fecha_nacimiento;IF ((datediff(curdate(),fecha))/365)<18 THEN

…END IF;END;$

DELIMITER $CREATE TRIGGER insert_persona BEFORE INSERT ON personaFOR EACH ROWBEGINdeclare fecha date;set fecha=new.fecha_nacimiento;IF ((datediff(curdate(),fecha))/365)<18 THEN set @msg = 'Trigger Error: menor de edad: '; signal sqlstate '45000' set message_text = @msg;END IF;END;$

Se puede entonces:

• Generar un PA simple para insercion, que tome en cuenta reglas de integridad.

• Generar un trigger on insert que tome en cuenta la regla de negocio.

• Ojo: para conocer los triggers generados:– SELECT * FROM INFORMATION_SCHEMA.TRIGGERS– show triggers

• Ejercicio.

• Usar BD practico 1 select.• Se necesita insertar un producto cuya fecha de

vencimiento sea minimo en 15 dias despues del registro. Si no es asi, no se debe realizar la insercion.

• Generar PA de insercion en producto que tome en cuenta integridad referencial (pk y fk).

• Regla de negocio la manejara trigger: before o after?• Hacer pruebas.

DELIMITER $CREATE TRIGGER insert_producto BEFORE INSERT ON productoFOR EACH ROWBEGINIF new.fecha_vencimiento-curdate()<15 then set @msg = 'Trigger Error: No se aceptan productos a vencer

en menos de 15 dias'; signal sqlstate '45000' set message_text = @msg;END IF;END;$

• Ejercicio.

• Se necesita insertar un producto nuevo. Si su stock es menor que 10, no se debe realizar la insercion.

• PA de insercion ya esta creado.***• Generar trigger.• Hacer pruebas.

DELIMITER $CREATE TRIGGER insert_pro_stock BEFORE INSERT ON productoFOR EACH ROWBEGINIF new.stock<10 then set @msg = 'Trigger Error: No se acepta stock tan bajo'; signal sqlstate '45000' set message_text = @msg;END IF;END;$

• Ejercicio.

• El almacen solo maneja 5 productos por proveedor registrado en la BD. No se debe poder insertar un nuevo producto si no se cumple esta regla.

• PA de insercion creado.***• Generar trigger.• Hacer pruebas.

DELIMITER $CREATE TRIGGER insert_pro_prov BEFORE INSERT ON productoFOR EACH ROWBEGINIF (select count(*) from producto where

proveedor_codigo_proveedor=new.proveedor_codigo_proveedor)>=5 then

set @msg = 'Trigger Error: No se aceptan mas productos por proveedor'; signal sqlstate '45000' set message_text = @msg;END IF;END;$

• Ejercicio.

• Insercion en producto.• …• Regla: Si el producto es de marca nestle, no se acepta

un stock mayor a 15. • PA de insercion creado.***• Generar trigger.• Hacer pruebas.

DELIMITER $CREATE TRIGGER insert_nestle BEFORE INSERT ON productoFOR EACH ROWBEGINIF new.marca='nestle' and new.stock>15 then set @msg = 'Trigger Error: No se acepta stock mayor a 15 en

productos de esta marca'; signal sqlstate '45000' set message_text = @msg;END IF;END;$

• Trigger After Insert• Para que nos podria servir este tipo de

trigger?

• Respaldo, auditoria de datos, y…..

• Se necesita un trigger que, hecha la compra de una cantidad de producto, actualice el stock.

• Se asume que existe el stock necesario.

• Que tipo de trigger es?• Sobre que tabla?

• Hacer pruebas.

DELIMITER $CREATE TRIGGER insert_after_detalle after INSERT ON

detalle_ventaFOR EACH ROWBEGINupdate productoset stock=stock-new.cantidadwhere codigo_producto=new.producto_codigo_producto;END;$

• Ahora, que pasa si no esta el stock necesario?

• No se podria insertar la compra de tal cantidad de producto…

• Como seria el trigger? (Complementar anterior)

• Before o after insert?• Pienselo en casa con tranquilidad…

• Trigger para Update.

• Cuando usarlos?• Verificar una condicion antes de hacer el

update.

• Se necesita verificar que, si al modificar el precio de algun producto especifico, este nuevo precio no sea superior al doble del precio actual.

• Como seria el trigger?• Before/after?

DELIMITER $CREATE TRIGGER insert_before_prod before UPDATE ON

productoFOR EACH ROWBEGIN

IF new.precio>old.precio*2 then set @msg = 'Trigger Error: No se puede subir tanto los

precios'; signal sqlstate '45000' set message_text = @msg;END IF;END;$

• Al modificar algun dato de sucursal, se debe manejar un respaldo de estos datos (los antiguos), incluida fecha y usuario que genero la modificacion.

• Modificar telefono de sucursal.• Generar PA para modificacion de sucursal (telefono)

a partir de su codigo.

• Cómo sería el trigger?

create table info2(id int auto_increment,codigos varchar(8),telefono varchar(20),fecha date,usuario varchar(15),primary key (id));

DELIMITER $CREATE TRIGGER insert_after_suc after UPDATE ON

sucursalFOR EACH ROWBEGINinsert into info2 (codigos, telefono, fecha, usuario)values(old.codigo_sucursal, old.telefono_sucursal,

curdate(), current_user());END;$

• Ejercicio.

• No esta permitido realizar modificaciones los fines de semana.

• Tomar en cuenta la modificacion de telefono de sucursal.

• Generar trigger que verifique esto.• Before/after?

DELIMITER $CREATE TRIGGER update_before_suc before UPDATE ON sucursalFOR EACH ROWBEGINif dayname(curdate()) in ('Saturday','Sunday') then set @msg = 'Trigger Error: No se puede actualizar los fines de

semana'; signal sqlstate '45000' set message_text = @msg;END IF;END;$

• Trigger para DELETE.

• Para qué podria usarse un trigger para delete?

• Verificar condiciones de borrado.• Respaldos.

• Ejercicio.

• El almacen ha decidido que no se pueden eliminar productos de la BD que no hayan vencido aun.

• Qué tipo de trigger es?• BEFORE/AFTER?

DELIMITER $CREATE TRIGGER delete_prod before delete ON productoFOR EACH ROWBEGINif old.fecha_vencimiento>curdate() then set @msg = 'Trigger Error: No se puede eliminar productos que

aun no esten vencidos'; signal sqlstate '45000' set message_text = @msg;END IF;END;$

• Ejercicio.

• Al eliminarse un producto, se debe manejar un respaldo de los datos eliminados, incluida fecha y usuario que genero la eliminacion.

• Creacion de tabla respaldo.• BEFORE/AFTER?

create table info3(id int auto_increment,codigos varchar(8),nombre varchar(20),Marca varchar(15),Precio int,Fecha_v date,Stock int,Proveedor varchar(6),Fecha_eliminacion date,usuario varchar(15),primary key (id));

DELIMITER $CREATE TRIGGER delete_after_prod after delete ON productoFOR EACH ROWBEGINinsert into info3 (codigos, nombre, marca, precio, fecha_v, stock,

proveedor, fecha_eliminacion, usuario)values(old.codigo_producto, old.nombre_fantasia, old.marca,

old.precio, old.fecha_vencimiento, old.stock, old.proveedor_codigo_proveedor, curdate(), current_user());

END;$