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:

NameKontinentKontinentFlaecheKontinentEinwohner
ÖsterreichEuropa10733
DeutschlandEuropa10180733000
FrankreichEurope10733
ItalienEuropa10733
PolenEuropa10733

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:

LNRNameKNREinwohner
AÖsterreichEU8.51
DDeutschlandEU84.36
FFrankreichEU66.32
IItalienEU60.78
PLPolenEU38.56

Ausschnitt der Tabelle land

KNRNameFlaecheEinwohnerAnteilErdoberflaeche
AAAntarktis1302.6
AFAfrika309445.9
ASAsien4440108.7
AUAustralien9341.7
EUEuropa107332.1
NANordamerika245234.9
SASüdamerika183813.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“.

Freitext

Nenne zwei Probleme, die durch redundante Daten entstehen.

💡 Zum Speichern deiner Antwort bitte einloggen.

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.

Versuch 1 🗄 terra (mit Schlüsseln)
Führe diesen Befehl aus. Wie viele Datensätze liefert er?
Datenbankschema „terra (mit Schlüsseln)“ anzeigen
kontinent (7 Datensätze)
  • 🔑 KNR text
  • Name text
  • Flaeche numeric
  • Einwohner numeric
  • AnteilErdoberflaeche numeric
land (197 Datensätze)
  • 🔑 LNR text
  • Name text
  • KNR text → kontinent.KNR
  • Einwohner numeric
  • Flaeche numeric
  • HauptONR text → ort.ONR
ort (27092 Datensätze)
  • 🔑 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.

Freitext

Das Ergebnis ist nicht wie erwartet. Erkläre, wie das Datenbanksystem vorgegangen ist.

💡 Zum Speichern deiner Antwort bitte einloggen.
Versuch 2 🗄 terra (mit Schlüsseln)
Ergänze nun die Bedingung WHERE KNR = KNR und führe den Befehl aus.
Datenbankschema „terra (mit Schlüsseln)“ anzeigen
kontinent (7 Datensätze)
  • 🔑 KNR text
  • Name text
  • Flaeche numeric
  • Einwohner numeric
  • AnteilErdoberflaeche numeric
land (197 Datensätze)
  • 🔑 LNR text
  • Name text
  • KNR text → kontinent.KNR
  • Einwohner numeric
  • Flaeche numeric
  • HauptONR text → ort.ONR
ort (27092 Datensätze)
  • 🔑 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.

Freitext

Übersetze und erkläre die Fehlermeldung.

💡 Zum Speichern deiner Antwort bitte einloggen.

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
NameEinwohnerName
Brasilien214.5Südamerika
Indien1428.63Asien
Pakistan235.8Asien
Indonesien275.5Asien
Vereinigte Staaten von Amerika333.28Nordamerika
China1411.75Asien
Nigeria230.8Afrika

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'.
Aufgabe 1 🗄 terra (mit Schlüsseln)
Gib Name und Einwohner jedes Landes zusammen mit dem Namen seines Kontinents aus.
Datenbankschema „terra (mit Schlüsseln)“ anzeigen
kontinent (7 Datensätze)
  • 🔑 KNR text
  • Name text
  • Flaeche numeric
  • Einwohner numeric
  • AnteilErdoberflaeche numeric
land (197 Datensätze)
  • 🔑 LNR text
  • Name text
  • KNR text → kontinent.KNR
  • Einwohner numeric
  • Flaeche numeric
  • HauptONR text → ort.ONR
ort (27092 Datensätze)
  • 🔑 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)

Struktur vorgeben:

Ohne Anmeldung wird deine Abfrage nicht gespeichert.

Aufgabe 2 🗄 terra (mit Schlüsseln)
Gib Name und Einwohner aller Länder in Asien aus – die bevölkerungsreichsten zuerst. Verwende in deiner Bedingung keine Schlüsselwerte wie 'AS'.
Datenbankschema „terra (mit Schlüsseln)“ anzeigen
kontinent (7 Datensätze)
  • 🔑 KNR text
  • Name text
  • Flaeche numeric
  • Einwohner numeric
  • AnteilErdoberflaeche numeric
land (197 Datensätze)
  • 🔑 LNR text
  • Name text
  • KNR text → kontinent.KNR
  • Einwohner numeric
  • Flaeche numeric
  • HauptONR text → ort.ONR
ort (27092 Datensätze)
  • 🔑 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)

Struktur vorgeben:

Ohne Anmeldung wird deine Abfrage nicht gespeichert.

Aufgabe 3 🗄 terra (mit Schlüsseln)
Welche europäischen Länder haben mehr als 300.000 km² Fläche? Gib Name und Fläche aus.
Datenbankschema „terra (mit Schlüsseln)“ anzeigen
kontinent (7 Datensätze)
  • 🔑 KNR text
  • Name text
  • Flaeche numeric
  • Einwohner numeric
  • AnteilErdoberflaeche numeric
land (197 Datensätze)
  • 🔑 LNR text
  • Name text
  • KNR text → kontinent.KNR
  • Einwohner numeric
  • Flaeche numeric
  • HauptONR text → ort.ONR
ort (27092 Datensätze)
  • 🔑 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)

Struktur vorgeben:

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.

Aufgabe 4 🗄 terra (mit Schlüsseln)
Gib Name und Einwohner aller Orte mit mehr als 10 Millionen Einwohnern zusammen mit dem Namen ihres Landes aus – die größten zuerst.
Datenbankschema „terra (mit Schlüsseln)“ anzeigen
kontinent (7 Datensätze)
  • 🔑 KNR text
  • Name text
  • Flaeche numeric
  • Einwohner numeric
  • AnteilErdoberflaeche numeric
land (197 Datensätze)
  • 🔑 LNR text
  • Name text
  • KNR text → kontinent.KNR
  • Einwohner numeric
  • Flaeche numeric
  • HauptONR text → ort.ONR
ort (27092 Datensätze)
  • 🔑 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)

Struktur vorgeben:

Ohne Anmeldung wird deine Abfrage nicht gespeichert.

Aufgabe 5 🗄 terra (mit Schlüsseln)
Welche Orte in Europa haben mehr als 1 Million Einwohner? Gib Name und Einwohner der Orte aus.
Datenbankschema „terra (mit Schlüsseln)“ anzeigen
kontinent (7 Datensätze)
  • 🔑 KNR text
  • Name text
  • Flaeche numeric
  • Einwohner numeric
  • AnteilErdoberflaeche numeric
land (197 Datensätze)
  • 🔑 LNR text
  • Name text
  • KNR text → kontinent.KNR
  • Einwohner numeric
  • Flaeche numeric
  • HauptONR text → ort.ONR
ort (27092 Datensätze)
  • 🔑 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)

Struktur vorgeben:

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.

Aufgabe 6 🗄 Social Media
Gib Zeitpunkt, Nutzername und Text aller Fotofant-Beiträge aus, die im Freibad Bliesheim gepostet wurden.
Datenbankschema „Social Media“ anzeigen
nutzer (60 Datensätze)
  • 🔑 NutzerID integer
  • Nutzername varchar(30)
  • Vorname varchar(30)
  • Geburtsjahr integer
  • Wohnort varchar(30)
  • Privat integer
beitrag (477 Datensätze)
  • 🔑 BeitragID integer
  • NutzerID integer → nutzer.NutzerID
  • Zeitpunkt varchar(16)
  • Ort varchar(40)
  • Text varchar(200)
  • Aufrufe integer
gefaellt (3105 Datensätze)
  • 🔑 NutzerID integer → nutzer.NutzerID
  • 🔑 BeitragID integer → beitrag.BeitragID
folgt (454 Datensätze)
  • 🔑 FollowerID integer → nutzer.NutzerID
  • 🔑 NutzerID integer → nutzer.NutzerID
gewinnspiel (19 Datensätze)
  • 🔑 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)

Struktur vorgeben:

Ohne Anmeldung wird deine Abfrage nicht gespeichert.

Freitext

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?

💡 Zum Speichern deiner Antwort bitte einloggen.

Schlüssel selbst wählen

Für die Verwaltung der Noten einer Klasse hat sich ein Lehrer diese Datenbank erstellt:

schueler
NameVornameGeburtsdatum
FallKlara2013-04-02
KondaAnna2012-11-19
TürlichJana2013-01-23
note
NameFachDatumNote
FallMathematik2026-09-152
TürlichMathematik2026-09-151
FallEnglisch2026-09-223
Freitext

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?

💡 Zum Speichern deiner Antwort bitte einloggen.
Multiple Choice

Welches Attribut der Tabelle note ist ein Fremdschlüssel?

Freitext

Ändere beide Tabellen so ab, dass die Probleme vermieden werden. Notiere die neuen Attribute beider Tabellen und kennzeichne Primär- und Fremdschlüssel.

💡 Zum Speichern deiner Antwort bitte einloggen.

✏️ Übungen zu diesem Kapitel

9 freiwillige Aufgaben zum Üben und Weiterdenken.

Zu den Übungen →