Triggers (disparadores) en mySQL
Enviado por miguelcarmona :: 18 de diciembre de 2009
Hoy en día, prácticamente todos los motores de bases de datos populares y en mantenimiento incorporan una gran utilidad llamada triggers. Esta utilidad viene a ser como una acción a realizar automáticamente cuando hagamos una manual.
Básicamente un trigger realiza una acción cuando hacemos un insert, update o delete sobre una tabla determinada (a la que le hemos asignado dicho trigger).
Partamos de un ejemplo y lo explico:
DELIMITER |
CREATE TRIGGER mailtransport_insert AFTER INSERT ON mail_domain
FOR EACH ROW BEGIN
INSERT INTO mail_transport
(sys_userid, sys_groupid, sys_perm_user, sys_perm_group, server_id, domain_id, domain,
transport, sort_order, active)
VALUES
(1, 1, 'ruid', 'ruid', 100, NEW.domain_id, NEW.domain, concat('smtp:mail.', NEW.domain), 1, 'y');
END
|
DELIMITER ;
- Empezamos definiendo que el delimitador de fin de línea sql es ‘|’.
- Creamos un trigger en la tabla mailtransport_insert de forma que se ‘lance’ posteriormente a la inserción de algún dato en dicha tabla.
- Indicamos que para cada inserción que se realice (FOR EACH ROW BEGIN), debe realizar lo que haya en el interior del bucle (hasta END).
Como veis, es realmente sencillo e intuitivo. Si os fijáis en los valores a insertar dentro del bucle, veréis que hay unos campos con ‘NEW.’ delante. Esto quiere decir que debe recoger el nuevo valor para ese campo (osease, el que hemos insertado).
Para terminar, deberemos volver a definir el delimitador de fin de sentencia sql a ‘;’ (que suele ser el valor por defecto). Si no hubiésemos cambiado el delimitador al principio, justo al llegar a la línea de VALUES antes de END se hubiese ejecutado la consulta, y al estar sin terminar, nos hubiese retornado un estrepitoso error de sentencia mysql.
Como indiqué al principio, este «lanzador» podemos utilizarlo también para actualizaciones (UPDATE) y eliminaciones (DELETE). Os dejo un ejemplo de cada:
DELIMITER |
CREATE TRIGGER mailtransport_update AFTER UPDATE ON mail_domain
FOR EACH ROW BEGIN
UPDATE mail_transport
SET
domain = NEW.domain,
transport = concat('smtp:mail.', NEW.domain)
WHERE
domain_id = NEW.domain_id;
END
|
DELIMITER ;
DELIMITER |
CREATE TRIGGER mailtransport_delete BEFORE DELETE ON mail_domain
FOR EACH ROW BEGIN
DELETE FROM mail_transport WHERE domain = OLD.domain;
END
|
DELIMITER ;
Para aquellos a los que le pique la curiosidad de el porqué de esos nombres de tablas, diré en mi defensa que es para que cada vez que se de de alta un nuevo correo electrónico (en el panel de control de ispconfig versión 3), lo añada en la tabla de transportes con un id de servidor 100.
Básicamente es porque me vi en la necesidad de poner un servidor de reserva de correo, de forma que si el principal caía, el servidor de reserva recogía el correo y lo almacenaba hasta que el principal estuviese de nuevo «online».
Así pues, gracias a openVPN y a la replicación de tablas de mysql, en cuestión de un par de horas tenía el sistema funcionando correctamente, sin tener que hacer ningún cambio en el servidor principal, y teniendo el servidor de reserva «auto actualizado» fácilmente sin tener que hacer cambios en el código de dicho panel.