Motivation |
|
Stellen wir uns vor, in einer Relation zum Anwendungsbereich Projektmitarbeit (in einem Softwarehaus) geht es darum festzuhalten, mit welcher Programmiersprache jeder Mitarbeiter in einem bestimmten Projekt mitwirkt. In der zugehörigen Relation – nennen wir sie AngProjPS (Angestellte – Projekte – Programmiersprachen) könnten z.B. folgende Attribute und Tupel vorliegen: |
|
Relation AngProjPS |
|
PersNr |
BezProj |
BezPS |
1007 |
SocWeb |
XHTML |
1007 |
WebPl |
PHP |
1007 |
WebPl |
MySQL |
1008 |
WebPl |
PHP |
1008 |
WebPl |
MySQL |
1009 |
PPS |
Cpp |
1009 |
PPS |
Cpp |
1009 |
PPS |
C |
1010 |
PPS |
C |
1010 |
PPS |
Cpp |
1010 |
WebPl |
PHP |
1010 |
WebPl |
MySQL |
| |
Schlüssel: (PersNr, BezProj, BezPS) |
|
WebPl soll ein Projekt zur Erstellung einer neuen Webplattform für das Unternehmen sein. SocWeb eines zur Analyse von Daten im Social Web. PPS soll das (selbst programmierte) Produktionsplanungssystem des Unternehmens verbessern. |
|
Es soll nun aber nicht die übliche Semantik einer solchen Relation gelten, die einfach die Attribute in die üblichen Beziehungen (funktionale Abhängigkeiten) stellt, z.B.: |
|
- „1008“ arbeitet im Projekt WebPl mit und nutzt dort die Abfragesprache MySQL
|
|
Sondern es gilt eine vertiefte semantische Struktur, die an diesem Beispiel so beschrieben werden kann: |
Vertiefte Semantik |
- Falls die Angestellte 1007 im Projekt SocWeb mitarbeitet und falls im Projekt SocWeb XHTML benötigt wird, dann arbeitet 1007 mit XHTML in dem Projekt mit.
|
|
Für die Tupel bedeutet dies an obigem Beispiel: Falls |
|
- eine Person in einem Projekt mitwirkt,
- falls in diesem Projekt eine bestimmte Programmiersprache benötigt wird
- und falls die Person diese Programmiersprache beherrscht,
- dann wirkt diese Person mit dieser Programmiersprache in diesem Projekt mit.
|
|
Es werden hier also Projektmitarbeit, Programmiersprachenkompetenz und Programmierspracheneinsatz in Projekten miteinander verknüpft. |
|
Ansonsten verstößt diese Relation gegen keine der uns bisher bekannten Normalformen: |
|
- Funktionale Abhängigkeiten liegen nicht vor, auch nicht bei Schlüsselattributen (BCNF). Die einzelnen Attribute sind unabhängig voneinander.
- Alle drei Attribute zusammen sind Schlüssel.
- Es liegen keine mehrwertigen Abhänfigkeiten vor (4NF).
- Es liegt kein Verstoß gegen die ersten vier Normalformen vor.
|
|
Trotzdem wäre eine solche Relation nur schwer zu pflegen, weil die beschriebene komplexe Semantik beim Löschen, Einfügen und Aktualisieren ja erhalten bleiben müsste. |
|
Wie meist beim Optimieren von Relationen könnte die Lösung darin liegen, eine solche Relation ohne Semantikverluste zu zerlegen. Wie dies in diesem Fall geht, zeigen die Ausführungen in diesem Kapitel. |
|
Vorbemerkung |
|
Bevor die abschließende fünfte Normalform (5NF) besprochen werden kann, werden die beiden Techniken Verbund und Projektion benötigt. Diese beschreiben zwei sog. Relationale Operatoren (oder Operationen). |
|
Hier wird, zur Darstellung von Verbund (Join) und Projektion, mit SQL gearbeitet. Es wäre daher sinnvoll, zuerst Kapitel 19 mit einer Einführung in SQL zu lesen, insbesondere die Abschnitte 19.5 und 19.8. |
|
|
|
13.1 Verbund (Join) und Projektion |
|
13.1.1 Verbund (Join) |
|
Vgl. auch Abschnitt 19.8 |
|
Ein Verbund (Join) zweier Relationen ist die relationale Verknüpfung auf der Basis der Ausprägungen zweier Attribute (meist Schlüssel / Fremdschlüssel). Dabei werden die Tupel einer Relation A (mit Verknüpfungsattribt a1) mit denen einer Relation B (Verknüpfungsattribut b1) zu neuen Tupeln zusammengefügt, falls sich in a1 und b1 identische Attributsausprägungen finden. Meist ist a1 ein Schlüssel und b1 ein Fremdschlüssel, dann muss sich also zu einer Schlüsselausprägung eine übereinstimmende Fremdschlüsselausprägung finden, damit die Tupel verknüpft werden. Falls sich zu einer Schlüsselausprägung mehrere Fremdschlüsselausprägungen finden, entstehen mehrere verknüpfte Tupel. |
|
Beispiel |
|
Im folgenden Beispiel gehe es in Ang um die Angestellten und in Abt um die Abteilungen eines Unternehmens. |
|
Relation Ang |
|
PersNr |
Name |
Vname |
AbtBez |
1030 |
May |
Karl |
IT |
1005 |
Sommer |
Lisa |
PW |
1040 |
Winter |
Angelika |
IT |
1090 |
Stepper |
Rolf |
PW |
1008 |
Rülp |
Fred |
VB |
1009 |
Baum |
Ottilie |
FE |
1017 |
Czerny |
Rudi |
CO |
| |
|
|
Relation Abt |
|
AbtBez |
AbtLeiter |
Standort |
PW |
Sommer |
Hamburg |
RE |
Müller |
Passau |
VB |
Rülp |
Ulm |
CO |
Czerny |
Ulm |
LA |
Dorr |
Hamburg |
| |
PW=Personalwesen, IT=Datenverarbeitung, RE=Rechnungswesen, VB=Vertrieb CO Controlling, LA Lager |
|
Ein Verbund dieser zwei Relationen kann über über die Abteilungsbezeichnung (AbtBez) durchgeführt werden. Dieses Attribut ist Schlüssel in Abt und Fremdschlüssel in Ang. Mit dem folgenden VERBUND-Befehl (mit MySQL, vgl. Kapitel 19) werden nun alle Tupel aus Ang nacheinander abgeglichen mit den Tupeln der Relation Abt. Tritt in Abt dieselbe Ausprägung in AbtBez auf, wird ein neues zusammengesetztes Tupel aus allen oder ausgewählten Attributen beider Relationen gebildet. Die neuen Tupel werden zu einer Ergebnisrelation zusammengefasst.
|
Verbund (Join) |
Vgl. Abschnitt 5.7 für eine vertiefte Darstellung. |
|
Der SQL-Befehl ist wie folgt: |
|
Select a.PersNr, a.Name, a.VName, a.AbtBez,
|
|
b.AbtBez, b.AbtLeiter, b.Standort
|
|
from ang a, abt b
|
|
where a.AbtBez=b.AbtBez
|
|
Das Ergebnis des Verbunds: |
|
|
|
PersNr |
Name |
VName |
AbtBez |
AbtBez |
AbtLeiter |
Standort |
1005 |
Sommer |
Lisa |
PW |
PW |
Sommer |
Hamburg |
1090 |
Stepper |
Rolf |
PW |
PW |
Sommer |
Hamburg |
1008 |
Rülp |
Fred |
VB |
VB |
Rülp |
Ulm |
1017 |
Czerny |
Rudi |
CO |
CO |
Czerny |
Ulm |
| |
Das erste Attribut AbtBez stammt aus der Relation Ang, das zweite aus Abt.
|
|
Das Ergebnis der Abfrage ist nur für die Ausgabe und für eine eventuelle Weiterverarbeitung (z.B. in einem Reportgenerator oder einer Maske der Bedienoberfläche) vorhanden, es wird nicht dauerhaft (persistent) gespeichrt. Es enthält die verknüpften Daten mit den Redundanzen im Bereich der Abteilungsinformation und ist nur in 2NF. |
Temporäre Ausgaberelation |
Wie in Abschnitt 5.9 dargelegt, fordert die referentielle Integrität, dass es keinen Fremdschlüsseleintrag geben darf, den es im zugehörigen Schlüssel nicht gibt. Dies ist hier nicht gegeben: |
Referentielle Integrität |
Für die Abteilungsbezeichnung IT in Ang (Fremdschlüssel!) gibt es keine Entsprechung in Abt.AbtBez. Ebenso für FE. Umgekehrt: Der Schlüsselwert RE in Abt hat keine Entsprechung in den Fremdschlüsseln Ang.AbtBez. Ebenso LA. Es bleiben also nur die Ausprägungen PW, VB und CO, die in beiden Relationen vorkommen, so dass es auch nur für diese verknüpfte Tupel gib. |
|
Diese Operation Verbund (Join) wird in SQL ständig benötigt, da sie temporär Relationen wieder zusammenfügt, die vielleicht vorher im Rahmen der Normalisierung getrennt wurden. |
|
Vgl. für eine Einführung in SQL Kapitel 19, zum Join Abschnitt 19.8. |
|
13.1.2 Projektion |
|
Die relationale Operation Projektion besteht darin, bestimmte Attribute (Spalten) einer Relation zu streichen, so dass als Ergebnis eine "schlankere" Relation entsteht. Sollten dabei gleiche Tupel entstehen, werden diese gestrichen. |
|
Betrachten wir als erstes Beispiel wiederum eine Relation zu den Angestellten eines Unternehmens (Ang). Neben dem Namen enthält sie auch noch die Bezeichnung der Abteilung, in der der Angestellte arbeitet (AbtBez). |
Beispiel Angestellte |
Ang |
|
PersNr |
Name |
VName |
AbtBez |
1030 |
May |
Karl |
IT |
1005 |
Sommer |
Lisa |
PW |
1040 |
Winter |
Angelika |
IT |
1090 |
Stepper |
Rolf |
PW |
1008 |
Rülp |
Fred |
VB |
1009 |
Baum |
Ottilie |
FE |
1017 |
Czerny |
Rudi |
CO |
| |
Eine Projektion könnte darin bestehen, nur die Attribute Name und VName auszuwählen:
|
|
select Name, VName from Ang;
|
|
Projektion 1 auf Ang |
|
Name |
VName |
May |
Karl |
Sommer |
Lisa |
Winter |
Angelika |
Stepper |
Rolf |
Rülp |
Fred |
Baum |
Ottilie |
Czerny |
Rudi |
| |
Eine andere könnte für irgendeinen Zweck nur die Abteilungszugehörigkeit auswählen:
|
|
select PersNr, AbtBez from Ang;
|
|
Projektion 2 auf Ang |
|
PersNr |
AbtBez |
1030 |
IT |
1005 |
PW |
1040 |
IT |
1090 |
PW |
1008 |
VB |
1009 |
FE |
1017 |
CO |
| |
Oftmals ergeben sich bei Projektionen identische Tupel. Diese sind in Relationen sinnlos und nicht vorgesehen. Das folgende Beispiel einer Relation zur Thematik …
|
|
Angestellte - Projekte - Funktionen |
|
… möge dies verdeutlichen. Die Relation hält fest, wer in welchem Projekt mit welcher Funktion mitarbeitet. Es liegt eine n:m-Beziehung vor: Ein Angestellter kann in mehreren Projekten mitarbeiten, zu einem Projekt gehören typischerweise mehrere Angestellte. |
|
AngProjFu |
|
Name |
Projekt |
Funktion |
Bauer |
A |
Leitung |
Bauer |
B |
Controller |
Dürr |
D |
Leitung |
Hasslo |
A |
Entwickler |
Hasslo |
D |
Entwickler |
May |
C |
Leitung |
Müller |
A |
IT |
Müller |
B |
Leitung |
Müller |
C |
IT |
Müller |
D |
Finanzen |
| |
Schlüssel: #(Name, Projekt)) |
|
Eine Projektion könnte darin bestehen, die Attribute Name und Funktion auszuwählen, um festzustellen, welche Funktionen die einzelnen Personen in Projekten übernehmen. Dann ergibt sich, sortiert nach Name und Funktion sowie vor der Löschung der identischen Tupel, folgende Relation:
|
Projektion 1 auf AngFu |
AngFu_redundant |
|
Name |
Funktion |
Bauer |
Controller |
Bauer |
Leitung |
Dürr |
Leitung |
Hasslo |
Entwickler |
Hasslo |
Entwickler |
May |
Leitung |
Müller |
Finanzen |
Müller |
IT |
Müller |
IT |
Müller |
Leitung |
| |
Schlüssel: #(Name, Funktion)) |
|
Die redundanten Tupel sind durchgestrichen. |
|
Werden die identischen Tupel gelöscht (identische Tupel gibt es in Relationen nicht!) entsteht AngFu_ohne Redundanz. |
|
AngFu_ohne Redundanz |
|
Name |
Funktion |
Bauer |
Controller |
Bauer |
Leitung |
Dürr |
Leitung |
Hasslo |
Entwickler |
May |
Leitung |
Müller |
Finanzen |
Müller |
IT |
Müller |
Leitung |
| |
Schlüssel: #(Name, Funktion)) |
|
Soweit die benötigten Grundlagen für die 5NF.
|
|
13.2 N-Zerlegbarkeit |
|
Kommen wir zurück zu der Relation AngProjPS aus dem Motivationsabschnitt: |
|
Relation AngProjPS |
|
PersNr |
BezProj |
BezPS |
1007 |
SocWeb |
XHTML |
1007 |
WebPl |
PHP |
1007 |
WebPl |
MySQL |
1008 |
WebPl |
PHP |
1008 |
WebPl |
MySQL |
1009 |
PPS |
Cpp |
1009 |
PPS |
Cpp |
1009 |
PPS |
C |
1010 |
PPS |
C |
1010 |
PPS |
Cpp |
1010 |
WebPl |
PHP |
1010 |
WebPl |
MySQL |
| |
Schlüssel: (PersNr, BezProj, BezPS) |
|
WebPl soll ein Projekt zur Erstellung einer neuen Webplattform für das Unternehmen sein. SocWeb eines zur Analyse von Daten im Social Web. PPS soll das (selbst programmierte) Produktionsplanungssystem des Unternehmens verbessern. |
|
Sie hat, wie oben ausgeführt, nicht die „übliche“ Semantik eines solchen Tupels, sondern eine vertiefte, die alle drei Attribute in Beziehung setzt: |
|
Falls eine Person in einem Projekt mitarbeitet, falls dort eine bestimmte Programmiersprache benötigt wird und die Person diese Programmiersprache beherrscht, dann arbeitet sie mit dieser Programmiersprache in diesem Projekt mit. |
|
In obigem Beispiel: |
|
Falls die Angestellte 1007 im Projekt SocWeb mitarbeitet und falls im Projekt SocWeb XHTML benötigt wird, dann arbeitet 1007 mit XHTML in dem Projekt mit. |
|
Für die Tupel bedeutet dies zum Beispiel: |
|
Mit den zwei Einträgen „1007 / WebPl“ (interpretiert als „1007 arbeitet im Projekt WebPl mit“) und „WebPl / MySQL“ (interpretiert als „in WebPl wird MySQL benötigt“) muss also auch „1007 / MySQL“ (interpretiert als „1007 beherrscht MySQL“) im Tupel vorhanden sein. |
|
Eine solche Relation wäre nur schwer zu pflegen, weil die beschriebene komplexe Semantik beim Löschen, Einfügen und Aktualisieren ja erhalten bleiben müsste. Entdeckt wurde dieses Strukturmerkmal von Relationen durch [Aho, Beeri und Ullman 1979], zitiert nach [Date, Kannan und Swamynathan 2006, S. 320]. |
|
Sie erfüllt die ersten vier Normalformen. Die dort jeweils angeführten Defizite liegen nicht vor. Trotzdem weist sie das beschriebene Defizit aus. Bleibt nur die Zerlegung, um eine Relationenstruktur zu schaffen, die gepflegt werden kann. |
|
Die übliche Vorgehensweise wäre eine Zerlegung in zwei Relationen. Dies klappt hier aber nicht. Dabei geht der semantische Bezug über die drei Attribute hinweg verloren. Bleibt nur die Zerlegung in mehr als zwei Relationen mit dem Join als Werkzeug, um die zerlegten Relationen wieder zusammenzuführen. |
|
Dies wurde in den einschlägigen Tagungen erarbeitet und führte zur Definition der n-Zerlegbarkeit: |
|
Eine Relation heißt n-zerlegbar, falls sie ohne Informationsverlust in n Relationen zerlegt werden kann, nicht aber in m (m < n). |
Definition:
n-Zerlegbarkeit |
Das Phänomen der n-Zerlegbarkeit bezieht sich also auf Beziehungen, die über mehr als zwei Attribute greifen. |
|
Wann kommt es zu einer solchen - zugegeben etwas konstruierten - Situation? Sie liegt genau dann vor, wenn die Relation dem Verbund von einigen ihrer Projektionen entspricht bzw. wenn ihre Entstehung so gedacht werden kann. |
|
Dies führte zur Definition der Verbundabhängigkeit, für die die beiden oben eingeführten Techniken (Verbund (Join) und Projektion) benötigt werden: |
|
Seien T die Menge der Attribute einer Relation R und AK1, AK2, AKn Teilmengen von T. R ist verbund-abhängig, in Zeichen |
Definition: Verbundabhängigkeit |
* (AK1, AK2, ..., AKn) |
|
falls R gleich dem Verbund seiner Projektionen auf AK1, AK2, ..., AKn ist. |
|
Damit kann dann die fünfte Normalform (5NF) definiert werden: |
|
Definition: 5NF |
|
Sei R eine Relation. R ist in der 5NF, falls jede Verbund-Abhängigkeit in R durch Schlüssel von R verursacht wird. |
|
Zur Abklärung der 5NF muss also erst mal geklärt werden, ob eine Verbundabhängigkeit, wie oben beschrieben, vorliegt. Dann muss geklärt werden, ob diese durch die Schlüssel verursacht ist. |
|
Verbund über Schlüssel, 5NF erfüllt: |
Beispiel |
Wir nutzen wieder die Relationen AngProj und AngPS sowie eine weitere, AngAbt, die auch den Schlüssel PersNr hat (damit der Verbund über den Schlüssel gehen kann). AngAbt (Angestellte / Abteilungen) erfasst die Abteilungszugehörigkeit: |
|
select* from angabt;
|
|
PersNr |
BezAbt |
1007 |
IT |
1008 |
Personalwesen |
1009 |
Entwicklung |
1010 |
Entwicklung |
1011 |
Produktion |
1012 |
Personalwesen |
1013 |
Prozessmanagement |
1014 |
Prozessmanagement |
| |
Führen wir nun einen Join durch, mit dem Ziel den Zusammenhang zwischen Personen, ihren Abteilungen und beherrschten Programmmiersprachen zu erfassen:
|
|
select a.PersNr, a.BezAbt, b.BezProj, c.BezPS
|
|
from AngAbt a, AngProj b, AngPS C
|
|
where a.PersNr=b.PersNr
|
|
and b.PersNr=c.PersNr;
|
|
PersNr |
BezAbt |
BezProj |
BezPS |
1007 |
IT |
WebPl |
PHP |
1007 |
IT |
SocWeb |
PHP |
1007 |
IT |
WebPl |
MySQL |
1007 |
IT |
SocWeb |
MySQL |
1008 |
Personalwesen |
WebPl |
XHTML |
1008 |
Personalwesen |
WebPl |
PHP |
1009 |
Entwicklung |
PPS |
C |
1009 |
Entwicklung |
PPS |
JavaScr |
1010 |
Entwicklung |
PPS |
Cpp |
1010 |
Entwicklung |
WebPl |
Cpp |
1010 |
Entwicklung |
PPS |
HTML 5 |
1010 |
Entwicklung |
WebPl |
HTML 5 |
1010 |
Entwicklung |
PPS |
Fortran |
1010 |
Entwicklung |
WebPl |
Fortran |
| |
Dieser Verbund wurde mit einem Schlüssel durchgeführt und führt zu einem fehlerfreien Ergebnis, da jedem Schlüsselwert der einen ein Schlüsselwert der anderen entspricht. In die Ergebnisrelation kommen auf diese Weise auch nur die Tupel der verschiedenen Relationen, die einen gemeinsamen Schlüssel haben.
|
Verbund mit Schlüsseln |
Das Beispiel macht auch deutlich, dass die Verbundabhängigkeit die ganz normale funktionale Abhängigkeit mitumfasst. Denn wenn der jeweilige Schlüssel ein solcher ist, liegen funktionale Abhängigkeiten zwischen ihm und den NSA vor. Erfolgt der Verbund über Schlüssel, werden demzufolge Attribute zusammengeführt, die von demselben Schlüssel funktional abhängig sind. |
|
Wie leicht gezeigt werden kann gilt damit: Jede Relation in 5NF ist auch in 4NF. Denn wenn die Relation aus einem Verbund mit Hilfe von Schlüsseln entstanden ist, können keine mehrwertigen Abhängigkeiten vorliegen. |
5NF umfasst 4NF |
Nun ein Verbund, der nicht mit Schlüsseln realisert wird, sondern mit Teilen von Schlüsseln (Schlüsselattributen). |
|
„Nicht-Schlüssel-Verbund“ |
|
Nun ein Verbund, der nicht mit Schlüsseln realisiert wird, sondern mit Teilen von Schlüsseln (Schlüsselattributen). |
|
Zur Veranschaulichung betrachten wir nochmals das Beispiel AngProjPS, jetzt ausgehend von einzelnen Relationen, deren Join zu AngProjPS geführt haben könnte. |
Beispiel AngProjPS |
Die Relationen AngProj (Angestellte, Projekte), ProjPS (Projekte, Programmiersprachen) und AngPS erfassen jeweils Aspekte der Tätigkeiten von Angestellten in Unternehmen: |
|
- AngProj: Wer arbeitet in welchem Projekt mit?
- ProjPS: Welche Programmiersprachen werden in welchen Projekten genutzt?
- AngPS: Wer beherrscht welche Programmiersprachen
|
|
Sie verbinden jeweils zwei voneinander unabhängige Aspekte dieses Anwendungsbereichs, weshalb sie alle einen zusammengesetzten Schlüssel haben. Hier zur Veranschaulichung einige Beispieldaten. |
|
Wer arbeitet in welchem Projekt mit: |
|
Relation AngProj |
|
PersNr |
BezProj |
1007 |
WebPl |
1007 |
SocWeb |
1008 |
WebPl |
1009 |
PPS |
1010 |
PPS |
1010 |
WebPl |
| |
Schlüssel #(PersNr, BezProj) |
|
|
|
Wieder gilt: |
|
WebPl soll ein Projekt zur Erstellung einer neuen Webplattform für das Unternehmen sein. SocWeb eines zur Analyse von Daten im Social Web. PPS soll das (selbst programmierte) Produktionsplanungssystem des Unternehmens verbessern. |
|
Zum Nachvollziehen, zum Beispiel mit MySQL (vgl. Kapitel 19): |
|
Create table AngProj (PersNr int(4), BezProj char(6)); |
|
Insert into AngProj values |
|
(1007, 'WebPl'), |
|
(1007, 'SocWeb'), |
|
(1008, 'WebPl'), |
|
(1009, 'PPS'), |
|
(1010, 'PPS'), |
|
(1010, 'WebPl'); |
|
In Projekten benötigte Programmiersprachen: |
|
Relation ProjPS |
|
BezProj |
BezPS |
WebPl |
PHP |
WebPl |
C# |
WebPl |
CSS |
SocWeb |
HTML5 |
SocWeb |
Python |
SocWeb |
XHTML |
WebPl |
MySQL |
PPS |
C |
PPS |
Cpp |
| |
Schlüssel #(BezProj, BezPS) |
|
|
|
Zum Nachvollziehen: |
|
Create table ProjPS (BezProj char(6), BezPS char(6)); |
|
Insert into ProjPS values |
|
('WebPl' ,'PHP'), |
|
('WebPl', 'C#'), |
|
('WebPl', 'CSS'), |
|
('SocWeb', 'HTML5'), |
|
('SocWeb', 'Python'), |
|
('SocWeb', 'XHTML'), |
|
('WebPl', 'MySQL'), |
|
('PPS', 'C'), |
|
('PPS', 'Cpp'); |
|
Programmiersprachen, die Angestellte beherrschen: |
|
Relation AngPS |
|
PersNr |
BezPS |
1007 |
PHP |
1007 |
MySQL |
1008 |
XHTML |
1009 |
C |
1009 |
JavaScr |
1010 |
Cpp |
1010 |
HTML 5 |
1010 |
Fortran |
1011 |
Cpp |
| |
Schlüssel #(PersNr, BezPS) |
|
|
|
Zum Nachvollziehen: |
|
Create table AngPS (PersNr int(4), BezPS char(7)); |
|
Insert into AngPS values |
|
(1007 ,'PHP'), |
|
(1007, 'MySQL'), |
|
(1008, 'XHTML'), |
|
(1009, 'C'), |
|
(1009, 'JavaScript'), |
|
(1010, 'Cpp'), |
|
(1010, 'HTML 5'), |
|
(1010, 'Fortran'), |
|
(1011, 'Cpp'); |
|
Nun der Verbund |
|
Ein Verbund ist hier nur über Nichtschlüsselattribute (NSAs) möglich. Zuerst für zwei Attribute, mit denen die Projektmitarbeit und die Programmiersprachenkompetenz einer jeden Person zusammengeführt werden: |
|
select *
|
|
from AngProj a, AngPS c
|
|
where a.PersNr = c.PersNr
|
|
order by a.PersNr, a.BezProj, c.BezPS
|
|
PersNr |
BezProj |
PersNr |
BezPS |
1007 |
SocWeb |
1007 |
MySQL |
1007 |
SocWeb |
1007 |
PHP |
1007 |
WebPl |
1007 |
MySQL |
1007 |
WebPl |
1007 |
PHP |
1008 |
WebPl |
1008 |
PHP |
1008 |
WebPl |
1008 |
XHTML |
1009 |
PPS |
1009 |
C |
1009 |
PPS |
1009 |
JavaScr |
1010 |
PPS |
1010 |
Cpp |
1010 |
PPS |
1010 |
Fortran |
1010 |
PPS |
1010 |
HTML 5 |
1010 |
WebPl |
1010 |
Cpp |
1010 |
WebPl |
1010 |
Fortran |
1010 |
WebPl |
1010 |
HTML 5 |
| |
Es werden in diesem Beispiel bewusst alle Attribute ausgegeben, um die Verknüpfung und Einschränkungen zu verdeutlichen. Dabei wird auch deutlich, dass – wenn wir uns die doppelte Personalnummer wegdenken – eine optimale Struktur vorliegt. Beide, BezProj und BezPS sind funktional abhängig von PersNr.
|
|
Nun der erste Ausbau des Verbunds durch Hinzunahme der Einschränkung auf die Tupel, bei denen die Programmiersprache der Person identisch ist mit der benötigten Programmiersprache im Projekt. |
|
select *
|
|
from AngProj a, ProjPS b, AngPS c
|
|
where a.PersNr = c.PersNr
|
|
AND b.BezPS = c.BezPS
|
|
order by a.PersNr, a.BezProj, c.BezPS
|
|
PersNr |
BezProj |
BezProj |
BezPS |
PersNr |
BezPS |
1007 |
SocWeb |
WebPl |
MySQL |
1007 |
MySQL |
1007 |
SocWeb |
WebPl |
PHP |
1007 |
PHP |
1007 |
WebPl |
WebPl |
MySQL |
1007 |
MySQL |
1007 |
WebPl |
WebPl |
PHP |
1007 |
PHP |
1008 |
WebPl |
WebPl |
PHP |
1008 |
PHP |
1008 |
WebPl |
SocWeb |
XHTML |
1008 |
XHTML |
1009 |
PPS |
PPS |
C |
1009 |
C |
1010 |
PPS |
PPS |
Cpp |
1010 |
Cpp |
1010 |
WebPl |
PPS |
Cpp |
1010 |
Cpp |
| |
Der zweite Ausbau des Verbunds bringt eine weitere semantische Einschränkung auf die Tupel, bei denen das bei AngProj (Projektmitarbeit) genannte Projekt gleich dem ist, welches in ProjPS genannt wird:
|
|
select *
|
|
from AngProj a, ProjPS b, AngPS c
|
|
where a.PersNr = c.PersNr
|
|
AND b.BezPS = c.BezPS
|
|
AND a.BezProj = b.BezProj
|
|
order by a.PersNr, a.BezProj, c.BezPS
|
|
PersNr |
BezProj |
BezProj |
BezPS |
PersNr |
BezPS |
1007 |
WebPl |
WebPl |
MySQL |
1007 |
MySQL |
1007 |
WebPl |
WebPl |
PHP |
1007 |
PHP |
1008 |
WebPl |
WebPl |
PHP |
1008 |
PHP |
1009 |
PPS |
PPS |
C |
1009 |
C |
1010 |
PPS |
PPS |
Cpp |
1010 |
Cpp |
| |
Hier mit Unterdrückung identischer Attribute:
|
|
select a.PersNr, a.BezProj, c.BezPS
|
|
from AngProj a, ProjPS b, AngPS c
|
|
where a.PersNr = c.PersNr
|
|
AND b.BezPS = c.BezPS
|
|
AND a.BezProj = b.BezProj
|
|
order by a.PersNr, a.BezProj, c.BezPS
|
|
PersNr |
BezProj |
BezPS |
1007 |
WebPl |
MySQL |
1007 |
WebPl |
PHP |
1008 |
WebPl |
PHP |
1009 |
PPS |
C |
1010 |
PPS |
Cpp |
| |
Insgesamt tragen die Tupel nun folgende Semantik:
|
|
Falls eine Person in einem Projekt mitwirkt, falls dort eine bestimmte Progammiersprache benötigt wird und falls die Person diese Programmiersprache beherrscht, dann wirkt sie auch mit dieser Programmiersprache in diesem Projekt mit. |
|
Betrachten wir den Befehl nochmal detailliert: |
|
select a.PersNr, b.BezProj, c.BezPS
|
|
from AngProj a, ProjPS b, AngPS c
|
|
where a.PersNr = c.PersNr |
|
Damit wird jede Personalnummer von a mit der identischen von c zusammengefügt. Da beide Mehrfacheinträge haben, gibt es viele gleiche Tupel. |
|
AND b.BezPS = c.BezPS |
|
Dies führt zu einer Einschränkung bzgl. der Tupelmenge. Gestrichen werden die, bei denen b.BezPS ungleich c.BezPS ist: |
|
- b.BezPS: Im jeweiligen Projekt genutzte Programmiersprache.
- c.BezPS: von der jeweiligen Person beherrschte Programmiersprache.
|
|
Es bleiben also nur die Tupel übrig, bei denen (persönliche) Programmiersprachenkompetenz und notwendige (Projekt-)Programmiersprachen übereinstimmern. |
|
AND a.BezProj = b.BezProj |
|
Wieder eine Einschränkung auf der Tupelmenge. Gestrichen werden nun die, bei denen a.BezProj ungleich b.BezProj ist: |
|
- a.BezProj: Projekt in dem die Person mitarbeitet.
- b.BezProj: Projekt in dem die jeweilige Programmiersprache genutzt wird.
|
|
Es bleiben also nur die Tupel übrig, bei denen bzgl. persönlicher Programmiersprachenkompetenz und benötigter (Projekt-)Programmiersprache derselbe Eintrag vorliegt. |
|
Diese Relation ist nicht in 5NF. Eine Zerlegung in weniger als drei Relationen ist ohne Semantikverlust nicht möglich. |
|
Eine einfache Zerlegung durch Projektionen in drei Relationen führt zu den oben angeführten Relationen, allerdings nur mit den Daten, die den semantischen Anforderungen genügen. |
|
Zum besseren Verständnis |
|
Mit den Befehlen |
|
create table angprojPS AS
|
|
select a.PersNr, a.BezProj, c.BezPS
|
|
from AngProj a, ProjPS b, AngPS c
|
|
where a.PersNr = c.PersNr
|
|
AND b.BezPS = c.BezPS
|
|
AND a.BezProj = b.BezProj
|
|
order by a.PersNr, b.BezProj, c.BezPS
|
|
erzeugen wir die Relation AngProjPS. Nun die Projektionen, die hier gleich als persistente Relationen angelegt wurden: |
|
Projektion 1 |
|
PersNr |
BezProj |
1007 |
WebPl |
1008 |
WebPl |
1009 |
PPS |
1010 |
PPS |
| |
Projektion 2
|
|
PersNr |
BezPS |
1007 |
MySQL |
1007 |
PHP |
1008 |
PHP |
1009 |
C |
1010 |
Cpp |
| |
Projektion 3
|
|
BezProj |
BezPS |
WebPl |
MySQL |
WebPl |
PHP |
PPS |
C |
PPS |
Cpp |
| |
Nun der Join über diese drei Relationen:
|
|
select* from proj1 a, proj2 b, proj3 c
|
|
where a.PersNr=b.PersNr
|
|
and a.BezProj=c.BezProj
|
|
and b.BezPS=c.BezPS
|
|
PersNr |
BezProj |
PersNr |
BezPS |
BezProj |
BezPS |
1007 |
WebPl |
1007 |
MySQL |
WebPl |
MySQL |
1007 |
WebPl |
1007 |
PHP |
WebPl |
PHP |
1008 |
WebPl |
1008 |
PHP |
WebPl |
PHP |
1009 |
PPS |
1009 |
C |
PPS |
C |
1010 |
PPS |
1010 |
Cpp |
PPS |
Cpp |
| |
Die identischen Attribute zeigen, dass die gewünschte Semantik voll erfüllt ist. Allerdings enthält diese Relation nicht alle Daten, die in unseren Ausgangsrelationen AngProj, AngPS und ProjPS vorhanden waren, sondern nur diejenigen mit der gewünschten Semantik. Die ursprüngliche Ausgangsrelation AngProjPS erfüllt also nicht die 5NF.
|
|
Letzte denkbare Normalform |
|
Normalformen sind bezüglich einer Operation (bzw. bezüglich zweier in Beziehung stehender Operationen) definiert. Die hier betrachteten bezogen sich auf die oben vorgestellten Verbund/Projektion - Operationen. Date weist darauf hin, dass die 5NF die letzte denkbare Normalform bezüglich der Verbund/Projektion-Operationen ist [Date 1990, S. 390]. |
|
In der Praxis spielt die 5NF so gut wie keine Rolle. Eine Verbund-Abhängigkeit ist auch nicht ohne weiteres zu erkennen, denn selbst wenn alle Einträge einer Relation angegeben sind, und die vorliegenden Daten die oben angegebene Regel einhalten, muss sie ja nicht gelten. |
|
Wenngleich es nicht immer sinnvoll ist, alle Normalisierungsschritte tatsächlich durchzuführen, verhilft die Kenntniss der Normalisierungstheorie doch zu einem besseren Datenmodell und zu einem tieferen Verständnis der attributbasierten Modellierung, die hier mit den Normalisierungsstufen einen ihrer Höhepunkte erlebt. Ein erheblicher Teil dessen, was Stammdatenkrisegenannt wird, ist auf inkompetente Normalisierung zurückzuführen. |
Normalisierung - wie weit? |
Auf jeden Fall ist die Realisierung der BCNF und die Verhinderung einer mehrfachen mehrwertigen Abhängigkeit zu empfehlen, so dass die 4NF immer sichergestellt ist. |
|
Ganz aktuell und ganz anders: Im Bereich von BigData und NoSQL wird teilweise sogar auf elementare Normalisierungsschritte verzichtet. Grund ist die gewünschte hohe Verarbeitungsgeschwindigkeit. Voraussetzung ist eine entsprechende einfache Datenstruktur. Vgl. hierzu Kapitel 24. |
NoSQL: Keine Normalisierung |
Zum Nachdenken |
|
Hier noch etwas zum Nachdenken und zum Überprüfen des Erkenntnigewinns: In [Date 1990, S. 558] finden sich folgende elegante Definitionen der drei höheren Normalformen: |
|
- A relation R is in BCNF if and only if every FD in R is a consequence of the candidate keys of R
- A relation R is in 4NF if and only if every MVD in R is a consequence of the candidate keys in R
- A relation R is in 5NF if and only if every JD in R is a consequence of the candidate keys of R.
|
|
Zur Erinnerung: |
|
FD = functional dependency =funktionale Abhängigkeit = FA |
|
MVD = multi-valued dependency =mehrwertige Abhängigkeit =MWA |
|
JD= join dependency = Verbund-Abhängigkeit = VA |
|
candidate key = (Sekundär)Schlüssel, Schlüsselkandidat |
|
13.3 Regeln für die Erstellung relationaler Datenmodelle |
|
Hier nun - kurz zusammengefasst - die aus dem obigen Text ableitbaren Regeln für die Erstellung relationaler Datenmodelle: |
|
- Jede Relation muss in 5NF sein. Dafür genügt meist ein Herbeiführen der 3NF und ein Prüfen, ob die BCNF erfüllt ist und ob keine mehrfachen mehrwertigen Attribute oder fehlerhafte Verbundabhängigkeiten vorliegen.
- Die Zerlegungen im Rahmen der Normalisierung dürfen zu keinem Informationsverlust führen. D.h., es ist immer darauf zu achten, dass durch relationale Verknüpfungen entlang von Schlüsseln und Fremdschlüsseln die in der Ausgangsrelation vorhandene Information erhalten bleibt.
- In jede Relation kommen nur die Attribute, die für alle Objekte Gültigkeit haben. Dies ergibt sich auch aus den Normalformen, soll aber nochmals deutlich gemacht werden (vgl. hierzu auch Kapitel 14 zum Muster Generalisierung / Spezialisierung). Es darf also keine semantisch bedingten Leereinträge geben. Ausnahmen sind Attribute zu Anfang und Ende bei zeitlichen Dimensionsangaben.
- Normalerweise gibt es keine unterschiedlichen Relationen mit identischem Schlüssel. Ausnahmen sind Relationen im Rahmen einer Generalisierung / Spezialisierung (vgl. Abschnitt 14) und große Relationen mit sehr lückenhaften Daten. Hier greift man u.U. ganz pragmatisch zu einer Aufteilung, damit die Leereinträge nicht vervielfacht werden. Ein Beispiel könnte eine Relation zu Datenbanksystemen sein, bei der man alle "kaufmännischen" Attribute hat, aber nur sehr wenige technische. Dann könnte in DBS-Kfm und DSBS-Tech aufgeteiltt werden.
|
|
Wird dies alles realisiert, ist auch eine zentrale Regel des Datenbankentwurfs umgesetzt: |
|
Jede (hier ja immer attributbasierte) Information darf in einer Datenbank nur einmal vorkommen. |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|