CodeGym /Kursy /SQL SELF /Podstawy składni triggerów: CREATE TRIGGER, WHEN, EXECUTE...

Podstawy składni triggerów: CREATE TRIGGER, WHEN, EXECUTE FUNCTION

SQL SELF
Poziom 57 , Lekcja 2
Dostępny

Żeby stworzyć trigger w PostgreSQL, musisz określić następujące elementy:

  • Nazwę triggera.
  • Typ zdarzenia (INSERT, UPDATE, DELETE).
  • Moment wykonania (BEFORE albo AFTER).
  • Tabelę, do której się odnosi.
  • Funkcję, która zostanie wykonana (w PL/pgSQL lub innym języku).

Oto ogólna struktura komendy:

CREATE TRIGGER nazwa_triggera
[BEFORE | AFTER] {INSERT | UPDATE | DELETE}
ON nazwa_tabeli
[FOR EACH ROW | FOR EACH STATEMENT]
WHEN (warunek)
EXECUTE FUNCTION nazwa_funkcji();

Przykład prostego triggera

Stwórzmy bazową tabelę students i dodajmy trigger, który odpala się po dodaniu nowego rekordu.

Na początek tworzymy tabelę students

CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    last_modified TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Co tu się dzieje? Stworzyliśmy tabelę z polami id, name i last_modified. Pole last_modified będzie przechowywać datę i godzinę ostatniej modyfikacji rekordu.

Triggery są zawsze powiązane z funkcjami. Najpierw napiszemy prostą funkcję, która będzie aktualizować pole last_modified przy każdym dodaniu rekordu:

CREATE OR REPLACE FUNCTION update_last_modified()
RETURNS TRIGGER AS $$
BEGIN
    -- Ustawiamy aktualną datę i godzinę w polu last_modified
    NEW.last_modified := CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Co to za magia?

  1. NEW — specjalna zmienna, która przechowuje nowe wartości wiersza (dla zdarzeń INSERT lub UPDATE).
  2. CURRENT_TIMESTAMP — funkcja zwracająca aktualną datę i godzinę.
  3. RETURN NEW — zwraca zmodyfikowany wiersz do dalszego zapisania.

Teraz tworzymy sam trigger:

CREATE TRIGGER set_last_modified
AFTER INSERT
ON students
FOR EACH ROW
EXECUTE FUNCTION update_last_modified();

Rozszyfrowanie:

  • AFTER INSERT: trigger odpala się po dodaniu nowego wiersza.
  • ON students: trigger dotyczy tabeli students.
  • FOR EACH ROW: trigger działa dla każdego nowego wiersza.
  • EXECUTE FUNCTION: wskazuje, jaką funkcję wywołać.

Sprawdzanie działania triggera

Sprawdźmy, jak działa nasz trigger:

INSERT INTO students (name) VALUES ('Alice');
SELECT * FROM students;

Zobaczysz mniej więcej taki wynik:

id name last_modified
1 Alice 2023-10-15 14:23:45

Trigger automatycznie zaktualizował pole last_modified. Magia? Nie, po prostu PostgreSQL.

Użycie warunków z WHEN

Czasem chcesz, żeby trigger odpalał się nie zawsze, tylko przy określonych warunkach. Do tego służy słowo kluczowe WHEN.

Zobaczmy przykład, gdzie trigger działa tylko dla określonych wartości.

Załóżmy, że chcemy, żeby trigger odpalał się tylko dla studentów o imieniu "Alice". Zmieniamy nasz trigger:

CREATE OR REPLACE FUNCTION update_last_modified_condition()
RETURNS TRIGGER AS $$
BEGIN
    NEW.last_modified := CURRENT_TIMESTAMP;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER set_last_modified_condition
AFTER INSERT
ON students
FOR EACH ROW
WHEN (NEW.name = 'Alice')
EXECUTE FUNCTION update_last_modified_condition();

Teraz trigger zaktualizuje pole last_modified tylko dla studentów o imieniu "Alice".

Sprawdźmy:

INSERT INTO students (name) VALUES ('Alice');
INSERT INTO students (name) VALUES ('Bob');
SELECT * FROM students;

Wynik:

id name last_modified
1 Alice 2023-10-15 14:30:00
2 Bob (NULL)

Zwróć uwagę: dla studenta "Bob" pole last_modified zostało puste, bo trigger się nie odpalił.

Powiązanie triggera z funkcją: EXECUTE FUNCTION

Funkcja to serce każdego triggera. Trigger nie może istnieć bez funkcji, która określa jego logikę. W PostgreSQL funkcje można pisać w PL/pgSQL lub innych wspieranych językach, jak Python czy C.

Pokażmy przykład użycia funkcji PL/pgSQL.

Stwórzmy funkcję, która loguje zmiany w osobnej tabeli audit_log.

Najpierw tworzymy tabelę audit_log

CREATE TABLE audit_log (
    id SERIAL PRIMARY KEY,
    operation TEXT NOT NULL,
    student_id INTEGER NOT NULL,
    log_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

A teraz – funkcja:

CREATE OR REPLACE FUNCTION log_insert()
RETURNS TRIGGER AS $$
BEGIN
    INSERT INTO audit_log (operation, student_id)
    VALUES ('INSERT', NEW.id);
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Teraz piszemy trigger:

CREATE TRIGGER log_student_insert
AFTER INSERT
ON students
FOR EACH ROW
EXECUTE FUNCTION log_insert();

I sprawdzamy działanie:

INSERT INTO students (name) VALUES ('Charlie');
SELECT * FROM audit_log;

Zobaczysz mniej więcej taki wynik:

id operation student_id log_time
1 INSERT 3 2023-10-15 14:35:00

Trigger automatycznie zapisał log o nowym rekordzie.

Błędy i specyfika pracy z triggerami

Błąd: brak funkcji. Jeśli spróbujesz stworzyć trigger bez funkcji, PostgreSQL wyrzuci błąd. Zawsze najpierw twórz funkcję, potem trigger.

Problemy z wydajnością. Duża liczba triggerów albo skomplikowane funkcje mogą spowolnić bazę danych. Używaj ich z głową.

Rekursja. Jeśli trigger zmienia coś w tej samej tabeli, na której działa, może to wywołać nieskończoną pętlę. Używaj warunków WHEN, żeby tego uniknąć.

Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION