Datenbankdesign Normalisierung
Datenbankdesign: Normalisierung verstehen
Gutes Datenbankdesign verhindert Datenanomalien und Redundanz. Normalisierung ist die Technik, um Tabellen optimal zu strukturieren.
Warum Normalisierung?
Ohne Normalisierung entstehen Probleme:
- Redundanz: Gleiche Daten mehrfach gespeichert
- Update-Anomalie: Änderung an mehreren Stellen nötig
- Insert-Anomalie: Daten nur mit anderen einfügbar
- Delete-Anomalie: Unbeabsichtigter Datenverlust
Beispiel: Unnormalisierte Tabelle
❌ Bestellungen (unnormalisiert) +----+------------+------------------+----------------+-------------+ | ID | Kunde | Kunde_Adresse | Produkt | Preis | +----+------------+------------------+----------------+-------------+ | 1 | Max Müller | Hauptstr. 1, Köln| Laptop | 999.00 | | 2 | Max Müller | Hauptstr. 1, Köln| Maus | 29.00 | | 3 | Anna Schmidt| Berliner Str. 5 | Laptop | 999.00 | +----+------------+------------------+----------------+-------------+ Probleme: - Kunde und Adresse mehrfach gespeichert - Preis mehrfach gespeichert - Adressänderung erfordert mehrere Updates
Erste Normalform (1NF)
Regel: Jede Zelle enthält nur atomare (unteilbare) Werte. Keine Wiederholungsgruppen.
❌ FALSCH (verletzt 1NF) +----+------------------+ | ID | Telefonnummern | +----+------------------+ | 1 | 0123, 0456, 0789 | ← Mehrere Werte in einer Zelle +----+------------------+ ✅ RICHTIG (1NF) +----+---------------+ | ID | Telefonnummer | +----+---------------+ | 1 | 0123 | | 1 | 0456 | | 1 | 0789 | +----+---------------+
Zweite Normalform (2NF)
Regel: 1NF + jedes Nicht-Schlüssel-Attribut hängt vom gesamten Primärschlüssel ab (nicht nur von einem Teil).
❌ FALSCH (verletzt 2NF) Bestellung_Produkte (Primärschlüssel: Bestellung_ID + Produkt_ID) +-------------+------------+---------------+--------------+ | Bestellung | Produkt_ID | Produkt_Name | Menge | +-------------+------------+---------------+--------------+ | 1 | 101 | Laptop | 1 | | 1 | 102 | Maus | 2 | +-------------+------------+---------------+--------------+ Problem: Produkt_Name hängt nur von Produkt_ID ab, nicht vom gesamten Schlüssel ✅ RICHTIG (2NF) - Aufteilung in zwei Tabellen: Produkte +----+-------------+ | ID | Name | +----+-------------+ | 101| Laptop | | 102| Maus | +----+-------------+ Bestellung_Produkte +-------------+------------+-------+ | Bestellung | Produkt_ID | Menge | +-------------+------------+-------+ | 1 | 101 | 1 | | 1 | 102 | 2 | +-------------+------------+-------+
Dritte Normalform (3NF)
Regel: 2NF + kein Nicht-Schlüssel-Attribut hängt transitiv vom Primärschlüssel ab.
❌ FALSCH (verletzt 3NF) Mitarbeiter +----+-------+-------------+---------------+ | ID | Name | Abteilung | Abt_Leiter | +----+-------+-------------+---------------+ | 1 | Max | Entwicklung | Herr Schmidt | | 2 | Anna | Entwicklung | Herr Schmidt | +----+-------+-------------+---------------+ Problem: Abt_Leiter hängt von Abteilung ab (transitiv über Primärschlüssel) ✅ RICHTIG (3NF) - Aufteilung: Mitarbeiter +----+-------+---------------+ | ID | Name | Abteilung_ID | +----+-------+---------------+ | 1 | Max | 1 | | 2 | Anna | 1 | +----+-------+---------------+ Abteilungen +----+-------------+---------------+ | ID | Name | Leiter | +----+-------------+---------------+ | 1 | Entwicklung | Herr Schmidt | +----+-------------+---------------+
Vollständig normalisiertes Beispiel
-- Kunden
CREATE TABLE kunden (
id INT PRIMARY KEY,
name VARCHAR(100),
email VARCHAR(100)
);
-- Adressen (1 Kunde kann mehrere haben)
CREATE TABLE adressen (
id INT PRIMARY KEY,
kunde_id INT REFERENCES kunden(id),
strasse VARCHAR(100),
plz VARCHAR(10),
ort VARCHAR(100)
);
-- Produkte
CREATE TABLE produkte (
id INT PRIMARY KEY,
name VARCHAR(100),
preis DECIMAL(10,2)
);
-- Bestellungen
CREATE TABLE bestellungen (
id INT PRIMARY KEY,
kunde_id INT REFERENCES kunden(id),
adresse_id INT REFERENCES adressen(id),
bestelldatum TIMESTAMP
);
-- Bestellpositionen (n:m zwischen Bestellung und Produkt)
CREATE TABLE bestellpositionen (
bestellung_id INT REFERENCES bestellungen(id),
produkt_id INT REFERENCES produkte(id),
menge INT,
preis_zum_zeitpunkt DECIMAL(10,2),
PRIMARY KEY (bestellung_id, produkt_id)
);
Wann Denormalisierung?
Manchmal ist bewusste Denormalisierung sinnvoll:
- Performance: Weniger JOINs bei Lesezugriffen
- Reporting: Aggregierte Werte speichern
- Historische Daten: Preise zum Bestellzeitpunkt
-- Beispiel: Preis zum Bestellzeitpunkt speichern -- (obwohl auch in Produkte-Tabelle) INSERT INTO bestellpositionen (bestellung_id, produkt_id, menge, preis_zum_zeitpunkt) VALUES (1, 101, 2, 999.00); -- Falls Preis sich ändert, bleibt historischer Preis erhalten
ER-Diagramm Notation
[Kunde] 1---n [Bestellung] n---m [Produkt] | 1 | n [Adresse] 1:n = Ein Kunde hat viele Bestellungen n:m = Bestellung enthält viele Produkte, Produkt in vielen Bestellungen
Zusammenfassung
| Normalform | Anforderung |
|---|---|
| 1NF | Atomare Werte, keine Wiederholungsgruppen |
| 2NF | 1NF + volle funktionale Abhängigkeit vom Schlüssel |
| 3NF | 2NF + keine transitiven Abhängigkeiten |