Trigger Overview
Un trigger, come suggerisce il nome (grilletto), è un insieme di istruzioni che si eseguono, o vengono attivate, quando un dato evento avviene su una tabella.
L'evento può essere una INSERT, una UPDATE o una DELETE.
Creare un trigger
Ecco un semplice esempio per vedere un trigger in azione. Utilizzeremo come esempio queste due tabelle:
MariaDB [test]> CREATE TABLE animals (id mediumint(9) NOT NULL AUTO_INCREMENT, name char(30) NOT NULL, PRIMARY KEY (`id`)); Query OK, 0 rows affected (0.29 sec) CREATE TABLE animal_count (animals int); INSERT INTO animal_count (animals) VALUES(0);
Vogliamo incrementare un contatore ogni volta che un animale viene aggiunto. Ecco il trigger necessario:
MariaDB [test]> CREATE TRIGGER increment_animal AFTER INSERT ON animals FOR EACH ROW UPDATE animal_count SET animal_count.animals = animal_count.animals+1;
Il trigger ha:
- un nome (in questo caso
increment_animal) - una tempistica (in questo caso after, dopo l'evento specificato)
- un evento (una
INSERT) - una tabella al quale è associato (
animals) - un insieme di istruzioni da eseguire (in questo caso una sola istruzione UPDATE)
AFTER INSERT specifica che il trigger deve essere eseguito dopo una INSERT. Il trigger può anche essere impostato per agire prima, e l'istruzione che aziona il trigger può anche essere una DELETE o una UPDATE.
Ora, se inseriamo un record nella tabella animals, il trigger verrà eseguito, incrementando la tabella animal_count;
MariaDB [test]> SELECT * FROM animal_count;
+---------+
| animals |
+---------+
| 0 |
+---------+
MariaDB [test]> INSERT INTO animals (name) VALUES('aardvark');
MariaDB [test]> INSERT INTO animals (name) VALUES('baboon');
MariaDB [test]> SELECT * FROM animal_count;
+---------+
| animals |
+---------+
| 2 |
+---------+
Per ulteriori dettagli sulla sintassi, si veda CREATE TRIGGER.
Eliminare i trigger
Per eliminare un trigger, si usa l'istruzione DROP TRIGGER. I trigger inoltre vengono eliminati se si elimina la tabella alla quale sono associati.
MariaDB [test]> DROP TRIGGER increment_animal;
Trigger più complessi
I trigger possono consistere di più istruzioni racchiuse tra BEGIN e END. Se si stanno inserendo queste istruzioni dalla riga di comando, è necessario impostare temporaneamente un nuovo delimitatore, per poter utilizzare i punto e virgola come delimitatore per le istruzioni che compongono il trigger.
MariaDB [test]> DROP TABLE animals;
MariaDB [test]> UPDATE animal_count SET animals=0;
MariaDB [test]> CREATE TABLE animals (id mediumint(9) NOT NULL AUTO_INCREMENT,
name char(30) NOT NULL,
PRIMARY KEY (`id`))
ENGINE=InnoDB;
MariaDB [test]> DELIMITER //
CREATE TRIGGER the_mooses_are_loose
AFTER INSERT ON animals
FOR EACH ROW
BEGIN
IF NEW.name = 'Moose' THEN
UPDATE animal_count SET animal_count.animals = animal_count.animals+100;
ELSE
UPDATE animal_count SET animal_count.animals = animal_count.animals+1;
END IF;
END; //
MariaDB [test]> DELIMITER ;
MariaDB [test]> INSERT INTO animals (name) VALUES('Aardvark');
MariaDB [test]> SELECT * FROM animal_count;
+---------+
| animals |
+---------+
| 1 |
+---------+
MariaDB [test]> INSERT INTO animals (name) VALUES('Moose');
MariaDB [test]> SELECT * FROM animal_count;
+---------+
| animals |
+---------+
| 101 |
+---------+
1 row in set (0.00 sec)
Errori nei trigger
Se un trigger contiene un errore e lo Storage Engine è transazionale, il trigger non si esegue, e non viene eseguita nemmeno l'istruzione originale. Se l'Engine non è transazionale, il trigger non si esegue, ma l'istruzione originale sì.
Qui di seguito abbandoniamo gli esempi precedenti, e ricreiamo il trigger con un errore, cioè un campo che non esiste, utilizzando prima lo Storage Engine predefinito InnoDB, che è transazionale, e poi usando MyISAM, uno Storage Engine non transazionale.
MariaDB [test]> DROP TABLE animals;
MariaDB [test]> CREATE TABLE animals (id mediumint(9) NOT NULL AUTO_INCREMENT,
name char(30) NOT NULL,
PRIMARY KEY (`id`))
ENGINE=InnoDB;
MariaDB [test]> CREATE TRIGGER increment_animal
AFTER INSERT ON animals
FOR EACH ROW
UPDATE animal_count SET animal_count.id = animal_count_id+1;
MariaDB [test]> INSERT INTO animals (name) VALUES('aardvark');
ERROR 1054 (42S22): Unknown column 'animal_count.id' in 'field list'
MariaDB [test]> SELECT * FROM animals;
Empty set (0.00 sec)
E ora la stessa procedura, ma su una tabella MyISAM.
MariaDB [test]> DROP TABLE animals;
MariaDB [test]> CREATE TABLE animals (id mediumint(9) NOT NULL AUTO_INCREMENT,
name char(30) NOT NULL,
PRIMARY KEY (`id`))
ENGINE=MyISAM;
MariaDB [test]> CREATE TRIGGER increment_animal
AFTER INSERT ON animals
FOR EACH ROW
UPDATE animal_count SET animal_count.id = animal_count_id+1;
MariaDB [test]> INSERT INTO animals (name) VALUES('aardvark');
ERROR 1054 (42S22): Unknown column 'animal_count.id' in 'field list'
MariaDB [test]> SELECT * FROM animals;
+----+----------+
| id | name |
+----+----------+
| 1 | aardvark |
+----+----------+
1 row in set (0.00 sec)