Eine "Viele-zu-Viele"-Beziehung bedeutet, dass ein Eintrag in einer Tabelle mit mehreren Einträgen in einer anderen Tabelle verbunden sein kann – und umgekehrt. Zum Beispiel: - Ein Student (aus der Tabelle students) kann in mehreren Kursen (aus der Tabelle courses) eingeschrieben sein. - Ein Kurs kann von mehreren Studenten besucht werden.
Das Problem ist, dass es ziemlich unpraktisch ist, so eine Beziehung direkt zu speichern. Hier kommt die Zwischentabelle ins Spiel, die diese Verbindungen speichert.
Beispiel aus dem echten Leben
Stell dir vor, du hast eine Tabelle für Studenten und eine für Kurse angelegt. Wenn du jetzt in jeder Tabelle eine Spalte für alle zugehörigen Daten einbauen willst, wird das schnell chaotisch:
- In der Tabelle
studentsmüsstest du eine Liste aller Kurse speichern, für die der Student eingeschrieben ist. Aber wie speicherst du eine Liste? Mit Kommas? Als Array? Das macht SQL-Queries echt kompliziert. - In der Tabelle
coursesmüsstest du eine Liste der Studenten speichern – das ist noch schlimmer.
Die richtige Lösung ist also: Erstelle eine dritte Tabelle, die die Beziehungen zwischen Studenten und Kursen speichert.
Die Zwischentabelle: Unser Retter!
Die Zwischentabelle (manchmal auch Beziehungstabelle genannt) löst alle Probleme. Sie enthält zwei Foreign Keys:
- Ein Foreign Key auf die Tabelle
students. - Ein Foreign Key auf die Tabelle
courses.
Jeder Eintrag in dieser Tabelle stellt eine Verbindung zwischen einem bestimmten Studenten und einem bestimmten Kurs her.
Tabellen für die "Viele-zu-Viele"-Beziehung erstellen
Lass uns loslegen! So kannst du Tabellen für die Beziehungen zwischen Studenten und Kursen erstellen:
Schritt 1: Tabelle students erstellen
Hier ist unsere Tabelle für Studenten. Wir speichern die eindeutigen IDs der Studenten und ihre Namen.
CREATE TABLE students (
student_id SERIAL PRIMARY KEY,
name TEXT NOT NULL
);
student_id– das ist die eindeutige ID des Studenten (autoincrement, dankeSERIAL!).name– der Name des Studenten.
Schritt 2: Tabelle courses erstellen
Jetzt erstellen wir die Tabelle für Kurse. Hier speichern wir die eindeutigen Kurs-IDs und ihre Titel.
CREATE TABLE courses (
course_id SERIAL PRIMARY KEY,
title TEXT NOT NULL
);
course_id– eindeutige ID des Kurses.title– Titel des Kurses.
Schritt 3: Die Zwischentabelle enrollments erstellen
Jetzt kommt unsere magische Beziehungstabelle. Sie enthält zwei Spalten, die jeweils ein Foreign Key auf die entsprechenden Tabellen sind.
CREATE TABLE enrollments (
student_id INT REFERENCES students(student_id),
course_id INT REFERENCES courses(course_id),
PRIMARY KEY (student_id, course_id)
);
Schauen wir uns die Struktur an:
student_id– Foreign Key, der aufstudent_idaus der Tabellestudentszeigt.course_id– Foreign Key, der aufcourse_idaus der Tabellecourseszeigt.PRIMARY KEY (student_id, course_id)– der Primary Key besteht aus der Kombination der beiden Foreign Keys. Das stellt sicher, dass jede Verbindung einzigartig ist.
Daten einfügen
Lass uns ein paar Daten einfügen, um zu sehen, wie das Ganze läuft.
Schritt 1: Studenten hinzufügen
INSERT INTO students (name) VALUES
('Alice'),
('Bob'),
('Charlie');
Ergebnis:
| student_id | name |
|---|---|
| 1 | Alice |
| 2 | Bob |
| 3 | Charlie |
Schritt 2: Kurse hinzufügen
INSERT INTO courses (title) VALUES
('Mathematics'),
('History'),
('Biology');
Ergebnis:
| course_id | title |
|---|---|
| 1 | Mathematics |
| 2 | History |
| 3 | Biology |
Schritt 3: Einträge in enrollments hinzufügen
Jetzt schreiben wir die Studenten in die Kurse ein. Zum Beispiel:
Aliceist inMathematicsundHistoryeingeschrieben.Bobist nur inBiologyeingeschrieben.Charlieist in allen drei Kursen eingeschrieben.
INSERT INTO enrollments (student_id, course_id) VALUES
(1, 1), -- Alice in Mathematics
(1, 2), -- Alice in History
(2, 3), -- Bob in Biology
(3, 1), -- Charlie in Mathematics
(3, 2), -- Charlie in History
(3, 3); -- Charlie in Biology
Ergebnis:
| student_id | course_id |
|---|---|
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
Queries für die "Viele-zu-Viele"-Beziehung
Jetzt, wo wir Daten haben, holen wir uns mal ein paar Infos raus!
Wie finde ich alle Kurse, für die ein Student eingeschrieben ist?
Zum Beispiel: Um herauszufinden, in welchen Kursen Alice (ID = 1) eingeschrieben ist, mach diesen Query:
SELECT c.title
FROM courses c
JOIN enrollments e ON c.course_id = e.course_id
WHERE e.student_id = 1;
Ergebnis:
| title |
|---|
| Mathematics |
| History |
Wie finde ich alle Studenten, die in einem bestimmten Kurs eingeschrieben sind?
Sagen wir, du willst wissen, wer im Kurs Mathematics (ID = 1) eingeschrieben ist:
SELECT s.name
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
WHERE e.course_id = 1;
Ergebnis:
| name |
|---|
| Alice |
| Charlie |
Wie finde ich alle Studenten und ihre Kurse?
Um den kompletten Überblick zu bekommen, wer wo eingeschrieben ist, mach diesen Query:
SELECT s.name AS student, c.title AS course
FROM students s
JOIN enrollments e ON s.student_id = e.student_id
JOIN courses c ON e.course_id = c.course_id;
Ergebnis:
| student | course |
|---|---|
| Alice | Mathematics |
| Alice | History |
| Bob | Biology |
| Charlie | Mathematics |
| Charlie | History |
| Charlie | Biology |
Die enrollments-Tabelle macht unser Schema mega flexibel – wir können easy Beziehungen zwischen Studenten und Kursen hinzufügen oder löschen, ohne die Haupttabellen anzufassen. Mit JOIN-Queries findest du schnell raus, wer in welchem Kurs ist. Und die Foreign Keys sorgen automatisch dafür, dass keine Fehler passieren – zum Beispiel, dass niemand einen Studenten in einen Kurs einschreibt, den es gar nicht gibt.
Typische Fehler bei "Viele-zu-Viele"-Beziehungen
Fehlende Unique-Constraint: Wenn du keinen PRIMARY KEY setzt, kannst du versehentlich dieselbe Beziehung mehrfach eintragen.
Verletzung der Datenintegrität: Wenn du versuchst, einen Eintrag mit einer nicht existierenden student_id oder course_id einzufügen, gibt's einen Fehler.
Falsche Reihenfolge beim Löschen: Wenn du zuerst einen Kurs aus courses löschst, bleiben die Einträge in enrollments als "Waisen" zurück. Um das zu verhindern, nutze ON DELETE CASCADE beim Definieren der Foreign Keys.
GO TO FULL VERSION