Tabellen verbinden – Fremdschlüssel und Join
Der Fremdschlüssel
Es ist oft nicht sinnvoll, alles in einer Tabelle zu speichern. In der Tabelle land von terra1 stehen die Daten des Kontinents bei jedem Land noch einmal – und prompt passieren Fehler:
| Name | Kontinent | KontinentFlaeche | KontinentEinwohner |
|---|---|---|---|
| Österreich | Europa | 10 | 733 |
| Deutschland | Europa | 10180 | 733000 |
| Frankreich | Europe | 10 | 733 |
| Italien | Europa | 10 | 733 |
| Polen | Europa | 10 | 733 |
Merke
- Daten, die mehrfach gespeichert sind, heißen redundant.
- Daten, die sich widersprechen, heißen inkonsistent.
Redundanz kostet Speicherplatz und führt schnell zu Inkonsistenz: Ändert sich ein Wert, muss man ihn an allen Stellen ändern – vergisst man eine, widersprechen sich die Daten.
Deshalb teilt man die Daten auf mehrere Tabellen auf. In der Datenbank terra3 stehen die Kontinente in einer eigenen Tabelle kontinent. Jedes Land verweist über das Attribut KNR auf seinen Kontinent:
| LNR | Name | KNR | Einwohner |
|---|---|---|---|
| A | Österreich | EU | 8.51 |
| D | Deutschland | EU | 84.36 |
| F | Frankreich | EU | 66.32 |
| I | Italien | EU | 60.78 |
| PL | Polen | EU | 38.56 |
Ausschnitt der Tabelle land
| KNR | Name | Flaeche | Einwohner | AnteilErdoberflaeche |
|---|---|---|---|---|
| AA | Antarktis | 13 | 0 | 2.6 |
| AF | Afrika | 30 | 944 | 5.9 |
| AS | Asien | 44 | 4010 | 8.7 |
| AU | Australien | 9 | 34 | 1.7 |
| EU | Europa | 10 | 733 | 2.1 |
| NA | Nordamerika | 24 | 523 | 4.9 |
| SA | Südamerika | 18 | 381 | 3.5 |
Die Tabelle kontinent
Jetzt stehen die Daten von Europa nur noch in einem Datensatz.
Merke
Ein Fremdschlüssel ist ein Attribut in einer Tabelle, das auf den Primärschlüssel einer anderen Tabelle verweist. Über den Fremdschlüssel stehen die beiden Tabellen in Beziehung.
Das Datenbanksystem achtet darauf, dass nur Werte im Fremdschlüssel stehen, die es in der anderen Tabelle auch gibt: Ein Land mit der KNR „XY“ kann man nicht speichern.
Merkhilfe: Ein Fremdschlüssel funktioniert wie ein Link im Internet. Im Wikipedia-Artikel zu Deutschland steht nicht alles über Europa, sondern ein Link zum Artikel „Europa“.
Nenne zwei Probleme, die durch redundante Daten entstehen.
Daten aus zwei Tabellen
Jetzt sollen wieder alle Länder ausgegeben werden – zusammen mit dem Namen ihres Kontinents. Dazu greifst du auf beide Tabellen zu.
Datenbankschema „terra (mit Schlüsseln)“ anzeigen
- 🔑 KNR text
- Name text
- Flaeche numeric
- Einwohner numeric
- AnteilErdoberflaeche numeric
- 🔑 LNR text
- Name text
- KNR text → kontinent.KNR
- Einwohner numeric
- Flaeche numeric
- HauptONR text → ort.ONR
- 🔑 ONR text
- Name text
- LNR text → land.LNR
- Landesteil text
- Einwohner integer
- Breite numeric
- Laenge numeric
🔑 Primärschlüssel · → Fremdschlüssel (verweist auf Tabelle.Attribut)
Ohne Anmeldung wird deine Abfrage nicht gespeichert.
Das Ergebnis ist nicht wie erwartet. Erkläre, wie das Datenbanksystem vorgegangen ist.
WHERE KNR = KNR und führe den Befehl aus.Datenbankschema „terra (mit Schlüsseln)“ anzeigen
- 🔑 KNR text
- Name text
- Flaeche numeric
- Einwohner numeric
- AnteilErdoberflaeche numeric
- 🔑 LNR text
- Name text
- KNR text → kontinent.KNR
- Einwohner numeric
- Flaeche numeric
- HauptONR text → ort.ONR
- 🔑 ONR text
- Name text
- LNR text → land.LNR
- Landesteil text
- Einwohner integer
- Breite numeric
- Laenge numeric
🔑 Primärschlüssel · → Fremdschlüssel (verweist auf Tabelle.Attribut)
Ohne Anmeldung wird deine Abfrage nicht gespeichert.
Übersetze und erkläre die Fehlermeldung.
Der SQL-Join
Will man Daten aus mehreren Tabellen ausgeben, bildet man einen Join (engl. to join: verbinden). Man kann sich ihn in drei Schritten vorstellen:
1. Tabellen auswählen. Im FROM-Teil stehen alle Tabellen, deren Daten gebraucht werden. Das Ergebnis ist zunächst das Kreuzprodukt – jeder Datensatz mit jedem.
2. Verbindung angeben. Nur die Zeilen sind sinnvoll, bei denen der Fremdschlüssel zum Primärschlüssel passt. Damit klar ist, welches Attribut gemeint ist, schreibt man den Tabellennamen davor:
SELECT * FROM land, kontinent WHERE land.KNR = kontinent.KNR
3. Ergebnis einschränken. Weitere Bedingungen hängt man mit AND an, und man wählt nur die Attribute aus, die man braucht:
SELECT land.Name, land.Einwohner, kontinent.Name FROM land, kontinent WHERE land.KNR = kontinent.KNR AND land.Einwohner > 200
| Name | Einwohner | Name |
|---|---|---|
| Brasilien | 214.5 | Südamerika |
| Indien | 1428.63 | Asien |
| Pakistan | 235.8 | Asien |
| Indonesien | 275.5 | Asien |
| Vereinigte Staaten von Amerika | 333.28 | Nordamerika |
| China | 1411.75 | Asien |
| Nigeria | 230.8 | Afrika |
Merke
- Die Joinbedingung im
WHERE-Teil verbindet zwei Tabellen: Fremdschlüssel = Primärschlüssel. - Kommt ein Attributname in mehreren Tabellen vor, steht der Tabellenname davor:
land.Name. - Bedingungen mit internen Schlüsselwerten wie
land.KNR = 'EU'vermeidet man. Schlüssel können sich intern ändern – frage stattdessen nach dem Namen:kontinent.Name = 'Europa'.
Datenbankschema „terra (mit Schlüsseln)“ anzeigen
- 🔑 KNR text
- Name text
- Flaeche numeric
- Einwohner numeric
- AnteilErdoberflaeche numeric
- 🔑 LNR text
- Name text
- KNR text → kontinent.KNR
- Einwohner numeric
- Flaeche numeric
- HauptONR text → ort.ONR
- 🔑 ONR text
- Name text
- LNR text → land.LNR
- Landesteil text
- Einwohner integer
- Breite numeric
- Laenge numeric
🔑 Primärschlüssel · → Fremdschlüssel (verweist auf Tabelle.Attribut)
Ohne Anmeldung wird deine Abfrage nicht gespeichert.
'AS'.Datenbankschema „terra (mit Schlüsseln)“ anzeigen
- 🔑 KNR text
- Name text
- Flaeche numeric
- Einwohner numeric
- AnteilErdoberflaeche numeric
- 🔑 LNR text
- Name text
- KNR text → kontinent.KNR
- Einwohner numeric
- Flaeche numeric
- HauptONR text → ort.ONR
- 🔑 ONR text
- Name text
- LNR text → land.LNR
- Landesteil text
- Einwohner integer
- Breite numeric
- Laenge numeric
🔑 Primärschlüssel · → Fremdschlüssel (verweist auf Tabelle.Attribut)
Ohne Anmeldung wird deine Abfrage nicht gespeichert.
Datenbankschema „terra (mit Schlüsseln)“ anzeigen
- 🔑 KNR text
- Name text
- Flaeche numeric
- Einwohner numeric
- AnteilErdoberflaeche numeric
- 🔑 LNR text
- Name text
- KNR text → kontinent.KNR
- Einwohner numeric
- Flaeche numeric
- HauptONR text → ort.ONR
- 🔑 ONR text
- Name text
- LNR text → land.LNR
- Landesteil text
- Einwohner integer
- Breite numeric
- Laenge numeric
🔑 Primärschlüssel · → Fremdschlüssel (verweist auf Tabelle.Attribut)
Ohne Anmeldung wird deine Abfrage nicht gespeichert.
Auch die Orte sind in terra3 mit den Ländern verbunden: Die Tabelle ort hat einen Fremdschlüssel LNR, der auf das Land verweist. Schau dir das Schema an.
Datenbankschema „terra (mit Schlüsseln)“ anzeigen
- 🔑 KNR text
- Name text
- Flaeche numeric
- Einwohner numeric
- AnteilErdoberflaeche numeric
- 🔑 LNR text
- Name text
- KNR text → kontinent.KNR
- Einwohner numeric
- Flaeche numeric
- HauptONR text → ort.ONR
- 🔑 ONR text
- Name text
- LNR text → land.LNR
- Landesteil text
- Einwohner integer
- Breite numeric
- Laenge numeric
🔑 Primärschlüssel · → Fremdschlüssel (verweist auf Tabelle.Attribut)
Ohne Anmeldung wird deine Abfrage nicht gespeichert.
Datenbankschema „terra (mit Schlüsseln)“ anzeigen
- 🔑 KNR text
- Name text
- Flaeche numeric
- Einwohner numeric
- AnteilErdoberflaeche numeric
- 🔑 LNR text
- Name text
- KNR text → kontinent.KNR
- Einwohner numeric
- Flaeche numeric
- HauptONR text → ort.ONR
- 🔑 ONR text
- Name text
- LNR text → land.LNR
- Landesteil text
- Einwohner integer
- Breite numeric
- Laenge numeric
🔑 Primärschlüssel · → Fremdschlüssel (verweist auf Tabelle.Attribut)
Ohne Anmeldung wird deine Abfrage nicht gespeichert.
Verknüpfte Daten: Fotofant
Auch die erfundene Foto-Plattform Fotofant verteilt ihre Daten auf mehrere Tabellen: Die Beiträge stehen in beitrag, die Nutzerinnen und Nutzer in nutzer. Im Schema siehst du an den Pfeilen →, welcher Fremdschlüssel auf welchen Primärschlüssel verweist.
Datenbankschema „Social Media“ anzeigen
- 🔑 NutzerID integer
- Nutzername varchar(30)
- Vorname varchar(30)
- Geburtsjahr integer
- Wohnort varchar(30)
- Privat integer
- 🔑 BeitragID integer
- NutzerID integer → nutzer.NutzerID
- Zeitpunkt varchar(16)
- Ort varchar(40)
- Text varchar(200)
- Aufrufe integer
- 🔑 NutzerID integer → nutzer.NutzerID
- 🔑 BeitragID integer → beitrag.BeitragID
- 🔑 FollowerID integer → nutzer.NutzerID
- 🔑 NutzerID integer → nutzer.NutzerID
- 🔑 TeilnahmeID integer
- Nutzername varchar(30)
- Vorname varchar(30)
- Nachname varchar(30)
- Strasse varchar(40)
- PLZ varchar(5)
- Ort varchar(30)
🔑 Primärschlüssel · → Fremdschlüssel (verweist auf Tabelle.Attribut)
Ohne Anmeldung wird deine Abfrage nicht gespeichert.
Sieh dir das Ergebnis von Aufgabe 6 an. Was erfährt jemand, der Zugriff auf diese Daten hat, über die Nutzerin lina_rennt? Warum ist das bedenklich?
Schlüssel selbst wählen
Für die Verwaltung der Noten einer Klasse hat sich ein Lehrer diese Datenbank erstellt:
| Name | Vorname | Geburtsdatum |
|---|---|---|
| Fall | Klara | 2013-04-02 |
| Konda | Anna | 2012-11-19 |
| Türlich | Jana | 2013-01-23 |
| Name | Fach | Datum | Note |
|---|---|---|---|
| Fall | Mathematik | 2026-09-15 | 2 |
| Türlich | Mathematik | 2026-09-15 | 1 |
| Fall | Englisch | 2026-09-22 | 3 |
Warum wäre das Attribut Name im Moment ein möglicher Primärschlüssel der Tabelle schueler? Warum kann das später zu Problemen führen?
Welches Attribut der Tabelle note ist ein Fremdschlüssel?
Ändere beide Tabellen so ab, dass die Probleme vermieden werden. Notiere die neuen Attribute beider Tabellen und kennzeichne Primär- und Fremdschlüssel.