Die Normalisierung als systematische Vorgehensweise auf dem Weg, Redundanzen zu vermeiden bzw. zu beseitigen
Was versteht man unter „Normalisierung“?
Unser relationales Datenbankmodell der Datenbank „Schule“ ist nun fertig.
Bevor es mit einem nicht unbeträchtlichen Aufwand mit Hilfe eines DBMS in eine Datenbank umgesetzt wird, ist es prinzipiell sinnvoll, jedes Datenbankmodell auf mögliche Redundanzen hin zu untersuchen und diese ggf. zu beseitigen. Den Vorgang der systematischen Beseitigung von Redundanzen nennt man Normalisierung.
Die zentrale Frage der Normalisierung lautet:
- An welchen Stellen der Datenbank gibt es Abhängigkeiten zwischen den Attributen einer Relation, welche zu Redundanzen und damit zu Inkonsistenzen führen (können)?
Welche Ziele werden mit der Normalisierung verfolgt?
Insbesondere sollen durch die Normalisierung folgende Ziele erreicht werden:
- Redundanzfreiheit (keine Mehrfachspeicherung gleicher Daten)
- ⇒ Vermeidung logischer Widersprüche (Inskonsistenzen)
- ⇒ Höchstmögliche Flexibilität des Datenbanksystems, so dass Veränderungen leicht durchzuführen sind
- ⇒ Größtmögliche Schnelligkeit beim Zugriff auf die Daten
Um der Frage nachzugehen und die notwendigen Schritte kennen zu lernen, wollen wir unser bisheriges Beispiel einer Schuldatenbank zunächst einmal verlassen und uns dem Beispiel eines Möbelherstellers widmen:
Die Normalisierung soll nicht anhand eines fertigen Datenbankmodells durchgeführt werden. Vielmehr soll ein relationales Datenbankmodell unter Berücksichtigung der Normalformenlehre entwickelt werden. Die Grundlage der Überlegungen bildet eine Rechnung des Möbelherstellers:

Ausgangsrechnung der Firma Möbelmax
Die Betrachtung der Rechnung führt zunächst zu einer Relation mit folgenden Attributen:

Aus der Ausgangsrechnung abgeleitete Relation „tbl_rechnung“ mit den Rechnungsdaten
Die Rechnungsnummer wird als Primärschlüssel festgelegt und daher mit rechnungs-id bezeichnet. Bliebe es bei dieser einen Relation, würden viele Ziele der Datenorganisation nicht erreicht:
| Probleme | Erläuterung |
| Redundanzen | Kauft ein Kunde mehrfach ein, werden die Kundendaten für jede einzelne Rechnung erneut erfasst. Auch wenn ein Artikel in mehreren Rechnungen aufgeführt wird, werden alle Artikeldaten jedes Mal wieder vollständig eingegeben. |
| Inkonsistenzen | Die mehrfache Erfassung von Kunden- und Artikeldaten kann zu widersprüchlichen Daten und damit zu Inkonsistenzen führen. |
| Einfügeanomalien | Ein Artikel wird nur dann in die (aus einer einzigen Tabelle bestehenden) Datenbank aufgenommen, wenn es auch eine Bestellung für diesen Artikel gibt. Artikel, die auf Lager sind, aber noch nicht bestellt wurden, können nicht erfasst werden. |
| Löschanomalien | Wurde ein Artikel bisher nur ein einziges Mal bestellt, und wird die betreffende Rechnung gelöscht, z.B. weil ein Kunde die Löschung seiner personenbezogenen Daten beantragt, dann gehen auch alle Informationen über diesen Artikel verloren. |
| Änderungsanomalien | Gibt eine Kunde z.B. eine Adressänderung bekannt, dann müssen auch alle alten offenen Rechnungen dieses Kunden abgeändert werden. Wird dabei ein vorhandener Datensatz übersehen, werden unterschiedliche Informationen über den Kunden abgespeichert. |
Zum besseren Verständnis: Redundanzen und Inkonsistenzen sind das Ergebnis von Einfüge- und Änderungsanomalien. Bei Nichtbeachtung der Normalformen kann die Löschanomalie zu ungewolltem Datenverlust führen.
Warum die o.g. Ziele nicht erreicht werden, soll ein Datensatzbeispiel aus der o.g. „tbl_rechnung“ verdeutlichen:
Datenansicht der Relation „tbl_rechnung“
Abgesehen von der auf dieser Seite relativ kleinen Darstellung des abgebildeten Datensatzes ist zu erkennen, dass die Relation „tbl_rechnung“ in der vorliegenden Konzeption folgende Mängel enthält:
- Die Kundenadresse enthält neben dem Straßennamen auch die Hausnummer, die Postleitzahl sowie den Ort. Das macht die Formulierung von Abfragen zum Finden bestimmter Kunden bzw. deren Adressen relativ aufwändig.
- Die Attribute der Relation sind darauf ausgelegt, dass ein Auftrag und die daraus resultierende Rechnung maximal drei Artikel enthalten darf. Bei mehr enthaltenen Artikeln in einem Auftrag müsste ein neuer Datensatz mit einer neuen ID angelegt werden.
- Bei nur einem oder zwei Artikeln pro Bestellung blieben Zellen leer, was das System unnötig bremst, wenn es z.B. um das Sortieren oder das Auffinden bestimmter Daten geht. Auch leere Zellen benötigen Speicherplatz.
- Zuletzt ist erkennbar, dass die Eingabe sämtlicher Daten bei der Eingabe neuer Bestellungen wiederholt werden müsste. Davon sind alle in der Relation vorkommenden Daten betroffen (Artikelnummern, -bezeichnungen und -einzelpreise. Aber auch die Daten der Kunden.). Daten wären dann ggf. mehrfach, d.h. redundant, vorhanden, was die Gefahr der Widersprüchlichkeit und damit der Inkosistenz in sich birgt.
Bei der Gelegenheit halten wir fest: Eine Relation ist durch die Eingabe von neuen Datensätzen grundsätzlich beliebig verlängerbar. Was ihre Breite, festgelegt durch die Anzahl der Attribute, anbelangt, so ist diese nicht so einfach erweiterbar, ohne dann die Daten ggf. neu eingeben zu müssen.
Damit die Ziele der Datenorganisation besser verwirklicht werden können, sollen beim Entwurf von Datenmodellen die nachfolgenden Normalformen beachtet bzw. die Datenbank und deren Relationen in diese gebracht werden.
Erste Normalform
Eine Tabelle entspricht der ersten Normalform, wenn sie folgende Bedingungen erfüllt:
1. Alle Attributwerte müssen atomar, d.h. nicht mehr sinnvoll teilbar sein.
Für das Beispiel Möbelhersteller bedeutet das:
Die Kundenadresse ist nicht atomar, da sie sich sinnvollerweise in die Felder Straße, Hausnummer, Postleitzahl und Ort aufteilen lässt. Den Vorteil atomarer Werte kann man dann erkennen, wenn der Möbelhersteller z.B. Kunden in einer bestimmten Region anschreiben möchte. Ist die Postleitzahl als eigenständiges Attribut abgelegt, lassen sich die Kunden eines bestimmten Postleitzahlbereiches viel schneller extrahieren. Daher wird das Attribut Kundenadresse in vier Merkmale unterteilt.
2. Es dürfen keine Wiederholungsgruppen existieren.
In vorliegendem Beispiel hatte der Kunde drei verschiedene Artikel bestellt. Für jeden Artikel wurden nun jeweils fünf Merkmale abgespeichert – Artikelnummer, Artikelbezeichnung, Anzahl, Einzelpreis und Gesamtpreis. Da diese Merkmale mehrfach vorkommen, spricht man von Wiederholungsgruppen.
Muss eine Rechnung mit mehr als drei Artikeln gestellt werden, würden, wie oben bereits festgestellt, diese drei Mal fünf Felder nicht ausreichen. Die Tabelle müsste erweitert werden. Dies hätte zur Folge, dass wiederum bei vielen Rechnungen einige Felder leer blieben, die Tabelle unübersichtlicher und Speicherplatz für die Bereithaltung der (leeren) Datenfelder verschwendet würde.
Das Problem lässt sich lösen, indem die Tabelle Rechnung in zwei Tabellen aufgeteilt wird: In die Tabelle „tbl_rechnung“ mit den Kunden- und Rechnungsdaten und die Tabelle „tbl_rechnungsposition“ mit den Artikelinformationen der jeweiligen Rechnung. Die beiden Tabellen werden über die Rechnungsnummer miteinander verbunden, die weiterhin als rechnungs-ID Primärschlüssel der Tabelle „tbl_rechnung“ ist.
Für die Tabelle tbl_rechnungsposition sind die Rechnungsnummer und die Artikelnummer der zusammengesetzte Primärschlüssel (aus zwei Fremdschlüsseln). Sie werden mit rechnungs-Nr bzw. artikel-Nr bezeichnet.
Anmerkung: Datumsangaben, bestehend aus Tages-, Wochen- und Jahresangabe, verletzen die erste Normalform nicht, da in den meisten Fällen eine sinnvolle Informationsvermittlung erst durch die Kombination der drei Angaben möglich ist. Das gleiche gilt für die Angabe von Adressen, bestehend aus Straßenname und Hausnummer.
Die Datenbank des Möbelherstellers für die Erstellung der Rechnungen hat in der ersten Normalform folgendes Aussehen:

tbl_rechnung in der ersten Normalform durch Auslagerung von Daten in eine zweite Relation „tbl_rechnungsposition“
In Bezug auf die Abbildung sei an dieser Stelle erwähnt, dass die Attribute „summe netto“, „umsatzsteuer“ und „summe brutto“ durch Berechnung in einer Abfrage generiert werden könnten, was an dieser Stelle jedoch die Gefahr der Verwirrung für den Leser in sich birgt, wenn diese hier fehlen würden.
In der Datenansicht ergibt sich nun folgendes Bild:
Datenansicht der Relation „tbl_rechnung“, welche sich nun in der ersten Normalform befindet

tbl_rechnungsposition
Zweite Normalform
Eine Tabelle entspricht der zweiten Normalform, wenn sie folgende Bedingungen erfüllt:
- Die Tabelle ist in der ersten Normalform.
- Jedes Nichtschlüsselattribut muss voll funktional abhängig vom (zusammengesetzten) Primärschlüssel sein, d.h. entweder von allen Teilen oder von keinem.
Die zweite Normalform ist nur relevant, wenn die Tabelle einen zusammengesetzten Primärschlüssel (Gesamtschlüssel) hat.
Auf unser Beispiel des Möbelherstellers bezogen bedeutet das:
Die Tabelle tbl_rechnung befindet sich automatisch in der zweiten Normalform, weil sie sich in der ersten Normalform befindet und einen einfachen Primärschlüssel hat.
Daher ist nur die Tabelle tbl_rechnungsposition auf die zweite Normalform zu überprüfen. Sie weist einen Gesamtschlüssel auf (rechnungs-nr und artikel-nr). Die anzahl, der einzelpreis und der gesamtpreis sind sowohl von der rechnungsnummer als auch von der artikelnummer abhängig, brauchen folglich beide Attribute zur eindeutigen Identifikation, da der Kunde bei Bestellungen einerseits unterschiedliche Mengen eines Artikels bestellen kann, andererseits unterschiedliche Preise (z.B. aufgrund von Preiserhöhungen) für den gleichen Artikel in Rechnung gestellt bekommen kann.
Die artikelbezeichnung ist allerdings nur von der Artikelnummer abhängig. Sie ändert sich nur, wenn die Artikelnummer geändert wird. Wird der Gesamtschlüssel geändert, ändert sie sich nicht zwangsläufig. Damit ist sie nicht voll funktional abhängig vom Gesamtschlüssel, weil für die eindeutige Identifikation mit der Artikelnummer nur ein Teil dessen notwendig ist.
Um nun die Tabelle tbl_rechnungsposition in die zweite Normalform zu bringen, muss eine weitere Tabelle tbl_artikeleingeführt werden. In der Tabelle tbl_artikel ist die artikel_id Primärschlüssel. In diese Tabelle wird auch die artikelbezeichnung aufgenommen.
Die Datenbank des Möbelherstellers für die Erstellung der Rechnungen hat in der zweiten Normalform folgendes Aussehen:

Die Datenbank ist jetzt auch in der zweiten Normalform, da sie sich in der ersten Normalform befindet und jedes Nichtschlüsselattribut vom Gesamtschlüssel und nicht nur von einem Teil des Gesamtschlüssels funktional abhängig ist.
Trotzdem ist die Datenbank vor Inkonsistenzen noch nicht vollkommen geschützt. Dies soll mit Einhaltung der dritten Normalform erreicht bzw. verhindert werden:
Dritte Normalform
Eine Tabelle entspricht der dritten Normalform, wenn sie folgende Bedingungen erfüllt:
- Die Tabelle ist in der zweiten Normalform.
- Es dürfen keine funktionalen Abhängigkeiten zwischen Nichtschlüsselattributen existieren, d.h. Merkmale, die in keinem direkten Bezug zum Primärschlüssel stehen, sollten in einer eigenen Tabelle gespeichert werden oder, wenn es sich um berechenbare Daten handelt, gar nicht in die Datenbasis aufgenommen werden.
In unserem Beispiel des Möbelherstellers stellen wir fest, dass folgende Abhängigkeiten zwischen Nichtschlüsselattributen bestehen:
Die Eigenschaften kundenfirma, straße, hausnummer, plz und ort sind nicht vom Primärschlüssel rechnungs-id, sondern von der kundennummer abhängig. Daher muss eine weitere Tabelle tbl_kunde erstellt werden. Darin werden diese Attribute aufgenommen. Die kundennummer wird Primärschlüssel, der dann als kunden-id bezeichnet wird. Verknüpft wird die Tabelle tbl_kunde mit der Tabelle tbl_rechnung über die Attribute kunden_id und kunden_nr.
Weiterhin ist der ort vom Nichtschlüsselattribut plz abhängig. Aus diesem Grund ist eine eigene Tabelle tbl_plzanzulegen. Darin bildet die plz_id den Primärschlüssel, der mit plz-nr als Fremdschlüssel in der Tabelle tbl_kundeverbunden wird.
Die Attribute umsatzsteuer und summe brutto sind abhängig vom Nichtschlüsselattribut summe netto. Da sie mit Hilfe der summe netto berechnet werden können, sind sie aus dem Datenmodell zu entfernen.
Gleiches gilt für den gesamtpreis der Tabelle tbl_echnungsposition: Dieses Merkmal ist abhängig von den Nichtschlüsselattributen anzahl und einzelpreis und durch diese berechenbar.
Die summe netto ist zwar nicht von anderen Nichtschlüsselattributen der Tabelle tbl_rechnung abhängig; es empfiehlt sich aber dennoch, dieses Merkmal zu löschen, da es sich mit Hilfe der Attribute aus der Tabelle tbl_rechnungspositionberechnen lässt. Diese Berechnungen lassen sich leicht und gezielt mit Hilfe von Abfragen durchführen, welche wir später kennen lernen werden.
Die Datenbank des Möbelherstellers für die Erstellung der Rechnungen hat in der dritten Normalform folgendes Aussehen:

Die Datenbank des Möbelherstellers in der dritten Normalform
Die Datenbank ist in der dritten Normalform, da sie sich in der ersten und zweiten Normalform befindet und jedes Nichtschlüsselattribut direkt funktional abhängig vom Primärschlüssel ist, also keine Abhängigkeiten mehr zwischen den Nichtschlüsselattributen bestehen. Außerdem wurden alle berechenbaren Felder eliminiert.
Gemäß unseren Erkenntnissen aus der Normalisierung müssen wir unsere Datenbank „Schule“ noch abändern, indem wir der Datenbank noch die Tabellen tbl_plz und tbl_ort sowie in den Tabellen tbl_schüler und tbl_lehrer die Attribute plz und ort durch das Attribut plz_nr ersetzen. Das Ergebnis sehen wir uns im nächsten Kapitel an.