10. Integrität und Trigger#

In diesem Kapitel beschäftigen wir uns mit Integritätsbedingungen und Triggern.

10.1. Motivation – Aktive Datenbanken#

Die Daten, die wir in eine Datenbank einfügen wollen können fehlerhaft sein, es kann sich um typographische Fehler, logische Fehler oder auch Andere handeln. Um den Fehlern entgegenzuwirken wäre eine Möglichkeit , das Schreiben besserer Anwendungen, jedoch ist das Prüfen der Konsistenz und Korrektheit sehr schwer, da z.B komplexe Bedingungen, schon abhängig von vorhandenen Daten sein können. Eine andere Möglichkeit ist das Benutzen von aktiven Elementen im DBMS wie Integritätsbedingungen(integrity constraints, ICs), die einmal spezifiziert werden und wenn nötig dann ausgeführt werden. Integritätsbedingungen “bewachen”, dass nur Daten die der spezifizierten Form entsprechen, zugelassen werden.

10.2. Schlüssel und Fremdschlüssel#

10.2.1. Schlüssel#

Die einfachtse und am häufigsten genutzte Bedingung sind Schlüssel. Schlüssel sollten aus den vorherigen Kapiteln bekannt sein, sie bilden sich auch ein oder mehreren Attributen und identifizieren eindeutig ein Tupel. Falls eine Schlüsselmenge S gegeben ist, müssen sich also zwei Tupel einer Relation in mindestens einem Attributwert der Schlüsselmenge unterscheiden.

Schlüssel werden im CREATE TABLE Ausdruck spezifiziert. Der Primärschlüssel wird mit dem Schlüsselwort PRIMARY KEY gekennzeichnet und kann nie einen Nullwert enthalten. Es gibt pro Relation maximal einen PRIMARY KEY. Ein weiterer Schlüssel ist UNIQUE, hiervon ist es erlaubt mehrere pro Relation und auch Nullwerte zu haben. Falls UNIQUE ohne Nullwerte benutzt werden soll, ist dies mit UNIQUE NOT NULL möglich.

10.2.1.1. Primärschlüssel#

Primaärschlüssel werden im CREATE TABLE Ausdruck spezifiziert. Im Folgenden finden Sie eine Deklaration eines Primärschlüssels bei genau einem Attribut, dort findet die Deklaration dirket in der Attributenliste statt. Es ist auch möglich bei nur einem Attribut die Deklaration nach den Attributen zu nennen.

CREATE TABLE SchauspielerIn(
Name CHAR(30) PRIMARY KEY,
Adresse VARCHAR(255),
Geschlecht CHAR(1),
Geburtstag DATE);

Bei mehreren Attributen findet die Deklaration zwingend nach den Attributen statt, wie im Beispiel unten gezeigt.

CREATE TABLE SchauspielerIn(
Name CHAR(30),
Adresse VARCHAR(255),
Geschlecht CHAR(1),
Geburtstag DATE,
PRIMARY KEY (Name, Adresse) );

10.2.1.2. Sekundärschlüssel#

Sekundärschlüssel bzw. Schlüsselkandidaten werden mit dem Schlüsseltwort UNIQUE spezifiziert. Die Sytax ist genau wie bei der Deklaration von einem PRIMARY KEY, also direkt beim Attribut oder als separate Attributliste nach den Attributen.

Der große Unterschied zu PRIMARY KEY ist, dass es mehrere UNIQUE Deklarationen geben darf. Standardmäßig erlaubt UNIQUE NULL-Werte, da von NULL ≠ NULL (bzw. UNKNOWN) ausgegangen wird. Bei NULL ist es also möglich, dass zwei Tupel in UNIQUE Attributen übereinstimmen. Um auch Nullwerte zu unterbinden, kann UNIQUE NOT NULL verwendet werden. Ein Beispiel für eine Deklaration eines Sekundärschlüssel befindet sich unten.

CREATE TABLE SchauspielerIn(
Name CHAR(30),
Adresse VARCHAR(255),
Geschlecht CHAR(1),
Geburtstag DATE UNIQUE,
UNIQUE (Name, Adresse));

10.2.1.3. Schlüsselbedingungen erzwingen#

Die spezifizierten Schlüsselbedingungen müssen stets gelten. Diese sind nur relevant bei INSERT und UPDATE, da bei DELETE keine Verletzung der Bedingungen passieren kann, denn es wurden keine Tupel der Relation hinzugefügt, die nicht den Bedingungen entsprechen. Beim Einfügen oder Ändern wird geprüft der neue Schlüsselwert bereits vorhanden ist.

Meistens ist die effiziente Prüfung der Bedingungen mittels Index möglich, da DBMS in der Regel automatisch Indizes für Primärschlüsselattribute anlegen. Optional ist es auch möglich manuell für UNIQUE-Attribute Indizes zu erstellen, z.B CREATE UNIQUE INDEX JahrIndex ON Filme(Jahr). Das entspricht CREATE INDEX JahrIndex ON Filme(Jahr), aber mit einer neuen UNIQUE Bedingung auf Jahr.

Ohne Indizes ist die Überprüfung eher ineffizient, da die gesamte Spalte durchsucht werden muss. Sind die Dtaen sortiert, kann binäre Suche verwendet werden, andernfalls muss sequentielle Suche benutzt werden.

10.2.1.4. Fremdschlüssel#

Werte in bestimmten Attributen sollen „sinnvoll“ sein.
ManagerIn(Name, Adresse, ManagerinID, Gehalt)
Studios(Name, Adresse, VorsitzendeID)
Z.B.: Der Attributwert für VorsitzendeID sollte auf einen bestimmten, vorhandenen Manager verweisen.
Referentielle Integrität – dangling tuples
Ein Attribut oder eine Attributmenge kann als FOREIGN KEY deklariert werden, die eine entsprechende Attributmenge einer zweiten Relation referenziert.
Die referenzierte Attributmenge muss UNIQUE oder PRIMARY KEY sein.
Gemeinsame Werte der Fremdschlüsselattribute müssen als gemeinsame Werte des referenzierten Schlüssels auftauchen.
Ausnahme: Ein Fremdschlüssel darf den Wert NULL annehmen.
Das Schlüsselattribut muss nicht einen NULL-Wert besitzen (und darf es meist auch nicht).
Abhilfe: NOT NULL

Syntax
Auf einem Attribut:
REFERENCES Relation(Attribut)
Auf (einem oder) mehreren Attributen:
FOREIGN KEY (Attribute) REFERENCES Relation(Attribute) ManagerIn(Name, Adresse, ManagerinID, Gehalt) Studios(Name, Adresse, VorsitzendeID)

CREATE TABLE Studios(
    Name CHAR(30) PRIMARY KEY,
    Adresse VARCHAR(255),
    VorsitzendeID INT REFERENCES Manager(ManagerinID));
    
CREATE TABLE Studios(
    Name CHAR(30) PRIMARY KEY,
    Adresse VARCHAR(255),
    VorsitzendeID INT,
    FOREIGN KEY (VorsitzendeID) REFERENCES
ManagerIn(ManagerinID));

10.2.2. CREATE TABLE – Beispiel#

CREATE TABLE Employee(
    FirstName CHAR(30),
    LastName CHAR(30),
    City VARCHAR(255) NOT NULL,
    ZIP INT,
    Street VARCHAR(255),
    ProjectName VARCHAR(50),
    ProjectYear INT,
    DepID INT NOT NULL,
    PRIMARY KEY (FirstName,LastName),
    FOREIGN KEY (DepID) REFERENCES Department(DepID),
    FOREIGN KEY (ProjectName,ProjectYear)
        REFERENCES Project(Name, Year) );

10.2.3. Referentielle Integrität erzwingen#

Drei Varianten
Verletzende Änderungen ablehnen (SQL default)
Kaskadierung
Null-Werte

Beispiel Manager(Name, Adresse, ManagerID, Gehalt)
Studios(Name, Adresse, VorsitzenderID)

CREATE TABLE Studios(
Name CHAR(30) PRIMARY KEY,
Adresse VARCHAR(255),
VorsitzendeID INT REFERENCES ManagerIn(ManagerinID));

10.2.3.1. Referentielle Integrität erzwingen: Änderungen Ablehnen#

Default: Änderungen ablehnen

Für jede VorsitzendeID muss es auch einen ManagerinID geben.
INSERT Studio mit neuer (nicht-NULL) VorsitzendeID, die nicht in Manager gespeichert ist
Abgelehnt

UPDATE eines Studios mit einer neuen VorsitzendeID, die nicht in Manager gespeichert ist
Abgelehnt

DELETE eines ManagerIn-Tupels, dessen ManagerinID auch eine (oder mehr) VorsitzendeID ist
Abgelehnt

UPDATE der ManagerinID eines Manager-Tupels, die auch eine (oder mehr) VorsitzendeID ist
Abgelehnt

10.2.3.2. Referentielle Integrität erzwingen: Kaskadierung#

Idee: Änderungen im Schlüssel werden im Fremdschlüssel nachgezogen.

INSERT Studio mit neuer (nicht-NULL) VorsitzendeID, die nicht in Manager gespeichert ist
Abgelehnt

UPDATE eines Studios mit einer neuen VorsitzendeID, die nicht in Manager gespeichert ist
Abgelehnt

DELETE eines Manager-Tupels, dessen ManagerinID auch eine (oder mehr) VorsitzendeID ist
OK, aber alle abhängigen Studios werden ebenfalls gelöscht.

UPDATE der ManagerinID eines Manager-Tupels, die auch eine (oder mehr) VorsitzendeID ist
OK, die VorsitzendeIDs in Studios werden ebenfalls geändert

10.2.3.3. Referentielle Integrität erzwingen: Auf NULL setzen#

Idee: Bei Änderungen im Schlüssel wird der Wert des Fremdschlüssels auf NULL gesetzt.

INSERT Studio mit neuer (nicht-NULL) VorsitzendeID, die nicht in Manager gespeichert ist
Abgelehnt

UPDATE eines Studios mit einer neuen VorsitzendeID, die nicht in Manager gespeichert ist
Abgelehnt

DELETE eines Manager-Tupels, dessen ManagerinID auch eine (oder mehr) VorsitzendeID ist
OK, aber VorsitzendeID aller abhängigen Studios werden auf NULL gesetzt.

UPDATE der ManageID eines ManagerIn-Tupels, die auch eine (oder mehr) VorsitzendeID ist
OK, aber die VorsitzendeIDs in Studios werden auf NULL gesetzt.

10.2.3.4. Referentielle Integrität erzwingen#

SQL Syntax
Vorgehensweise kann individuell spezifiziert werden

CREATE TABLE Studios(
Name CHAR(30) PRIMARY KEY,
Adresse VARCHAR(255),
VorsitzendeID INT REFERENCES ManagerIn(ManagerinID)
ON DELETE SET NULL
ON UPDATE CASCADE
);

„Vorsichtige“ Strategie
Studios werden nicht gelöscht
Studios behalten falls möglich ihren Vorsitzenden.

10.2.4. Integritätschecks verschieben#

Es ist nicht immer möglich, Tupel einzufügen, die der referentiellen Integrität gehorchen.

INSERT INTO Studios
VALUES (‘Redlight‘, ‘New York‘, 23456);

Problem: ManagerIn 23456 wurde (noch) nicht angelegt

INSERT INTO Studios(Name, Adresse)
VALUES (‘Redlight‘, ‘New York‘);

OK, da NULL-Werte nicht auf referentielle Integrität geprüft werden müssen.
Später dann (nach Einfügen des Managertupels):

UPDATE Studios SET VorsitzendeID = 23456
WHERE Name = ‘Redlight‘;

Bessere Lösung: Erst den Manager, dann das Studio einfügen.

Es kann zyklische referentielle Integritätsbedingungen geben.
Manager sind nur Vorsitzende von Studios
ManagerinID ist Fremdschlüssel und referenziert VorsitzendeID.
Es kann nach wie vor kein Studio ohne vorhandenes Managertupel eingefügt werden.
Es kann nun auch kein Manager ohne vorhandenes Studio eingefügt werden.
Catch 22!
Lösung
Mehrere Änderungsoperationen zu einer „Transaktion“ zusammenfassen (mehr später: „Transaktionsmanagement“)
Integritätschecks bis ans Ende der Transaktion verschieben

■ Jeder Constraint kann als DEFERRABLE oder NOT DEFERRABLE deklariert werden.

■ NOT DEFERRABLE ist default
□ Bei jeder Änderung der Datenbank wird die Bedingung geprüft.

■ DEFERRABLE
□ INITIALLY DEFERRED:
– Verschieben ans Ende der Transaktion
– oder bis wir Verschiebung aufheben
□ INITIALLY IMMEDIATE
– Zunächst nichts verschieben, bis wir Verschiebung verlangen.

CREATE TABLE Studios(
Name CHAR(30) PRIMARY KEY,
Adresse VARCHAR(255),
VorsitzendeID INT UNIQUE REFERENCES ManagerIn(ManagerinID)
DEFERRABLE INITIALLY DEFERRED
);

10.3. Bedingungen auf Attributen und Tupel#

10.3.1. Weitere Arten der Nebenbedingungen#

■ Verbieten Annahme bestimmter Werte

■ Bedingungen auf einzelnen Attributen
□ NOT NULL
□ CHECK

■ Bedingungen für ganze Tupel, also auf das Schema
□ CHECK

10.3.2. NOT NULL#

CREATE TABLE Studios(
Name CHAR(30) PRIMARY KEY,
Adresse VARCHAR(255) NOT NULL,
VorsitzendeID INT NOT NULL
REFERENCES ManagerIn(ManagerinID)
ON UPDATE CASCADE
);

■ Einfügen eines Studios ohne Manager ist nicht mehr möglich.

■ Jedes Studio muss eine Adresse haben.

■ Die Null-Werte Strategie beim Löschen von Managern ist nicht mehr möglich.

10.3.3. Attribut-basierte CHECK Bedingungen#

Verfeinerung der erlaubten Werte für ein Attribut durch Spezifikation einer Bedingung.

Bedingung beliebig komplex
Wie WHERE Klausel
Oder sogar als SELECT…FROM…WHERE… Anfrage

i.d.R. aber eine einfache Einschränkung der Werte

CHECK wird geprüft falls ein Attribut einen neuen Wert erhält
INSERT
UPDATE

Falls FALSE, scheitert die Änderung

CREATE TABLE Studios(
Name CHAR(30) PRIMARY KEY,
Adresse VARCHAR(255) NOT NULL,
VorsitzendeID INT REFERENCES ManagerIn(ManagerinID)
CHECK (VorsitzendeID >= 100000)
);

CREATE TABLE SchauspielerIn (
Name CHAR(30),
Adresse VARCHAR(255),
Geschlecht CHAR(1) CHECK (Geschlecht IN (‘W‘, ‘M‘, ‘D‘)),
Geburtstag DATE );

CHECK Bedingung darf sich auch auf andere Attribute beziehen.
Nur im Zusammenhang mit einer SQL Anfrage

CREATE TABLE Studios(
Name CHAR(30) PRIMARY KEY,
Adresse VARCHAR(255) NOT NULL,
VorsitzendeID INT CHECK (
VorsitzendeID IN
(SELECT ManagerinID FROM ManagerIn))
);

Simuliert referentielle Integrität
Was kann schief gehen?
UPDATE und INSERT auf der Studios Relation
CHECK wird geprüft
DELETE auf der Manager Relation
CHECK wird nicht geprüft; CHECK Bedingung wird ungültig
D.h.: Andere Relationen kennen diese CHECK Bedingung nicht.

10.3.4. Tupel-basierte CHECK Bedingungen#

Bedingungen können auch für ganze Tupel deklariert werden.
Wie Primär- und Fremdschlüsselbedingungen kann auch einen CHECK Bedingung in der Liste der Attribute auftauchen.
Ebenso wie bei Attribut-basierten CHECKs: Beliebige Bedingungen wie eine WHERE Klausel.
Wird geprüft bei jedem INSERT und jedem UPDATE eines Tupels.

CREATE TABLE SchauspielerIn (
Anrede CHAR(10),
Name CHAR(30) PRIMARY KEY,
Adresse VARCHAR(255),
Geschlecht CHAR(1) CHECK (Geschlecht IN (‘W‘, ‘M‘, ‘D‘)),
Geburtstag DATE,
CHECK (Geschlecht = ‚W‘ OR Anrede NOT LIKE ‚Fr%‘ ));

Typischer Aufbau einer Bedingung wenn wir mehrere Eigenschaften gemeinsam verbieten wollen (Männlich und Name beginnt mit „Frau…“)

Wird nicht geprüft falls eine andere (oder sogar die gleiche) Relation in einer Subanfrage der CHECK Bedingung erwähnt wird und diese eine Änderung erfährt.
D.h.: Andere Relationen kennen diese CHECK Bedingung nicht.
Solche Probleme gibt es bei ASSERTIONS (siehe unten) nicht. Deshalb komplexe Bedingungen lieber als ASSERTION deklarieren,
oder (realistischer) in die Anwendungslogik stecken.

10.3.5. Bedingungen ändern#

Zur Änderung von Bedingungen müssen Namen vergeben werden.

CREATE TABLE SchauspielerIn (
Anrede CHAR(19),
Name CHAR(30) CONSTRAINT NamePrimaer PRIMARY KEY,
Adresse VARCHAR(255),
Geschlecht CHAR(1) CONSTRAINT NichtGeschlechtslos
CHECK (Geschlecht IN (‚W‘, ‚M‘)),
Geburtstag DATE,
CONSTRAINT AnredeKorrektConstraint
CHECK (Geschlecht = ‚W‘ OR Anrede NOT LIKE ‚Frau%‘ );

Meist vergeben DBMS sowieso interne (aber hässliche) Namen.

SET CONSTRAINT MyConstraint DEFERRED;

SET CONSTRAINT MyConstraint IMMEDIATE;

■ Entfernen

ALTER TABLE Schauspieler DROP CONSTRAINT NamePrimaer;
ALTER TABLE Schauspieler DROP CONSTRAINT NichtGeschlechtslos;
ALTER TABLE Schauspieler DROP CONSTRAINT AnredeKorrekt;

■ Hinzufügen

ALTER TABLE Schauspieler ADD CONSTRAINT NamePrimaer PRIMARY KEY (Name);
ALTER TABLE Schauspieler ADD CONSTRAINT NichtGeschlechtslos CHECK (Geschlecht IN (‚W‘, ‚M‘));
ALTER TABLE Schauspieler ADD CONSTRAINT AnredeKorrekt CHECK (Geschlecht = ‚W‘ OR name NOT LIKE ‚Frau%‘ );

□ Diese Bedingungen sind nun alle Tupel-basiert.
□ Attribut-basierte Bedingungen können nicht nachträglich eingefügt werden.

10.4. Zusicherungen und Trigger#

10.4.1. Motivation#

Manche Bedingungen sollen sich nicht auf bestimmte Tupel beziehen, sondern auf Schemaebene definiert werden (wie Relationen und Sichten).

Assertion (Zusicherungen)
Boole‘scher SQL Ausdruck, der stets wahr sein muss
Einfache Handhabung für Admin
Schwierig, effizient zu implementieren

Trigger („Auslöser“)
Aktionen, die bei bestimmten Ereignissen (INSERTs, …) ausgelöst werden
Leichter, effizient zu implementieren

10.4.2. Assertions#

CREATE ASSERTION Name CHECK (Bedingung)

Bedingung muss bei Erzeugung der Assertion bereits gelten.
Bedingung muss stets gelten; Änderungen, die die Assertion falsch machen, werden abgewiesen.
CHECK Bedingung können hingegen falsch werden!

Zur Formulierung
Kein direkter Bezug zu Relationen, deshalb müssen Attribute und Relationen in einer SQL Anfrage eingeführt werden.

Löschen
DROP ASSERTION Name;

10.4.2.1. Assertions – Beispiel#

■ ManagerIn(Name, Adresse, ManagerinID, Gehalt) Studios(Name, Adresse, VorsitzendeID)
■ Vorsitzende von Studios müssen mindestens 1.000.000 verdienen.

CREATE ASSERTION ReicheVorsitzende CHECK
(NOT EXISTS
(SELECT *
FROM Studios, ManagerIn
WHERE ManagerinID = VorsitzendeID
AND Gehalt < 1000000)
);

■ Alternative:

CREATE TABLE Studios(
Name CHAR(30) PRIMARY KEY,
Adresse VARCHAR(255) NOT NULL,
VorsitzendeID INT REFERENCES ManagerIn(ManagerinID),
CHECK ( VorsitzendeID NOT IN
(SELECT ManagerinID FROM ManagerIn
WHERE Gehalt < 1000000))
);

■ Was ist der Unterschied?
□ Änderungen der ManagerIn Relation (Gehalt sinkt) werden nicht erkannt.

■ Filme(Titel, Jahr, Länge, inFarbe, StudioName, ProduzentID)

CREATE ASSERTION NurGrosseStudios CHECK
(10000 <= ALL
(SELECT SUM(Länge) FROM Filme
GROUP BY StudioName)
);

□ Ein Studio muss mindestens 10,000 Minuten Filmmaterial haben

■ Alternative beim Schema für Filme

□ CHECK (10000 <= ALL
(SELECT SUM(Länge) FROM Filme
GROUP BY StudioName)

■ Unterschied?
□ Beim Löschen eines Films wird die Bedingung nicht geprüft.
□ Beim Studiowechsel eines Films wird die Bedingung nicht geprüft.

10.4.3. Unterschiede der CHECK Bedingungen#

Constraint-Art

Wo spezifiziert?

Wann geprüft?

Gilt immer?

Attribut-basiertes

CHECK Beim Attribut

Bei INSERT in Relation oder UPDATE des Attributs

Nein, falls Subanfragen verwendet werden.

Tupel-basiertes CHECK

Teil des Relationenschemas

Bei INSERT oder UPDATE eines Tupels

Nein, falls Subanfragen verwendet werden.

Assertion

Teil des Datenbankschemas

Beliebige Änderung auf einer erwähnten Relation

Ja

10.4.4. Trigger#

■ Auch: Event-Condition-Action Rules (ECA-Rules)

■ Unterschiede zu Zusicherungen
□ Gelten nicht immer, sondern werden bei bestimmten Ereignissen (INSERT, UPDATE, DELETE, Ende einer Transaktion) ausgeführt.
□ Ein Ereignis wird zunächst nicht verhindert, es wird lediglich ein bestimmte Bedingung geprüft.
– Falls falsch, passiert nichts weiter
□ Falls wahr, wird eine Aktion ausgeführt. Die Aktion könnte das Ereignis verhindern oder rückgängig machen.
Oder auch etwas völlig anderes tun.

10.4.5. Trigger in SQL#

Eigenschaften/Fähigkeiten
Ausführung der Aktion vor oder nach dem Ereignis
Die Aktion kann sich auf alte und/oder neue Werte von Tupeln beziehen, die beim Ereignis eingefügt, verändert oder gelöscht werden.
Mit WHEN können neben dem Ereignis auch weitere Bedingungen angegeben werden, die gelten müssen um die Aktion durchzuführen.
Aktion wird durchgeführt
Einmal für jedes veränderte Tupel oder
einmalig für alle Tupel, die verändert wurden

10.4.5.1. Trigger – Beispiel#

CREATE TRIGGER GehaltsTrigger --Name des Triggers
AFTER UPDATE OF Gehalt ON ManagerIn --Ereignis
REFERENCING
    OLD ROW AS AltesTupel,
    NEW ROW AS NeuesTupel
FOR EACH ROW --Für jedes veränderte Tupel einmal durchführen
WHEN (AltesTupel.Gehalt > NeuesTupel.Gehalt) --Bedingung (condition)
    UPDATE ManagerIn --Aktion
    SET Gehalt = AltesTupel.Gehalt
    WHERE ManagerinID = NeuesTupel.ManagerinID; --Nur betroffenes Tupel

■ Was bewirkt der Trigger?
□ Managergehälter werden nicht gesenkt!
□ Rekursionsverhalten ist DBMS-Hersteller-spezifisch.

10.4.5.2. Trigger – Alternative#

CREATE TRIGGER GehaltsTrigger                   --BEFORE
AFTER UPDATE OF Gehalt ON ManagerIn             --INSERT / DELETE (ohne OF…)
REFERENCING
    OLD ROW AS AltesTupel,                      --Bei INSERT nicht erlaubt
    NEW ROW AS NeuesTupel                       --Bei DELETE nicht erlaubt
FOR EACH ROW                                    --Default: FOR EACH STATEMENT Dann: OLD TABLE / NEW TABLE
WHEN (AltesTupel.Gehalt > NeuesTupel.Gehalt)    --WHEN ist optional
    UPDATE ManagerIn                            --Auch mehrere SQL Ausdrücke (BEGIN … END)
    SET Gehalt = AltesTupel.Gehalt
    WHERE ManagerinID = NeuesTupel.ManagerinID;

10.4.5.3. Trigger - Beispiel#

CREATE TRIGGER DurchschnittsgehaltTrigger
AFTER UPDATE OF Gehalt ON ManagerIn
REFERENCING
    OLD TABLE AS AlteTupel --Enthält nur die alten bzw. neuen Tupel.
    NEW TABLE AS NeueTupel
FOR EACH STATEMENT  --Ausführung nur einmal, egal wie viele Tupel betroffen.
WHEN (500000 > (SELECT AVG(Gehalt) FROM ManagerIn)) --Wird nach dem UPDATE geprüft.
BEGIN
    DELETE FROM ManagerIn
        WHERE (Name, Adresse, ManagerID, Gehalt) IN NeueTupel; --Es werden nur veränderte Tupel entfernt und durch die alten Tupel ersetzt.
    INSERT INTO ManagerIn
        (SELECT * FROM AlteTupel)
END;

■ Was bewirkt dieser Trigger?
□ Das Durchschnittsgehalt von Managern soll nicht unter 500,000 sinken!
□ Je ein Trigger für UPDATE, INSERT und DELETE nötig

10.5. Zusammenfassung#

■ Schlüssel
□ UNIQUE, PRIMARY KEY, NOT NULL

■ Referentielle Integrität
□ REFERENCES, FOREIGN KEY

■ Attribut-basiertes CHECK

■ Tupel-basiertes CHECK

■ Zusicherungen (Datenbank-basiertes CHECK)
□ ASSERTION

■ Trigger