Datenbankdesign: Normalisierung erklärt

Redundante Daten führen zu Fehlern und Chaos. Lerne, wie du mit Normalisierung dein Datenbankschema sauber und konsistent strukturierst.

Teilen
Datenbankdesign: Normalisierung erklärt

Ein gutes Datenbankschema entscheidet darüber, ob deine Anwendung wartbar bleibt oder im Chaos versinkt. Die Normalisierung ist ein systematischer Prozess, um Daten so zu strukturieren, dass Redundanz vermieden wird und die Konsistenz erhalten bleibt. In diesem Beitrag gehen wir die ersten drei Normalformen Schritt für Schritt durch.

Das Problem mit unnormalisierten Daten

Stell dir eine einzige große Tabelle vor, die Bestellungen mitsamt allen Kundendaten speichert. Schreibt ein Kunde mehrere Bestellungen, wiederholen sich Name und Adresse in jeder Zeile. Diese Redundanz ist gefährlich: Ändert sich die Adresse, musst du sie überall ändern, und vergisst du eine Zeile, sind die Daten widersprüchlich.

-- Schlecht: alles in einer Tabelle
CREATE TABLE bestellungen_schlecht (
  bestell_id INTEGER,
  kunde_name TEXT,
  kunde_adresse TEXT,
  produkt TEXT
);

Die erste Normalform (1NF)

Die erste Normalform verlangt, dass jede Zelle einen einzigen, unteilbaren Wert enthält. Listen mehrerer Werte in einem Feld sind nicht erlaubt. Außerdem sollte jede Zeile eindeutig identifizierbar sein, üblicherweise über einen Primärschlüssel.

-- Verletzt 1NF: mehrere Produkte in einem Feld
-- produkte = 'Buch, Stift, Heft'

-- 1NF-konform: ein Produkt pro Zeile
CREATE TABLE bestellpositionen (
  id INTEGER PRIMARY KEY,
  bestell_id INTEGER,
  produkt TEXT
);

Jeder Wert steht nun atomar in einer eigenen Zelle, und jede Zeile hat einen eindeutigen Schlüssel.

Die zweite Normalform (2NF)

Die zweite Normalform baut auf der ersten auf und verlangt, dass jede Nicht-Schlüssel-Spalte vom gesamten Primärschlüssel abhängt, nicht nur von einem Teil davon. Das wird vor allem bei zusammengesetzten Schlüsseln relevant.

-- Kundendaten gehören nicht in die Bestellposition,
-- sie hängen nur vom Kunden ab. Wir trennen sie aus:
CREATE TABLE kunden (
  id INTEGER PRIMARY KEY,
  name TEXT,
  adresse TEXT
);

CREATE TABLE bestellungen (
  id INTEGER PRIMARY KEY,
  kunde_id INTEGER REFERENCES kunden(id),
  datum DATE
);

Die Kundendaten leben jetzt nur noch an einer einzigen Stelle.

Die dritte Normalform (3NF)

Die dritte Normalform fordert, dass keine Nicht-Schlüssel-Spalte von einer anderen Nicht-Schlüssel-Spalte abhängt. Solche transitiven Abhängigkeiten löst man durch das Auslagern in eigene Tabellen.

-- Die Postleitzahl bestimmt die Stadt,
-- also hängt 'stadt' von 'plz' ab, nicht vom Schlüssel.
-- Lösung: eigene Tabelle für Orte
CREATE TABLE orte (
  plz TEXT PRIMARY KEY,
  stadt TEXT
);

CREATE TABLE kunden (
  id INTEGER PRIMARY KEY,
  name TEXT,
  plz TEXT REFERENCES orte(plz)
);

Jetzt ist jede Information genau an einem Ort gespeichert, und Änderungen bleiben konsistent.

Die Vorteile auf einen Blick

Wenn du dein Schema normalisierst, profitierst du gleich mehrfach:

  • Weniger Redundanz: Jede Information steht nur einmal in der Datenbank.
  • Konsistenz: Aktualisierungen müssen nur an einer Stelle erfolgen.
  • Klarheit: Die Struktur spiegelt die echten Beziehungen der Daten wider.

Bedenke aber: In sehr leselastigen Systemen wird manchmal bewusst denormalisiert, um Joins zu sparen und Abfragen zu beschleunigen. Das ist ein Kompromiss, den du gezielt eingehen solltest.

Fazit

Normalisierung hilft dir, Daten sauber und widerspruchsfrei zu organisieren. Die erste Normalform sorgt für atomare Werte, die zweite löst partielle Abhängigkeiten und die dritte beseitigt transitive Abhängigkeiten. In den allermeisten Anwendungen ist die dritte Normalform ein hervorragendes Ziel. Wenn du diese Prinzipien verinnerlichst, baust du Datenbankschemata, die auch nach Jahren noch wartbar und konsistent bleiben.