Sql-und-Xml - Home

Sql-Tutorial

Dritte Normalform - ein Nicht-Schlüssel-Attribut darf nicht von einem Schlüssel und einem anderen Nicht-Schlüssel abhängen

Die dritte Normalform (NF3) verlangt, daß bei allen in der Datenbank definierten Tabellen, die bereits in der zweiten Normalform sind, kein Attribut C existiert, das bereits funktional von einem Nicht-Schlüssel-Attribut B abhängt. Denn da das Attribut C zur Tabelle gehört, sollte es vom Primärschlüssel A dieser Tabelle voll funktional abhängig sein. A umfaßt nur ein Attribut, da die Tabelle bereits in der zweiten Normalform ist. Ist C jedoch zusätzlich vom Nicht-Schlüssel-Attribut B abhängig und ist das Nicht-Schlüssel-Attribut vom Primärschlüssel A abhängig, so ist die Folgerung A -> C zwingend. Das transitiv abhängige Attribut C und das Attribut B bilden eine neue, bislang noch nicht in einer eigenen Tabelle isolierte Relation. Diese kann aus der aktuellen Tabelle herausgezogen werden, in die aktuelle Tabelle wird nur noch Attribut B bzw. der Primärschlüssel der neu gebildeten Tabelle eingetragen.

Der Unterschied zur vollen funktionalen Abhängigkeit der zweiten Normalform besteht darin, daß es sich hier um eine zusätzliche Beziehung zwischen zwei Nicht-Schlüssel-Attributen handelt. Die Frage nach der zweiten Normalform lautet dagegen, ob ein Nicht-Schlüssel-Attribut vom gesamten Schlüssel oder nur von einem Teilschlüssel abhängt. Falls letzteres der Fall ist, wird das Attribut in eine bereits vorhandene Tabelle, in welcher der Teilschlüssel der Primärschlüssel ist, verschoben.

Betrachten Sie den folgenden Ausschnitt aus dem ursprünglichen Beispiel 2:

lfNrLiefer-NrDatumArtikel (E)LieferantEPZahlArtikel (V)EmpfängerEPZahl
12415.2.2003Hosen, blauFA Muster-Liefer GbR, Nürnberg39.9050
22415.2.2003Hose, braunFA Muster-Liefer GbR, Nürnberg39.9050

Zunächst ist offensichtlich, daß der Lieferant herausgezogen und die Adresse aufgesplittet wird. In die aktuelle Tabelle wird lediglich die Lieferanten-Nummer eingetragen. Dann können Artikel-Namen und Farbbezeichnungen in schmale, zweispaltige Tabellen bestehend aus Id und Begriff, ausgelagert werden. Dies erlaubt es, für die Eingabe Pulldown-Felder zu nutzen und vermeidet Fehler aufgrund von Rechtschreib-Problemen bei der Texteingabe. Die Tabelle sieht wie folgt aus:

lfNrLiefer-NrDatumArtikel-NrFarb-IdLieferanten-IdEPZahl

Es fällt auf, daß eine Lieferung, durchgeführt an einem Tag, aus mehreren Artikeln bestehen kann, so daß mehrere Zeilen dieselbe Liefer-Nummer und dasselbe Datum enthalten sowie sich auf einen Lieferanten beziehen. Besteht jede Lieferung nur aus einem Artikel, so ist die Spalte Liefer-Nr überflüssig und könnte entfernt bzw. durch 'lfNr' ersetzt werden. Besteht eine Lieferung aus mehreren Artikeln, so sind Datum und Lieferanten-Nummer abhängig von der Liefer-Nummer. Der Artikel, sein Einkaufspreis und die Artikel-Anzahl hängen jedoch nur vom Primärschlüssel dieser Zeile ab und unterscheidet sich von anderen Zeilen, die zu derselben Lieferung gehören. Also kann eine Tabelle gebildet werden, welche die Grunddaten jeder Lieferung enthält. Eine auf dieser basierende Detailtabelle 'Lieferdetails' beinhaltet pro Zeile eine Kombination aus Artikel, Farbe und Preis. Damit ergibt sich für die Lieferungen die folgende Aufteilung:

Tabelle tbl_Lieferungen:

Liefer-NrDatumLieferanten-Id

Tabelle tbl_Lieferdetails:

lfNr-DetailsLiefer-NrArtikel-NrFarb-NrEPZahl

Die detaillierte Betrachtung einzelner Liefer-Details führt zum Sichtbar-Werden von Wiederholungen, so daß ein neues 'Objekt' 'Bestell-Rahmendaten', 'Grundtatsachen einer Lieferung' identifiziert und in eine eigene Tabelle ausgelagert wird. Beachten Sie, daß dies nur dann gilt, falls tatsächlich eine Lieferung aus mehreren Artikeln besteht. Selbstverständlich sind Szenarien denkbar, in welchen dies nicht gilt - dann ist eine solche zusätzliche, eingeschobene Tabelle redundant.

Ein Beispiel mit partieller Abhängigkeit

Betrachten Sie die folgende denormalisierte Tabelle:

DatumStrasseHausEtageWohnungZählerStandMitarbeiter

Ein Mitarbeiter eines Strom- oder Gaslieferanten liest diverse Strom- oder Gaszähler ab. Zur Straßen-Id gehören viele Häuser, zu jedem Haus mehrere Etagen, zu jeder Etage mehrere Wohnungen. In jeder Wohnung befindet sich ein Zähler mit einer eindeutigen Nummer. Dessen Stand wird zu einem festgelegten Datum turnusgemäß von verschiedenen Mitarbeitern abgelesen.

Jede Zeile kann eindeutig durch die beiden Spalten Datum und Zählernummer identifiziert werden. Denn jeder Zähler wird an einem Tag höchstens einmal abgelesen. Damit bilden diese beiden Spalten den zusammengesetzten Primärschlüssel. Die Mitarbeiter-Id hängt natürlich von diesem Geschäftsvorfall der Zähler-Ablesung ab. Die Straße ist ein nur vom Zähler, nicht vom Datum abhängiges Attribut. Denn von der Zählernummer ausgehend ist die Straße über die Wohnung, Etage und das Haus festgelegt. Zum Erreichen der zweiten Normalform werden deshalb Wohnung, Etage, Haus und Straße herausgezogen, all diese Werte sind durch die Zähler-Id festgelegt. Bei der zweiten Normalform ergibt sich damit die folgende Tabelle:

DatumZählerStandMitarbeiter

Werden in diese Tabelle viele Zeilen eingetragen, so wird eine zusätzliche Regelmäßigkeit sichtbar: Ein Mitarbeiter sammelt an einem Tag Informationen von allen Häusern einer Straße. Die Spalte Mitarbeiter ist also bereits determiniert durch die Kombination aus Datum und Hausnummer und wird bsp. im Rahmen einer Arbeitsverteilung in voraus festgelegt. Oder die Mitarbeiter sind von vornherein Ablesebereichen zugeteilt, so daß - unabhängig vom Datum - bekannt ist, welcher Mitarbeiter für die Ablesung innerhalb eines Intervalls zuständig ist. Im datumsfreien Fall gilt also die folgende transitive Abhängigkeit:

Zähler ―> Straße ―> Mitarbeiter

Hier kann das Attribut 'Mitarbeiter' zur Tabelle 'Straße' hinzugefügt und aus der aktuellen Tabelle entfernt werden. Für diese Straße ist jener Mitarbeiter zuständig. Bei der Version mit Datum gilt:

Zähler ―> Straße
Datum + Straße―> Mitarbeiter

Hier gibt es eine neue Tabelle mit Straßen-Id und Datum als Primärschlüssel sowie der Mitarbeiter-Id als Nicht-Schlüssel-Attribut. Die Straße darf nicht zur normalisierten Tabelle mit Datum, Zähler und Zählerstand hinzugenommen werden, weil sie vom Zähler voll funktional abhängig ist. Die restlichen Spalten werden gemäß der 1:n - Beziehung kanonisch normalisiert, so daß sich insgesamt die folgende Tabellenstruktur ergibt:

Strassen-IdOrtNameweitere für Straßen typische Eigenschaften

Haus-IdStrassen-IdHausnummerweitere für Häuser typische Eigenschaften

Etagen-IdHaus-IdEtagennummerweitere für Etagen typische Eigenschaften

Wohnungs-IdEtagen-IdHauptmieterweitere für Wohnungen typische Eigenschaften

Zähler-IdWohnungs-IdWerksnummer - 10-stellig mit Buchstabenweitere für Zähler typische Eigenschaften

Die neu identifizierte Tabelle mit Datum und Straßen-Id als Primärschlüssel:

DatumStraßen-IdMitarbeiter

Die Tabelle mit den eigentlichen Ablesedaten sieht nun wie folgt aus:

DatumZähler-IdZählerstandBemerkungen

Erläuterungen zum Verhältnis zwischen der zweiten und der dritten Normalform

Die Notwendigkeit der ersten Normalform dürfte den meisten Lesern unmittelbar einleuchten. Die Forderung nach dem Erfüllen der zweiten und der dritten Normalform bzw. nach dem Unterschied zwischen beiden Normalformen dürfte dagegen eher irritieren, da es sich hierbei um relativ stark mathematisch geprägte Konzepte handelt. Es folgen deshalb einige erläuternde Bemerkungen.
  • Die zweite Normalform verlangt, daß Attribute in den korrekten Tabellen untergebracht sind. Normalerweise lassen sich einige 'statische Entitäten' rasch identifizieren und in eigene Tabellen mit Primärschlüsseln exportieren. Dann kann es zusätzliche Bewegungsdaten geben, welche diese Grunddaten, oft zeitpunktgebunden, miteinander verknüpfen. Eine solche Tabelle enthält einige Fremdschlüssel auf die Grundtabellen sowie zusätzliche Spalten. Damit umfaßt ein Schlüssel-Kandidat mehrere Attribute. Bei den Nicht-Schlüssel-Attributen muß geprüft werden, ob sie tatsächlich zum aktuellen Geschäftsvorfall oder zu einer der Grundtabellen gehören, falls es sich um zeitlich unveränderliche Eigenschaften handelt. Ändern sie sich dagegen in größeren Abständen, so daß zu verschiedenen Geschäftsvorfällen derselbe Attributwert gehört, dieses jedoch nicht einer Grundtabelle zugewiesen werden kann, so ist das Attribut in eine eigene Tabelle herauszuziehen.
  • Die dritte Normalform entspricht im wesentlichen der Forderung, 'eigenständige Einheiten' korrekt zu identifizieren. Ist eine denormalisierte Tabelle mit Filmtiteln, Regisseuren und ihren Geburtsdaten gegeben, so ist offenkundig das Geburtsdatum nur vom Regiseur, nicht jedoch von dem Film abhängig, in welchem der Schauspieler mitwirkt. Die Personen werden mit dem Attribut 'Geburtsdatum' herausgezogen, in eine eigene Tabelle mit Primärschlüssel abgelegt und nur dieser in die Filmtabelle eingebunden.
  • Werden solche Tabellen, die gewisse 'Handelnde', 'eigenständige Objekte' oder 'Stammdaten' beschreiben, mit einem zusätzlichen Primärschlüssel als Autowert definiert, so sind diese Tabellen in der Regel bereits in der zweiten Normalform. Denn das 'eigenständige Objekt', das durch eine Zeile abgebildet ist, determiniert seine Attribute. Da der hinzugefügte Primärschlüssel aus einer Spalte besteht, kann keine echte Teilmenge des Primärschlüssels gebildet werden.
  • Zusammengefaßt: Die Attribute innerhalb einer Tabelle müssen durch den Primärschlüssel vollständig determiniert sowie voneinander unabhängig sein. Abhängigkeiten zwischen Attributen sind in eigene Tabellen zu isolieren.

© 2003-2016 Jürgen Auer, Berlin.