CodeGym /Kurse /SQL SELF /Trigger-Typen in PostgreSQL: BEFORE, AFTER, INSTEAD OF

Trigger-Typen in PostgreSQL: BEFORE, AFTER, INSTEAD OF

SQL SELF
Level 57 , Lektion 1
Verfügbar

Trigger in PostgreSQL werden in drei Hauptkategorien unterteilt:

  1. BEFORE — werden vor der eigentlichen Operation ausgeführt (zum Beispiel vor INSERT, UPDATE oder DELETE). Du kannst sie nutzen, um die Ausführung der Operation zu verhindern oder die Daten vor dem Speichern zu ändern.

  2. AFTER — werden ausgeführt, nachdem die Hauptoperation abgeschlossen ist. Dieser Typ wird oft für Logging, das Erstellen von verbundenen Einträgen oder für Aktionen verwendet, die vom erfolgreichen Abschluss der Operation abhängen.

  3. INSTEAD OF — werden anstelle der eigentlichen Operation ausgeführt. Sie werden nur für Views verwendet. Zum Beispiel, wenn ein User versucht, Daten in eine View einzufügen, kannst du diesen Prozess mit einem INSTEAD OF-Trigger steuern.

Trigger BEFORE

BEFORE-Trigger werden ausgelöst, bevor PostgreSQL die Hauptoperation ausführt. Sie sind praktisch, wenn du Daten direkt vor dem Speichern prüfen oder ändern willst. Stell dir das wie eine Gepäckkontrolle vor dem Boarding vor: Wenn das Gepäck nicht passt, kann man es ändern oder komplett blockieren.

Hier ein Beispiel für eine Datenvalidierung vor dem Insert. Angenommen, wir haben eine Tabelle students, in der wir Infos über Studierende speichern. Wir wollen sicherstellen, dass das Alter eines Studenten nicht über 100 Jahre liegt (ziemlich unwahrscheinlich, klar).

Wir erstellen die Tabelle:

CREATE TABLE students (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    age INT NOT NULL
);

Wir erstellen die Funktion für den Trigger:

CREATE OR REPLACE FUNCTION validate_age()
RETURNS TRIGGER AS $$
BEGIN
    IF NEW.age > 100 THEN
        RAISE EXCEPTION 'Das Alter des Studenten darf nicht größer als 100 Jahre sein!';
    END IF;
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Wir erstellen den Trigger:

CREATE TRIGGER before_insert_students
BEFORE INSERT ON students
FOR EACH ROW
EXECUTE FUNCTION validate_age();

Jetzt, wenn du versuchst, einen Studenten mit mehr als 100 Jahren einzufügen, gibt PostgreSQL einen Fehler aus:

INSERT INTO students (name, age) VALUES ('John Doe', 120);
-- Fehler: Das Alter des Studenten darf nicht größer als 100 Jahre sein!

So sieht die Prüfung aus!

Trigger AFTER

AFTER-Trigger werden ausgelöst, nachdem die Hauptoperation erfolgreich abgeschlossen wurde. Sie sind nützlich für Aktionen, die vom Ergebnis der Operation abhängen. Zum Beispiel Logging oder das Erstellen von verbundenen Einträgen.

Szenario: Wir haben eine Tabelle students und wollen alle Änderungen in einer separaten Log-Tabelle speichern.

Wir erstellen die Log-Tabelle:

CREATE TABLE students_log (
    id SERIAL PRIMARY KEY,
    student_id INT,
    operation TEXT,
    timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Wir erstellen die Funktion für den Trigger:

CREATE OR REPLACE FUNCTION log_student_changes()
RETURNS TRIGGER AS $$
BEGIN
    INSERT INTO students_log (student_id, operation)
    VALUES (NEW.id, TG_OP);  -- TG_OP enthält den Operationstyp: INSERT, UPDATE oder DELETE
    RETURN NEW;
END;
$$ LANGUAGE plpgsql;

Wir erstellen den Trigger:

CREATE TRIGGER after_insert_students
AFTER INSERT ON students
FOR EACH ROW
EXECUTE FUNCTION log_student_changes();

Jetzt, wenn du einen neuen Studenten hinzufügst, schreibt PostgreSQL die Operation automatisch ins Log:

INSERT INTO students (name, age) VALUES ('Anna Ling', 22);

SELECT * FROM students_log;
-- Ergebnis:
-- id | student_id | operation |        timestamp
--  1 |          1 | INSERT    | 2023-11-15 12:00:00

Trigger INSTEAD OF

INSTEAD OF-Trigger werden anstelle der eigentlichen Operation ausgeführt. Das ist der einzige Trigger-Typ, den du mit Views verwenden kannst. Sie geben dir Flexibilität bei Operationen, die man nicht direkt auf einer View ausführen kann.

Szenario: Wir haben zwei Tabellen courses und teachers. Wir erstellen eine View, die beide verbindet, und schreiben einen Trigger, um Inserts über diese View zu verarbeiten.

Wir erstellen die Tabellen:

CREATE TABLE courses (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL,
    teacher_id INT NOT NULL
);

CREATE TABLE teachers (
    id SERIAL PRIMARY KEY,
    name TEXT NOT NULL
);

Wir erstellen die View:

CREATE VIEW course_details AS
SELECT 
    courses.id AS course_id,
    courses.name AS course_name,
    teachers.name AS teacher_name
FROM courses
JOIN teachers ON courses.teacher_id = teachers.id;

Das Problem: Wir können nicht einfach Daten in die View einfügen, weil sie Daten aus zwei Tabellen aggregiert. Die Lösung: Wir nutzen einen INSTEAD OF-Trigger.

Wir erstellen die Funktion für den Trigger:

CREATE OR REPLACE FUNCTION insert_course_details()
RETURNS TRIGGER AS $$
BEGIN
    INSERT INTO teachers (name) VALUES (NEW.teacher_name) RETURNING id INTO NEW.teacher_id;
    INSERT INTO courses (name, teacher_id) VALUES (NEW.course_name, NEW.teacher_id);
    RETURN NULL;  -- In der View werden keine Daten gespeichert
END;
$$ LANGUAGE plpgsql;

Wir erstellen den Trigger:

CREATE TRIGGER instead_of_insert_course_details
INSTEAD OF INSERT ON course_details
FOR EACH ROW
EXECUTE FUNCTION insert_course_details();

Jetzt kannst du direkt Daten in die View einfügen:

INSERT INTO course_details (course_name, teacher_name)
VALUES ('Mathematik', 'Alex Ming');

SELECT * FROM courses;
-- Ergebnis:
-- id | name        | teacher_id
--  1 | Mathematik  | 1

SELECT * FROM teachers;
-- Ergebnis:
-- id | name
--  1 | Alex Ming

Vergleich der Trigger-Typen

Trigger-Typ Wann wird er ausgeführt Hauptanwendung
BEFORE Vor der Operation Validierung, Datenvorbereitung
AFTER Nach erfolgreichem Abschluss Logging, Aktualisierung von verbundenen Daten
INSTEAD OF Anstelle der Operation Verarbeitung von Operationen auf Views

Besonderheiten und Einschränkungen

BEFORE-Trigger können Daten vor der Operation ändern. Zum Beispiel kannst du automatisch Namen formatieren (z.B. alles groß schreiben).

AFTER-Trigger können die Daten nicht mehr beeinflussen, weil die Operation schon abgeschlossen ist. Sie sind nur für nachfolgende Aktionen gedacht.

INSTEAD OF-Trigger werden nur für Views verwendet. Sie erlauben dir, komplexe Logik für Insert/Update in mehreren verbundenen Tabellen umzusetzen.

Das war's für heute! Wenn dir BEFORE, AFTER und INSTEAD OF noch kompliziert vorkommen, keine Sorge. Wichtig ist, dass du das Grundprinzip und die Anwendungsfälle im Kopf behältst. Probier ein paar Beispiele selbst aus, um das Thema zu festigen.

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