|
| ||||||||||||||||||||||
TriggersJosé Manuel Pérez Barberà Introducció¶Un trigger (disparador) és un bloc de codi PL/SQL que s'executa automàticament quan ocorre un esdeveniment en la base de dades. És a dir, no cal cridar-lo manualment: s'activa sol quan passa alguna cosa. Normalment, l'esdeveniment és una operació Triggers, procediments i funcions¶Tant els triggers com els procediments i les funcions guarden codi PL/SQL en la base de dades. La diferència és qui decideix quan s'executa:
Per tant, si el codi s'ha d'executar sempre que passe alguna cosa, cal un trigger. En canvi, si es vol decidir quan s'executa, cal un procediment. Moment d'execució¶Un trigger s'executa en un moment concret respecte de l'operació
A més, es poden combinar diverses operacions en un mateix trigger, com També cal indicar quantes vegades s'executa:
Estructura bàsica d'un trigger (
|
| Operació | :OLD |
:NEW |
|---|---|---|
INSERT |
❌ No existeix | ✅ Sí |
UPDATE |
✅ Sí | ✅ Sí |
DELETE |
✅ Sí | ❌ No existeix |
Exercici: Trigger de validació
Crea un trigger que:
- Es diga
trg_validar_salari. - S'execute abans d'inserir o modificar.
- Actue sobre
employees. - S'execute per cada fila.
- Llance un error si el salari és negatiu.
Exercici: :NEW i :OLD
Crea un trigger que:
- S'execute
AFTER UPDATEsobreemployees. - S'execute per cada fila.
- Si el salari canvia, mostre per pantalla
Salari antic: X - Salari nou: Y.
Triggers i regles de negoci¶
Els triggers permeten aplicar regles de negoci directament en la base de dades. No obstant això, no totes les regles són bones candidates.
Regles adequades per a triggers¶
Com a regla pràctica, si una regla s'ha de complir sempre, independentment de l'aplicació que accedisca a les dades, pot ser una bona candidata a trigger. És el cas de:
- Validacions simples: comprovar que les dades tenen valors vàlids.
- Control d'integritat addicional: restriccions que no es poden expressar amb
CHECKo claus foranes. - Auditoria: registrar els canvis en una taula d'historial.
- Automatització senzilla: assignar dates, valors per defecte, etc.
Regles poc adequades per a triggers¶
En canvi, si la regla és complexa o pot evolucionar molt, és millor implementar-la en procediments o en la capa d'aplicació. És el cas de:
- Processos molt complexos: són difícils de depurar si s'executen de manera oculta.
- Lògica que afecta moltes taules: multiplica els efectes de cada operació.
- Processos batch o càlculs pesats: alentirien cada operació sobre la taula.
- Regles que canvien sovint: és més fàcil mantindre-les en l'aplicació.
Riscos dels triggers¶
Encara que siguen útils, els triggers tenen uns riscos que cal tindre en compte:
- Efectes ocults: el codi s'executa automàticament i pot ser difícil saber què està passant.
- Manteniment difícil: si una taula té molts triggers, entendre'n el comportament es complica.
- Rendiment: si el trigger fa consultes o operacions costoses, alenteix totes les operacions que el disparen.
Exercici: Regles de negoci
Indica si posaries cadascuna d'aquestes regles en un trigger i justifica-ho:
- No permetre salaris negatius.
- Calcular les nòmines mensuals de tota l'empresa.
- Registrar cada canvi de salari.
Solució
- Sí, perquè és una validació simple i obligatòria.
- No, perquè és un procés complex i massiu (millor un procediment o un procés batch).
- Sí, perquè és una auditoria automàtica.
Bones pràctiques i errors comuns¶
Bones pràctiques¶
Per reduir els riscos anteriors, és convenient seguir aquestes pautes:
- Moderació: no abusar dels triggers.
- Documentació: explicar què fa cada trigger i per què.
- Simplicitat: mantindre la lògica senzilla.
- Noms descriptius: utilitzar el prefix
trg_.... - Rendiment: revisar-ne l'impacte abans de posar-lo en producció.
Errors freqüents¶
Els errors més habituals en treballar amb triggers són:
- Taula mutant (mutating table): consultar o modificar la mateixa taula dins d'un trigger
FOR EACH ROW(vegeu Error de taula mutant). COMMITdins d'un trigger: no està permés, ja que trenca la gestió de transaccions.- Encadenar triggers sense control: un trigger que provoca una acció que activa un altre trigger pot generar comportaments inesperats.
Exercici: Quin error té aquest trigger?
Solució
No es pot utilitzar COMMIT dins d'un trigger, ja que la gestió de la transacció
correspon a la sentència principal.
Error de taula mutant¶
Un error habitual en Oracle DB és l'error de taula mutant, que es produeix quan un trigger fila a fila intenta llegir la mateixa taula que està modificant.
Per exemple, es vol crear un trigger que comprove el salari mitjà d'un centre de treball
cada vegada que s'actualitza un salari a employees, i que llance un error si supera 5000:
CREATE OR REPLACE TRIGGER trg_check_avg_salary
AFTER UPDATE OF salary ON employees
FOR EACH ROW
DECLARE
v_avg_salary NUMBER;
BEGIN
-- Intent de llegir la mateixa taula dins del trigger
SELECT AVG(salary) INTO v_avg_salary
FROM employees
WHERE center_id = :NEW.center_id;
IF v_avg_salary > 5000 THEN
RAISE_APPLICATION_ERROR(-20001, 'Salari mitjà del centre massa alt');
END IF;
END;
/
Si s'actualitza un salari, Oracle genera l'error ORA-04091:
El motiu és que un trigger FOR EACH ROW, tant BEFORE com AFTER, no pot llegir la mateixa
taula que està canviant, ja que les dades encara estan a mig modificar. Per això, es diu que
la taula és «mutant».
La solució habitual és separar la captura de canvis (per fila) i la validació (per sentència):
- Un trigger per fila acumula les files modificades en una taula temporal o en un paquet PL/SQL.
- Un trigger per sentència, que s'executa quan la modificació ja ha acabat, fa la validació a partir de les files acumulades.
Resum¶
Un trigger és una ferramenta potent, però s'ha d'utilitzar amb moderació. És adequat quan una regla senzilla s'ha de complir sempre o quan cal una auditoria o una automatització transparent (vegeu Regles adequades per a triggers). En canvi, quan la lògica és complexa, afecta el rendiment o és millor que l'execució siga visible i explícita, és preferible un procediment.
Si tot és automàtic, després és difícil d'entendre.