Vom Problem zum Modell
Guter Entwurf ist wichtiger als schlaue Abfragen. Vorgehen:
- Entitäten finden (Dinge, über die du Daten speicherst): Kunde, Bestellung, Produkt
- Attribute bestimmen: Name, Preis, Datum
- Beziehungen festlegen: Kunde 1:n Bestellung, Bestellung n:m Produkt
- Schlüssel wählen und Tabellen anlegen
Als Skizze dient ein ER-Diagramm (Entity-Relationship).
Normalisierung
Normalisierung vermeidet Redundanz und Anomalien (Änderungs-, Lösch- und Einfügefehler).
Schlechte Tabelle (alles in einer):
| bestell_id | kunde | kunden_ort | produkte |
|---|---|---|---|
| 1 | Mia | Berlin | Maus, Laptop |
| 2 | Mia | Berlin | Monitor |
Probleme: Kundenort mehrfach gespeichert (Änderung muss überall erfolgen), mehrere Werte in einer Zelle.
| Normalform | Regel |
|---|---|
| 1NF | Jede Zelle enthält genau einen Wert (keine Listen), jede Zeile ist eindeutig |
| 2NF | 1NF, und jedes Nichtschlüsselattribut hängt vom ganzen Schlüssel ab |
| 3NF | 2NF, und kein Nichtschlüsselattribut hängt von einem anderen Nichtschlüsselattribut ab |
Gemerkt als: "Die Daten hängen vom Schlüssel, dem ganzen Schlüssel und nichts als dem Schlüssel."
Ergebnis
PRAGMA foreign_keys = ON;
CREATE TABLE kunden (id INTEGER PRIMARY KEY, name TEXT NOT NULL, ort TEXT);
CREATE TABLE produkte (id INTEGER PRIMARY KEY, name TEXT NOT NULL, preis REAL NOT NULL);
CREATE TABLE bestellungen (id INTEGER PRIMARY KEY, kunde_id INTEGER NOT NULL REFERENCES kunden(id), datum TEXT);
CREATE TABLE positionen (
bestellung_id INTEGER REFERENCES bestellungen(id),
produkt_id INTEGER REFERENCES produkte(id),
menge INTEGER NOT NULL CHECK (menge > 0),
preis_bei_kauf REAL NOT NULL,
PRIMARY KEY (bestellung_id, produkt_id)
);
INSERT INTO kunden VALUES (1, 'Mia', 'Berlin');
INSERT INTO produkte VALUES (1, 'Maus', 25.5), (2, 'Laptop', 999);
INSERT INTO bestellungen VALUES (1, 1, '2025-01-10');
INSERT INTO positionen VALUES (1, 1, 2, 25.5), (1, 2, 1, 999);
SELECT k.name, p.name AS produkt, po.menge, po.menge * po.preis_bei_kauf AS summe
FROM positionen po
JOIN bestellungen b ON b.id = po.bestellung_id
JOIN kunden k ON k.id = b.kunde_id
JOIN produkte p ON p.id = po.produkt_id;name produkt menge summe ---- ------- ----- ----- Mia Maus 2 51.0 Mia Laptop 1 999.0
Beachte preis_bei_kauf: Der Preis zum Kaufzeitpunkt wird bewusst kopiert, weil der Produktpreis sich später ändert. Das ist gewollte Denormalisierung.
Denormalisierung
Manchmal verletzt man Normalformen bewusst, z. B. für Berichte oder Lesegeschwindigkeit (Zwischensummen speichern). Wichtig ist, dass es eine bewusste Entscheidung ist.
Namens- und Stilregeln
- Einheitlich benennen (
snake_case, Einzahl oder Mehrzahl konsequent) - Fremdschlüssel nach dem Muster
tabelle_id - Immer Primärschlüssel; sinnvolle Constraints
- Zeitstempel
erstellt_am,geaendert_ambei Bedarf - Keine Sonderzeichen oder reservierten Wörter (
order,user,group) - Soft Delete (
geloescht_am) statt hartem Löschen, wenn Historie zählt
Merke
- Entitäten, Attribute, Beziehungen: erst planen, dann Tabellen bauen
- 1NF bis 3NF vermeiden Redundanz und Anomalien
- Verbindungstabellen lösen n:m-Beziehungen
- Gezielte Denormalisierung ist erlaubt, wenn begründet
- Konsistente Namensgebung erleichtert die Arbeit im Team
Aufgabe
Entwirf das Schema für eine Bibliothek (Bücher, Autoren, Mitglieder, Ausleihen) in 3NF.