pixel24
Goto Top

Warum benötigen ein CONSTRAINT auf Tabellen-Ebene einen Bezeichner?

Hallo zusammen,

ich lerne gerade SQL und habe eine Frage zu den CONSTRAINT 's. Im Buch (Einstieg in SQL) wurde zunächst der einfache Fall besprochen, CONSTRAINT auf Spalten-Ebene um z.B. den PRIMARY KEY zu definieren:

CREATE TABLE dienstwagen(
dienstwagenid SMALLINT PRIMARY KEY,
kennzeichen CHAR(9) NOT NULL,
erstzulassung DATE NOT NULL,
...
);

Alles verstanden. Im weiteren Verlauf wird dann der CONSTRAINT auf Tabellen-Ebene definiert:

CREATE TABLE dienstwagen(
dienstwagenid SMALLINT,
kennzeichen CHAR(9) NOT NULL,
erstzulassung DATE NOT NULL,
...
CONSTRAINT pk_dienstwagenid PRIMARY KEY (dienstwagenid)
);

Wenn ich das richtig verstehe macht man den CONSTRAINT auf Tabellen-Ebene hauptsächlich dann wenn mehrere Spalten mit einbezogen werden, richtig? Vermutlich auch da das Statement auch übersichtlicher zu lesen ist.

Auf Tabellen-Ebene bekommt der CONSTRAINT immer einen Bezeichner wie in diesem Beispiel "pk_dienstwagenid". Dessen Sinn bzw. Notwendigkeit ist mir nicht so klar. Wie und wo wird der später verwendet bzw. was ist der Sinn davon?

Hoffe die Fragestellung ist halbwegs verständlich.

Beste Grüße
pixel24

Content-ID: 7706146831

Url: https://administrator.de/contentid/7706146831

Ausgedruckt am: 25.11.2024 um 04:11 Uhr

LordGurke
LordGurke 01.07.2023 aktualisiert um 13:56:18 Uhr
Goto Top
Der offensichtlichste Grund: Alles muss eindeutig sein. Wenn du mehrere Constraints auf einer Tabelle hast, muss der SQL-Server diese eindeutig identifizieren und auseinanderhalten können. Schon alleine, um einen Constraint später zu bearbeiten oder zu löschen. Wenn du eine Constraint Violation hast, teilt dir der Server darüber ebenfalls mit, welcher Constraint gerade deine Datenänderungen verhindert.

Der andere Grund: Du kannst, abhängig von der eingesetzten Software, auch Trigger oder Functions haben, die explizit durch eine Constraint Violation getriggert werden. Auch hier musst du dann natürlich eindeutig den Constraint benennen können, der den Trigger auslösen soll.

Das genannte Beispiel ist ehrlich gesagt auch ein bisschen dämlich. Ein Primärschlüssel ist ja nunmal prinzipbedingt eindeutig und immer vorhanden, da kann ein Constraint wenig verbessern.
Ein besseres Beispiel für Constraints wäre IMHO:

Wir nehmen jetzt eine weitere Tabelle, in der wir Mitarbeiter verwalten und ggf. einen Dienstwagen zuordnen.
Das wäre dann:
CREATE TABLE mitarbeiter(
mitarbeiterid INT NOT NULL PRIMARY KEY,
name text NOT NULL,
dienstwagenid INT,
CONSTRAINT pk_mitarbeiterid PRIMARY KEY (mitarbeiterid)
);

Das gibt uns eine Reihe von Problemen:
Ein Dienstwagen kann mehreren Mitarbeitern zugeordnet sein, es können Dienstwagen zugewiesen werden die nicht existieren und wenn ich einen Dienstwagen lösche, bleibt er dem Mitarbeiter weiter zugewiesen.

Das kann man mit Constraints reparieren:
ALTER TABLE mitarbeiter
ADD CONSTRAINT unique_dienstwagenid UNIQUE KEY (dienstwagenid),
ADD CONSTRAINT fk_dienstwagen FOREIGN KEY (dienstwagenid) REFERENCES dienstwagen(dienstwagenid) ON DELETE RESTRICT;

Durch den Constraint "unique_dienstwagenid" (gut, dass wir ihn beim Namen referenzieren können!) sorgen wir dafür, dass ein Dienstwagen nur einem Mitarbeiter gleichzeitig zugewiesen ist.
Mit dem Constraint "fk_dienstwagen" sorgen wir dafür, dass der Dienstwagen nicht gelöscht werden kann, wenn noch ein Datensatz auf ihn referenziert.

Wenn du jetzt versuchst einen Dienstwagen zu löschen, wird dir der SQL-Server sagen dass es eine Constraint Violation gibt und "fk_dienstwagen" dich daran hindert, Datensätze zu löschen.

Und dafür brauchst du die eindeutigen Namen face-smile
pixel24
pixel24 01.07.2023 um 14:52:50 Uhr
Goto Top
Der offensichtlichste Grund: Alles muss eindeutig sein. Wenn du mehrere Constraints auf einer Tabelle hast, muss der SQL-Server diese eindeutig identifizieren und auseinanderhalten können. Schon alleine, um einen Constraint später zu bearbeiten oder zu löschen. Wenn du eine Constraint Violation hast, teilt dir der Server darüber ebenfalls mit, welcher Constraint gerade deine Datenänderungen verhindert.

Ja, klingt ja absolut logisch, bin jedoch nicht darauf gekommen face-sad

Der andere Grund: Du kannst, abhängig von der eingesetzten Software, auch Trigger oder Functions haben, die explizit durch eine Constraint Violation getriggert werden. Auch hier musst du dann natürlich eindeutig den Constraint benennen können, der den Trigger auslösen soll.

ok, grundsätzlich verstanden wenngleich ich von dieser Nutzung noch weit entfernt bin.

CREATE TABLE mitarbeiter(
mitarbeiterid INT NOT NULL PRIMARY KEY,
name text NOT NULL,
dienstwagenid INT,
CONSTRAINT pk_mitarbeiterid PRIMARY KEY (mitarbeiterid)
);

Dazu habe ich eine Frage. In der Form hatten wir das noch nicht. Ich definiere den PK also direkt in der Zeile in welcher die entsprechende Spalte definiert wird und am am Ende formuliere ich den CONSTRAINT indem er einen Bezeichner bekommt und angegeben wird welche der zuvor definierten Spalten der PK ist?
Macht ja Sinn wenn ich darüber nachdenke.

Ich denke ich habe es soweit verstanden face-smile Danke dafür!
ukulele-7
ukulele-7 04.07.2023 aktualisiert um 13:45:00 Uhr
Goto Top
Dein CREATE-Statement ist nicht korrekt. Tatsächlich versuchst du zwei Primary Keys zu definieren, es handelt sich nur um unterschiedliche Schreibweisen. Im ersten Fall wird ein zufälliger Name generiert, da kein Name spezifiziert wurde. In Zeile 5 versuchst du dann nochmal einen PRIMARY KEY zu erstellen, diesmal mit einem spezifischen Namen. MSSQL wirft hier z.B. folgende Meldung:

Msg 8110, Level 16, State 0, Line 1
Der mitarbeiter-Tabelle können nicht mehrere PRIMARY KEY-Einschränkungen hinzugefügt werden.

Die gesammte Tabelle wird nicht erstellt da es sich um ein Statement handelt. Du kannst aber auch CONSTRAINTs nachträglich per ADD hinzufügen, auch hier ist das Ergebnis aber gleich, es gibt maximal einen PK und wie der ursprünglich erzeugt wurde spielt keine Rolle, die Funktion ist die selbe.
pixel24
pixel24 06.07.2023 um 07:33:08 Uhr
Goto Top
Ok, hab es nochmal auf meiner MariDB ausprobiert. Hab's jetzt verstanden face-smile