Datenbankdesign in SQL – Normalformen 1NF bis 3NF einfach erklärt
Sauberes Datenbankdesign spart dir Zeit, Speicher und Nerven. Wenn Tabellen redundante Daten enthalten, drohen Update-, Insert- und Delete-Anomalien. Änderungen an einer Stelle ziehen überraschende Fehler an anderer Stelle nach sich.
Die SQL Normalformen helfen dir, Tabellen so zu schneiden, dass Attribute eindeutig zum Schlüssel passen. In diesem Guide lernst du 1NF, 2NF und 3NF mit einfachen Beispielen kennen. Du siehst, woran du Verstöße erkennst und wie du Tabellen schrittweise normalisierst.
Warum Normalisierung wichtig ist
Gute Modelle machen Abfragen einfacher, Änderungen sicherer und Leistung planbar. Du vermeidest Redundanz, machst Fremdschlüsselbeziehungen klar und stärkst die Datenintegrität. Denke an Normalisierung als Grundgerüst, auf dem du später bei Bedarf gezielt denormalisierst.
Ausgangssituation – typische Problem-Tabelle
Angenommen, du startest mit einer Sammel-Tabelle KundenBestellungen:
- BestellID, Kunde, KundenPLZ, KundenOrt, ArtikelListe = „Maus, Tastatur, Monitor“, Gesamtpreis
Diese Struktur klingt bequem, aber sie verletzt gleich mehrere Regeln. ArtikelListe ist eine Liste in einem Feld, KundenPLZ bestimmt KundenOrt transitiv, und Gesamtpreis ist aus Positionen abgeleitet.
1. Normalform (1NF) – atomare Werte statt Listen
Die 1NF fordert atomare Attribute: keine Listen, keine wiederholten Gruppen, jedes Feld genau ein Wert.
Verstoß erkennen
ArtikelListe enthält mehrere Artikel in einem Feld. Das ist nicht atomar. Du kannst einzelne Positionen nicht sauber filtern oder summieren.
Korrektur in 1NF
Trenne Bestellung und Bestellposition. Jede Position ist ein eigener Datensatz.
CREATE TABLE Kunde (
KundenID INT PRIMARY KEY,
Name VARCHAR(100),
PLZ CHAR(5),
Ort VARCHAR(100)
);
CREATE TABLE Bestellung (
BestellID INT PRIMARY KEY,
KundenID INT NOT NULL,
Bestelldatum DATE NOT NULL,
FOREIGN KEY (KundenID) REFERENCES Kunde(KundenID)
);
CREATE TABLE Produkt (
ProduktID INT PRIMARY KEY,
ProduktName VARCHAR(100),
Listenpreis DECIMAL(10,2)
);
CREATE TABLE Bestellposition (
BestellID INT NOT NULL,
ProduktID INT NOT NULL,
Menge INT NOT NULL,
Preis DECIMAL(10,2) NOT NULL,
PRIMARY KEY (BestellID, ProduktID),
FOREIGN KEY (BestellID) REFERENCES Bestellung(BestellID),
FOREIGN KEY (ProduktID) REFERENCES Produkt(ProduktID)
);
Jetzt ist jeder Artikel eine Zeile, und du kannst Preise und Mengen sauber aggregieren.
2. Normalform (2NF) – keine partiellen Abhängigkeiten
Die 2NF betrifft Tabellen mit zusammengesetztem Primärschlüssel. Kein Nicht-Schlüssel-Attribut darf nur von einem Teil des Schlüssels abhängen.
Verstoß erkennen
In Bestellposition(BestellID, ProduktID, Menge, Preis, ProduktName) hängt ProduktName nur von ProduktID, nicht vom ganzen Schlüssel. Das ist eine partielle Abhängigkeit.
Korrektur in 2NF
Lagere produktbezogene Attribute in Produkt aus. In Bestellposition bleiben nur Attribute, die von BestellID+ProduktID abhängen, etwa Menge und der vereinbarte Preis.
Ergebnis: Bestellposition hat nur noch Menge, Preis und die Schlüssel. ProduktName und Listenpreis liegen in Produkt. So sind Produktdaten einmalig gepflegt.
3. Normalform (3NF) – keine transitiven Abhängigkeiten
Die 3NF sagt: Nicht-Schlüssel-Attribute dürfen nicht voneinander abhängen. Sie müssen nur vom Primärschlüssel abhängen.
Verstoß erkennen
In Kunde(KundenID, PLZ, Ort) ist Ort von PLZ abhängig. KundenID → PLZ → Ort ist eine transitive Abhängigkeit. Wenn sich der Ort einer PLZ ändert, musst du es in allen Kundenzeilen mehrfach pflegen.
Korrektur in 3NF
Lagere die PLZ-Information aus oder behandle Ort als abgeleitet.
CREATE TABLE PLZRegister (
PLZ CHAR(5) PRIMARY KEY,
Ort VARCHAR(100) NOT NULL
);
-- Kunde referenziert nur PLZ
ALTER TABLE Kunde
ADD CONSTRAINT fk_kunde_plz
FOREIGN KEY (PLZ) REFERENCES PLZRegister(PLZ);
Damit hängt Ort nicht mehr von KundenID, sondern lebt einmalig pro PLZ.
Mini-Workflow – von der Roh-Tabelle zum sauberen Modell
Starte mit der Roh-Tabelle. Entferne zuerst Listenfelder und erzeugte Summen für die 1NF. Prüfe dann Tabellen mit zusammengesetzten Schlüsseln auf partielle Abhängigkeiten für die 2NF. Beseitige zum Schluss transitive Abhängigkeiten für die 3NF. Nach jedem Schritt kontrollierst du mit Beispielabfragen, ob alles noch funktioniert.
Praxisabfragen – so greifst du auf das Modell zu
Die Bestellsumme berechnest du jetzt zuverlässig per JOIN und SUM:
SELECT b.BestellID,
SUM(poz.Menge * poz.Preis) AS Gesamt
FROM Bestellung b
JOIN Bestellposition poz ON poz.BestellID = b.BestellID
GROUP BY b.BestellID;
Produktnamen blendest du über JOIN Produkt ein. Ortsangaben kommen über JOIN PLZRegister. Du änderst ProduktName oder Ort nur einmal, und alle Abfragen liefern sofort die neuen Werte.
Häufige Missverständnisse
Normalisierung ist kein Performance-Killer. Sie verhindert Widersprüche und hält Daten konsistent. Performance holst du mit Indexes, Query-Optimierung und nur dort nötiger Denormalisierung. Ein weiteres Missverständnis: 3NF reicht in der Praxis meist. Höhere Normalformen sind seltener nötig und eher für Spezialfälle.
Tipps für die Praxis
Benutze sprechende Primärschlüssel, setze Fremdschlüssel-Constraints konsequent und dokumentiere funktionale Abhängigkeiten. Prüfe regelmäßig mit EXPLAIN, ob deine Abfragen die richtigen Indexes nutzen. Wenn du denormalisierst, tue es gezielt und dokumentiere warum.
Fazit
Mit 1NF, 2NF und 3NF baust du Datenmodelle, die robust, verständlich und erweiterbar sind. Die wichtigsten Prinzipien sind atomare Attribute, keine partiellen Abhängigkeiten und keine transitiven Abhängigkeiten. Halte dich an diese Regeln, und du verhinderst Redundanz sowie Anomalien von Anfang an.


Hinterlasse einen Kommentar
An der Diskussion beteiligen?Hinterlasse uns deinen Kommentar!