MySQL Normalformen
Dieser Artikel dreht sich um gutes Datenbankdesign. Es wird euch erklärt, wie ihr sinnvoll eure Tabellen und Spalten strukturiert und was ihr dabei beachten solltet. Wichtig in diesem Zusammenhang zu nennen sind die drei Normalformen. Die drei Normalformen geben euch Regeln vor, wie ihr eure Daten aufzuteilen habt. Für Einsteiger ist es zu empfehlen, dass eure Datenbanktabellen stets die Regeln der dritten Normalform erfüllen. Nur in Ausnahmefällen solltet ihr davon abweichen.
Das Ziel der Normalformen ist, die Konsistenz eurer Datenbank zu erhöhen indem unnötige Datenredundanz reduziert wird. Die drei Normalformen sind dabei aufeinander aufbauend, sprich, damit eine Tabelle in der dritten Normalform ist, muss diese ebenfalls in der ersten und zweiten Normalform sein.
Inhaltsverzeichnis
Allgemeine Hinweise zum Datenbankdesign
Die drei Normalformen sind ziemlich theoretisch, helfen aber hoffentlich etwas beim besseren Design eurer Datenbank. Zusammengefasst solltet ihr die folgenden beiden Prinzipien beachten:
- Pro Spalte sollte nur ein Wert / eine Information abgespeichert werden. Habt ihr Zusammengesetzte Informationen, z.B. die Wohnanschrift, so ist es sinnvoll diese in die Bestandteile der Straße, PLZ, Wohnort etc. aufzusplitten.
- Pro Entität in eurer Datenbank sollte es eine eigenständige Tabelle gebe. Sprich, eine spezielle Tabelle für Kunden, eine Tabelle für Songs, eine Tabelle für Alben, eine Tabelle für Interpreten. Die Daten zu mehreren Entitäten, z.B. Songs und Alben, sollte ihr nicht in einer Tabelle vermischen. Habt ihr Redundanz in der Tabelle, z.B. der selbe Interpret taucht mehrfach in eurer Tabelle auf, so ist das ein Hinweis, dass ihr die dritte Normalform verletzt habt.
1. Normalform
Bedingung: Eine Tabelle befindet sich in der ersten Normalform, wenn in keiner Spalte mehrere Werte eingetragen sind. Pro Spalte wird damit genau ein Wert abgespeichert.
Nehmt das Beispiel einer Kundentabelle. In dieser habt ihr ggf. den Namen eurer Kunden sowie die Anschrift hinterlegt:
1 2 3 4 5 6 7 |
Tabelle 'kunden' +----+---------------+----------------------------------+ | id | Name | Anschrift | +----+---------------+----------------------------------+ | 1 | Klaus Schmidt | Winkelgasse 1, 10112 Berlin | | 2 | Lisa Müller | Berliner Allee 12, 81929 München | +----+---------------+----------------------------------+ |
Möchtet ihr nun alle Kunden ausgeben die in Berlin wohnen, so ist dies bei der obigen Tabelle kaum möglich oder nur mit viel viel Aufwand möglich. Die erste Normalform besagt nun, dass in keiner Spalte mehrere Werte eingetragen sein soll. In der Spalte Name ist allerdings der Vor- und Nachname und in der Spalte Anschrift die Straße, die Hausnummer, die Postleitzahl und der Ort eingetragen.
Diese Tabelle in der ersten Normalform würde wie folgt aussehen:
1 2 3 4 5 6 7 |
Tabelle 'kunden' in 1. Normalform +----+---------+----------+----------------+------------+-------+---------+ | id | Vorname | Nachname | Straße | Hausnummer | PLZ | Ort | +----+---------+----------+----------------+------------+-------+---------+ | 1 | Klaus | Schmidt | Winkelgasse | 1 | 10112 | Berlin | | 2 | Lisa | Müller | Berliner Allee | 12 | 81929 | München | +----+---------+----------+----------------+------------+-------+---------+ |
Bei dieser Tabelle alle Kunden die in Berlin wohnen abzufragen ist deutlich leichter.
2. Normalform
Bedingung: Eine Tabelle befindet sich in der zweiten Normalform, wenn sie sich in der ersten Normalform befindet und zusätzlich jede Spalte von allen Primärschlüsselspalten vollständig funktional abhängig ist.
Die zweite Normalform ist leider nicht mehr ganz so leicht zu verstehen, aber Intuitiv sollte es hoffentlich klar sein nach einem Beispiel.
Angenommen ihr habt eine Tabelle für Lieder von verschiedenen Alben. Die Tabelle sieht dabei wie folgt aus (diese ist nicht in der 2. Normalform):
1 2 3 4 5 6 7 8 |
Tabelle 'songs' (keine 2. Normalform) +---------+--------+----------+------------+------------+ | albumid | songnr | Album | Interpret | Song | +---------+--------+----------+------------+------------+ | 1 | 1 |Nevermind | Nirvana | Polly | | 1 | 2 |Nevermind | Nirvana | On a Plain | | 2 | 1 |The Wall | Pink Floyd | Vera | +---------+--------+----------+------------+------------+ |
In der obigen Songs-Tabelle sind die albumid und die songnr der Primärschlüssel (manchmal auch Schüsselkandidat genannt), da über diese beiden Spalten alle Datensätze identifiziert werden können. Diese Tabelle ist aber nicht in der 2. Normalform, da das Album und der Interpret nur von der Albumid abhängig ist, nich von der songid. Dieses ist bei der zweiten Normalform untersagt.
Sofern der Primärschlüssel eurer Tabelle nur eine Spalte umfasst, so ist jede Tabelle die in der ersten Normalform ist, automatisch auch in der 2. Normalform.
Ein besseres Tabellendesign für die obige Tabelle wäre:
1 2 3 4 5 6 7 8 |
Tabelle 'songs' Tabelle 'album' (2. aber keine 3. NF) +----+--------+------------+ +----+-----------+------------+ | id | albumid| Song | | id | Albumname | Interpret | +----+--------+------------+ +----+-----------+------------+ | 1 | 1 | Polly | | 1 | Nevermind | Nirvana | | 2 | 1 | On a Plain | | 2 | The Wall | Pink Floyd | | 3 | 2 | Vera | | 3 | Meddle | Pink Floyd | +----+--------+------------+ +----+-----------+------------+ |
3. Normalform
Bedingung: Eine Tabelle befindet sich in der dritten Normalform, wenn sie sich in der zweiten Normalform befindet und zusätzlich keine Nicht-Schlüssel-Spalten von anderen Nicht-Schlüssel-Spalten abhängig sind. Jede Nicht-Schlüssel-Spalte darf also nur direkt von einem Primärschlüssel abhängig sein.
Die unter der 2. Normalform aufgeführten Tabelle Album ist nicht in der dritten Normalform, denn die Nicht-Schlüssel-Spalte Interpret hängt von der Nicht-Schlüssel-Spalte Albumname ab. Dies darf bei der dritten Normalform nicht der Fall sein. Ein Hinweis dass diese Tabelle die dritte Normalform verletzt gibt übrigens, dass die Band Pink Floyd in mehr als nur einem Datensätzen auftaucht. Solche redundanten Daten sind oft ein guter Hinweis auf ein schlechtes Tabellendesign.
Redundanz ist tendenziell immer schlecht in Datenbanken. Möchtet ihr nun neben dem Bandnamen auch noch das Gründungsjahr der Band in der Datenbank abspeichern, so müsstet ihr in der Tabelle Album sicherstellen dass in alle Einträgen zu Pink Floyd das gleiche Gründungsdatum auftaucht.
Ein besseres Tabellendesign, welches in der 3. Normalform ist, sieht wie folgt aus:
1 2 3 4 5 6 7 8 |
Tabelle 'interpreten' Tabelle 'album' (3. NF) +----+------------+ +----+-----------+-------------+ | id | Interpret | | id | Albumname | interpretid | +----+------------+ +----+-----------+-------------+ | 1 | Metallica | | 1 | Nevermind | 1 | | 2 | Pink Floyd | | 2 | The Wall | 2 | +----+------------+ | 3 | Meddle | 2 | +----+-----------+-------------+ |
Bei diesem Datenbankdesign ist es leicht möglich, das Gründungsjahr der Band hinzuzufügen und pro Band / Interpret müsste nur ein Eintrag ergänzt werden.
Autor: Nils Reimers