Ce face CREATE TRIGGER
Un trigger are două părți: o funcție care returnează tipul special trigger și comanda CREATE TRIGGER, care spune când rulează funcția. În funcție, NEW este rândul nou (la INSERT/UPDATE), OLD rândul vechi (la UPDATE/DELETE), iar TG_OP numele operației.
Un trigger BEFORE ... FOR EACH ROW poate modifica rândul înainte de salvare (returnează NEW modificat) sau poate anula operația pentru acel rând (returnează NULL). Un trigger AFTER vede rândul deja salvat și se folosește pentru efecte secundare: jurnal, actualizarea altor tabele.
WHEN (...) limitează când rulează triggerul, de exemplu doar dacă prețul s-a schimbat: WHEN (OLD.pret IS DISTINCT FROM NEW.pret).
Parametri
| Parametru | Descriere |
|---|---|
BEFORE / AFTER / INSTEAD OF |
Înainte sau după operație; INSTEAD OF doar pentru view-uri. |
FOR EACH ROW / STATEMENT |
O dată pentru fiecare rând sau o dată pentru toată comanda (implicit STATEMENT). |
WHEN (condiție) |
Rulează funcția doar dacă este adevărată condiția. |
EXECUTE FUNCTION |
Funcția care rulează; înainte de PostgreSQL 11 se scria EXECUTE PROCEDURE. |
Ce returnează
Mesajul CREATE TRIGGER.
Exemple
Exemplul 1: Coloana actualizat_la completată automat
CREATE FUNCTION seteaza_actualizat_la() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
NEW.actualizat_la := now();
RETURN NEW;
END
$$;
CREATE TRIGGER produse_actualizat_la
BEFORE UPDATE ON produse
FOR EACH ROW
EXECUTE FUNCTION seteaza_actualizat_la();
UPDATE produse SET pret = 6.20 WHERE cod = 'PAINE-01';
Rezultat în psql
CREATE FUNCTION
CREATE TRIGGER
UPDATE 1
Exemplul 2: Jurnal al modificărilor de preț
CREATE TABLE istoric_preturi (
cod text,
operatie text,
pret_vechi numeric(10, 2),
pret_nou numeric(10, 2),
modificat timestamptz DEFAULT now()
);
CREATE FUNCTION jurnal_pret() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
INSERT INTO istoric_preturi (cod, operatie, pret_vechi, pret_nou)
VALUES (NEW.cod, TG_OP, OLD.pret, NEW.pret);
RETURN NULL;
END
$$;
CREATE TRIGGER produse_jurnal_pret
AFTER UPDATE OF pret ON produse
FOR EACH ROW
WHEN (OLD.pret IS DISTINCT FROM NEW.pret)
EXECUTE FUNCTION jurnal_pret();
UPDATE produse SET pret = 6.50 WHERE cod = 'PAINE-01';
UPDATE produse SET stoc = 40 WHERE cod = 'PAINE-01';
SELECT cod, operatie, pret_vechi, pret_nou FROM istoric_preturi;
Rezultat în psql
CREATE TABLE
CREATE FUNCTION
CREATE TRIGGER
UPDATE 1
UPDATE 1
cod | operatie | pret_vechi | pret_nou
----------+----------+------------+----------
PAINE-01 | UPDATE | 6.20 | 6.50
(1 row)
Exemplul 3: Blocarea unei operații cu o eroare
CREATE FUNCTION interzice_stoc_negativ() RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
IF NEW.stoc < 0 THEN
RAISE EXCEPTION 'Stocul pentru % nu poate fi negativ', NEW.cod;
END IF;
RETURN NEW;
END
$$;
CREATE TRIGGER produse_stoc
BEFORE INSERT OR UPDATE ON produse
FOR EACH ROW EXECUTE FUNCTION interzice_stoc_negativ();
UPDATE produse SET stoc = stoc - 100 WHERE cod = 'LAPTE-01';
Rezultat în psql
CREATE FUNCTION
CREATE TRIGGER
ERROR: Stocul pentru LAPTE-01 nu poate fi negativ
CONTEXT: PL/pgSQL function interzice_stoc_negativ() line 4 at RAISE
Greșeli frecvente
- Uiți
RETURN NEWîntr-un triggerBEFORE ... FOR EACH ROWși returneziNULL: rândul nu mai este salvat, fără nicio eroare. - Un trigger
AFTER UPDATEmodifică același tabel cuUPDATEși declanșează din nou triggerul, la nesfârșit. FoloseșteBEFOREcuNEW.coloana := ...sau o condițieWHEN. - Pui logică de business complicată în triggere: devine greu de urmărit de ce se schimbă datele. Păstrează triggerele scurte și documentate.
Comenzi înrudite
CREATE FUNCTION (LANGUAGE plpgsql): Creează o funcție în PL/pgSQL, limbajul procedural al PostgreSQL: variabile, IF, bucle, tratarea erorilor.RAISE și EXCEPTION (PL/pgSQL): RAISE afișează mesaje sau oprește codul cu o eroare; blocul EXCEPTION prinde erorile și le tratează.