6. Triggers
6.1. Introducció
Un disparador és un bloc de codi, associat a una taula, que s'executa abans o després que passe una acció concreta d'inserció, esborrat o modificació sobre eixa taula.
Per exemple, donada la següent taula:
| SQL | |
|---|---|
Volem fer que cada vegada que s'inserisca un nou compte, que s'acumule en una variable el saldo dels comptes. Per a fer això crearem el següent disparador:
| SQL | |
|---|---|
Hem definit el disparador de nom abans_ins_compte així: "Abans d'inserir en la taula comptes, per cada fila a inserir, acumula el nou saldo en la variable @suma".
Com que @suma fa d'acumulador, abans d'usar-lo caldrà inicialitzar-lo a 0:
| SQL | |
|---|---|
6.2. Sintaxi de CREATE TRIGGER
| SQL | |
|---|---|
Sobre la sentència
- La sentència pot ser composta (bloc BEGIN-END). En eixe cas, caldrà indicar que el delimitador de sentències no siga el ";", amb DELIMITER.
- En la sentència podran haver sentències condicionals, bucles...
Nota
Quan es fa una acció sobre una taula, primer s'executa el bloc associat al BEFORE, després la pròpia acció (insert, update, delete) i després el bloc associat al AFTER. Per tant, si donara error alguna d'estes accions, no s'executarien les següents.
Per a esborrar-lo:
| SQL | |
|---|---|
6.3. Els àlies OLD i NEW
En la sentència que s'executarà per a cada registre afectat, es pot fer referència als valors d'este registre abans i/o després de fer una acció d'UPDATE/INSERT/DELETE:
| Acció | OLD | NEW |
|---|---|---|
| UPDATE | Valor del camp abans de ser modificat | Valor del camp després de ser modificat |
| INSERT | (no té sentit) | Valor que s'insereix en eixe camp |
| DELETE | Valor del camp del registre que s'esborra | (no té sentit) |
6.4. Limitacions dels disparadors
- Limitacions en els noms:
- Una taula no pot tindre dos disparadors amb el mateix nom. I és convenient que en una mateixa BD no es repetisquen els noms dels disparadors.
- Limitacions en els tipus:
- En una taula no poden haver dos disparadors del mateix tipus. Per exemple, no pot tindre dos disparadors BEFORE UPDATE.
- Limitacions en la sentència:
- No es pot usar el
CALL(invocar procediments emmagatzemats), però sí invocar a funcions. - No es poden iniciar o acabar transaccions (
START TRANSACTION,COMMIToROLLBACK). - En BEFORE INSERT, el valor NEW per a una columna AUTO_INCREMENT és 0.
- Permisos:
- Per a fer
SET NEW.nom_camp = valorcal tindre permís d'UPDATE sobre la columnanom_camp(i fer-ho en triggers de tipus BEFORE). - Per a fer
SET nom_var = NEW.nom_campcal tindre permís de SELECT sobre la columnanom_camp.
- Per a fer
- No es pot usar el
6.5. Algunes utilitats
- Actualitzar camps de taules que depenen del valor d'altres camps: import en una línia de factura, el total d'una factura...
- Modificar els valors a introduir en la taula (amb BEFORE INSERT o BEFORE UPDATE):
Exemple: controlar que una nota estiga entre 0 i 10
Nota
Caldria repetir el mateix per a BEFORE INSERT. I estaria bé poder posar les sentències associades en un procediment emmagatzemat, però MySQL no permet fer ús del CALL en els disparadors.
6.6. Exercicis de triggers
10. En la taula de golejadors, entre altres camps estan: gols, gtitular i gsuplent. Realment el camp de gols no hauria d'estar ja que es pot calcular com la suma dels altres dos, però està per optimitzar consultes, etc.
- a) Fes els triggers necessaris per a assegurar que el camp gols sempre serà la suma dels altres dos.
- b) Fes alguna inserció en la taula de golejadors i alguna modificació, posant aposta els gols que no sumen els gols com a titular i com a suplent. Després comprova que ha funcionat: mira si els gols són igual a la suma dels altres dos camps.
11. Volem tindre en la taula d'equips un camp que guarde la quantitat de defenses que té cada equip (encara que sabem que serà un camp redundant, ja que es podria calcular a partir de la taula de jugadors). Per a això, fes el següent:
- a) Afig a la taula d'equips el camp qdefenses.
- b) Ompli els valors d'eixa columna per a cada equip existent en la base de dades.
- c) Fes els triggers necessaris per a mantindre sempre actualitzat eixe camp.
- d) Fes canvis amb els defenses de la base de dades per a vore que els triggers funcionen.
12. (BD geografia) Volem tindre en la taula de rius un camp que guarde la quantitat de províncies per on passa cadascun (encara que sabem que serà un camp redundant, ja que es podria calcular a partir de la taula passaper). Per a això, fes el següent:
- a) Afig a la taula de rius el camp qprov.
- b) Ompli els valors d'eixa columna per a cada riu existent en la base de dades.
- c) Fes els triggers necessaris per a mantindre sempre actualitzat eixe camp.
- d) Fes canvis amb els rius de la base de dades per a vore que els triggers funcionen.