Session D-DATA

Datenmodellierung

Manfred Rätzmann
Rätzmann GmbH


Wozu Datenmodellierung?

Die Applikationen, die Sie mit VFP entwickeln, haben mit hoher Wahrscheinlichkeit einen Schwerpunkt bei der Speicherung und Auswertung von Daten. Wenn dem nicht so wäre, wäre ein Datenbankentwicklungssystem vielleicht nicht das geeignetste Werkzeug.

Wenn aber die effiziente Speicherung und Auswertung bestimmter Daten den Schwerpunkt Ihrer Software bildet, so sollten Sie der Struktur dieser Daten natürlich die höchste Aufmerksamkeit widmen. Datenmodellierung beschäftigt sich mit der Struktur der Daten, die einer Software zu Grunde liegen.

Ziele der Datenmodellierung

Ziel der Datenmodellierung ist es, qualitativ hochwertige Datenstrukturen zu erzeugen. Die Qualität von Datenstrukturen läßt sich an vier Kriterien festmachen:

Integrität:

Die Integrität der Daten steht natürlich an erster Stelle. Niemandem nutzt eine superschnelle Applikation, die einfach zu warten ist und deren Ergebnisse sich vielfach weiterverwenden lassen, wenn man sich auf eben diese Ergebnisse nicht verlassen kann. Drei Punkte sind wichtig für die Integrität eines Datenmodells:

Details dazu folgen weiter unten.

Performance:

Die Performance nimmt als Qualitätsmerkmal unbestritten Platz zwei ein. Anwender sind ungeduldig. Leider steht der Anspruch, möglichst schnelle Antwortzeiten zu erzielen, häufig im Widerspruch zu den anderen drei Qualitätskriterien. Wird eine ausreichende Performance durch Datenredundanz erzielt, ist die Integrität der Daten gefährdet. Das zieht nicht nur erhöhten Programmieraufwand nach sich, sondern verringert auch die Wartbarkeit des Systems.

Zur Steigerung der Performance werden in allen RDBMs Indizes eingesetzt. VFP hat mit der Rushmore-Optimierung performanceseitig bei PC-Datenbanken eindeutig die Nase vorn. Wie Sie Rushmore optimal einsetzen, erfahren Sie auf dieser DevCon in der D-RUSH Session von Peter Herzog.

Wartbarkeit:

Die Wartung einer (VFP) Datenbank teilt sich in technische und strukturelle Aspekte. Zu den technischen Aspekten gehört zum Beispiel das Reindizieren und Packen von Tabellen. Die technischen Aspekte der Datenbankwartbarkeit sind nicht Bestandteil dieses Vortrags. Deshalb soll hier der Hinweis reichen, daß zur technischen Wartung einer VFP-Datenbank gute Werkzeuge von Drittanbietern zur Verfügung stehen.

Die strukturellen Aspekte der Wartbarkeit spielen bei der Datenmodellierung jedoch eine große Rolle. Wartbarkeit und Integrität sind (anders als die Performance) Ziele, die sich nicht widersprechen. So macht eine sauber normalisierte Datenstruktur sicher weniger Probleme bei notwendig werdenden Erweiterungen oder Änderungen als eine nicht normalisierte Struktur. Gleichzeitig sind normalisierte Strukturen der beste Garant für integre Daten. mehr zur Normalisierung von Datenstrukturen folgt weiter unten.

Wiederverwendbarkeit:

Auch das Qualitätskriterium Wiederverwendbarkeit hat zwei unterschiedliche Aspekte. Zum einen kann bei der Datenmodellierung darauf geachtet werden, daß die entstehenden Strukturen wiederverwendbar sind. Dies führt dann zu der Aufteilung einer Gesamtaufgabe in einzelne Module, die jeweils eine eigene, fest umrissenen Aufgabenstellung haben und nur über ihre definierten Schnittstellen miteinander kommunizieren. Der erfahrene Datenbank-Entwickler wird hier gleich eine mögliche Performancefalle wittern. Zu Recht - auch die strukturelle Wiederverwendbarkeit ist ein Ziel, daß häufig im Widerspruch zum Qualitätskriterium „Performance“ steht.

Die zweite Art der Wiederverwendbartkeit betrifft die Daten selbst. Ein mögliches Modellierungsziel kann sein, den gleichen Datenbestand aus mehreren Applikationen heraus nutzen zu können. Dann werden vielleicht nicht alle Felder einer Tabelle von jeder Applikation genutzt. Aus der Sicht einer einzelnen Applikation heraus sind diese Felder schlicht überflüssig. Der negative Einfluß auf die Performance ist dabei aber gering.

Methoden der Datenmodellierung

Die intuitive Methode:

Dies ist wahrscheinlich immer noch die häufigste Methode, die zur Datenmodellierung angewandt wird. Diese Methode benutzt

mehr oder weniger glücklich zur Entwicklung einer Datenstruktur, deren Tauglichkeit oder Fehlerhaftigkeit sich erst im praktischen Einsatz erweist. Durch Nachbesserungen, Erweiterungen und Optimierungsversuche entstehen dabie die sogenannten „gewachsenen Strukturen“, die später niemand mehr umzustoßen wagt. Von ihnen ist nur bekannt, daß sie einigermaßen funktionieren, aber nicht, warum. Also läßt man besser die Finger davon.

Bei der intuitiven Methode weiß der/die Entwickler/in einfach, welche Informationen zusammen gehören - oder glaubt es zu wissen. Die Erfahrung lehrt ihn oder sie zum Beispiel, Kopfdaten und Positionsdaten einer Rechnung zu trennen. Fachgebietswissen wird häufig unreflektiert übernommen (3 Preise im Artikelstamm, mehr kommt hier nicht vor) und technisches Wissen wird benutzt, um die Tabellen zu verknüpfen. Für SET RELATION TO ... INTO ... braucht die verknüpfte Tabelle halt ein oder mehrere Felder der Basistabelle. Der theoretische Hintergrund von Primär- und Fremdschlüsseln bleibt aber unklar und ihr Einsatz technisch motiviert.

Die intuitive Methode mag für kleine, wenig komplexe Projekte ausreichen. Für größere Projekte ist sie jedoch ungeeignet. Außerdem gilt: Wer einmal mit einem guten Modellierungswerkzeug Datenmodellierung methodisch statt intuitiv betrieben hat, wird es zukünftig auch bei kleinen Projekten nicht lassen. Dazu sind die Vorteile der Methodik (Sicherheit, feststehende Designprinzipien, Komplexitätsbewältigung) und des Werkzeugs (automatische Prüfung auf Designfehler, Verwaltung der benötigten Indizes, automatischer Datenbank-Update, Verwendung von Domänen statt Feldtypen usw.) zu gravierend.

Der Entity-Relationship Ansatz (ER)

Peter P.S. Chen stellte mit „The Entity-Relationship Model“ 1977 einen Ansatz zum logischen Datenbankentwurf vor. Damals waren hierarchische und Netzwerk (CODASYL-) Datenbanken vorherrschend, während die relationalen Datenbanken noch in ihren Anfängen steckten. Datenbankentwurf bedeutete immer physischer Datenbankentwurf, das heißt, es mußte entschieden werden, ob vorwärts oder rückwärts verzeigert werden soll und ähnliches. Chen ermöglichte mit seinem Entity-Relationship Ansatz erstmals einen logischen Blick auf die Datenbank. Datenstrukturen werden mit festgelegten Symbolen beschrieben, die physische Realisierung tritt in den Hintergrund. Spätestens mit dem Aufkommen von CASE-Tools hat sich der Entity-Relationship Ansatz zum logischen Datenbankentwurf in der Entwicklerwelt vollständig durchgesetzt.

Die ER-Modellierung setzt sich zum Ziel, ein Modell der realen Welt zu schaffen - oder besser: der Teile der realen Welt, die für die Datenbankanwendung von Interesse sind. Dieses Modell soll dann in einem zweiten Schritt in einen physischen Datenbankentwurf umgesetzt werden. Heutige CASE-Werkzeuge bieten dem Entwickler in den meisten Fällen einen grafischen Editor zur Erstellung der ER-Diagramme und führen den zweiten Schritt automatisch durch.

Ein ER-Modell beschreibt Entitäten oder Einheiten und deren Beziehungen zueinander. Eintitäten werden dabei durch Attribute beschrieben, während die wichtigste Angabe bei den Beziehungen neben der Rolle, die die eine Entität für die andere spielt, die Kardinalität ist. Die Kardinalität gibt an, wieviele Entitäten des einen Typs zu jeweils einer Entität des anderen Typs in Beziehung stehen können.

Bevor wir jedoch in die Einzelheiten der Modellierung einsteigen, möchte ich die dritte Methode vorstellen, die heute zur Datenmodellierung eingesetzt werden kann:

Die Objekt-Modellierungs Technik (OMT)

Nachdem der Entity-Relationship Ansatz sich als sehr hilfreich bei der Datenmodellierung erwiesen hatte, versuchte man, diesen auf den gesamten Programmentwurf anzuwenden. So richtig gelang das aber erst mit der von Rumbaugh und anderen vorgestellten Object-Modeling Technique (OMT). Die OMT erhebt den Anspruch, eine einheitliche Entwurfsmethode für alle Stadien der Softwareentwicklung zu sein, also auch für den Datenbankentwurf. In ihrem Buch „Object-Oriented Modeling and Design for Database Applications“ gehen Michael Blaha und William Premerlani explizit auf den Einsatz der OMT zur Datenmodellierung ein. Dabei wird - ähnlich der ER-Modellierung - ein Objektmodell entworfen, das die für die Anwendung relevanten Teile der realen Welt darstellt. Bei der Implementierung wird dieses Objektmodell in eine relationale Datenbank oder in eine andere Form der Datenspeicherung umgesetzt.

ER-Modellierung und OMT haben viele Parallelen, auf die im folgenden auch hingewiesen wird. Trotzdem ist überall deutlich zu merken, daß die OMT die fortgeschrittenere Methode ist. Neben der Vereinfachung der grafischen Darstellung werden in OMT auch Konzepte herausgearbeitet oder neu eingeführt, die im ER-Ansatz nur verschwommen oder gar nicht vorhanden waren. Beispiel dafür sind Verknüpfungs-Attribute (Link Attribute), Beziehungs-Klassen (Association Classes) und Vererbung (Inheritance).

Modellierungs Praxis

Im folgenden werde ich einige Begriffe der Modellierungstechniken erläutern. Dabei stelle ich jedem Abschnitt eine kleine Tabelle voran, die zeigt, wie der jeweilige Begriff in der Entity-Relationship Modellierung (ER) und in der Objekt-Modellierungs-Technik (OMT) heißt, und was diesem Begriff in einer relationalen Datenbank (RDB) entspricht.

Da für die Modellierungspraxis ein gutes Werkzeug unerläßlich ist - sonst macht das Ganze keinen Spaß - werde ich auch des öfteren auf Arbeitsweisen und Eigenheiten der von mir verwendeten Tools eingehen.

Ein einzelnes Ding

ER

OMT RDB

Entität

Objekt Datensatz

Alle Modellierungstechniken wollen ein Modell der realen Welt erstellen, bzw. eines Ausschnitts daraus, der für das zu entwerfende System von Interesse ist. Die Dinge der realen Welt werden im ER-Modell Entitäten genannt und im OMT-Modell Objekte. Eine mögliche Definition lautet: Eine Entität oder ein Objekt ist ein Ding, das eindeutig identifiziert werden kann. Der ER-Ansatz bietet dem Modellierenden darüber hinaus kein System zum Auffinden möglicher Entitäten. Hier ist also immer noch Intuition gefragt. Die OMT dagegen bietet ein System an, das darauf hinausläuft, aus der Aufgabenspezifikation alle Substantive zu nehmen und diese nach bestimmten Kriterien auf mögliche Objekte zu untersuchen. Da wir uns hier am Übergang zwischen gesprochener oder geschriebener Sprache mit all ihren Mehrdeutigkeiten und einem Systemmodell mit eindeutigen Symbolen befinden, ist aber auch bei systematischer Vorgehensweise Erfahrung und Intuition nötig, um die interessierenden Objekte zu finden. Zumal ein Objekt nicht immer ein physisches Ding sein muß, sondern auch eine Vorschrift, ein Verfahren oder was ähnlich Abstraktes sein kann.

Ein Objekt ist immer ein einzelnes Ding, also ein Kunde, ein Artikel oder eine Bestellung. In einer relationalen Datenbank entspricht einem solchen Objekt daher immer ein Datensatz. In der Modellierungsphase wird allerdings selten das einzelne Objekt betrachtet. Wichtiger sind hier Gruppen von gleichen Objekten.

Alle diese Dinge

ER OMT RDB
Entitätstyp
Klasse
Tabelle

Entitäten im ER-Ansatz haben einen Typ, Objekte aus der OMT gehören zu einer Klasse. Gemeint ist das selbe - nämlich eine Zusammenfassung gleichartiger Objekte. Entitätstypen bzw. Klassen sind die wichtigsten Bausteine eines ER- oder OMT-Modells. Datenbankseitig entspricht ein Entitätstyp bzw. eine Klasse einer Tabelle. In einer Tabelle sind also alle Objekte der gleichen Klasse oder alle Entitäten des gleichen Typs zusammengefaßt. Üblicherweise bezeichnet man in beiden Modellen Typen oder Klassen mit einem Begriff im Singular. „Kunde“ ist demnach ein Entitätstyp oder eine Klasse, während „EinKunde“ einObjekt dieser Klasse ist.

Um nicht dauernd zwischen den Begriffswelten hin und her wechseln zu müssen, benutze ich im folgenden die Begriffe der OMT. Ich sage also Objekt statt Entität und Klasse statt Entitätstyp

Ein bestimmtes Ding

ER OMT RDB
Identifikationsschlüssel
Identität
Primärschlüssel

Um in einer Menge gleicher Objekte ein bestimmtes Objekt zu finden, braucht man eine Eigenschaft, die mit Sicherheit bei jedem Objekt anders ist. Mit anderen Worten, einen eindeutigen Schlüssel. Für die Modellierung ist ein solcher eindeutiger Schlüssel eigentlich nicht notwendig. OMT setzt zum Beispiel einfach voraus, daß jedes Objekt eine eindeutige Identität hat und damit identifiziert werden kann.

Auch ER-Diagramme brauchen im Prinzip keine Schlüssel. Da die meisten Modellierungswerkzeuge aber darauf ausgerichtet sind, das Modell anschließend in eine relationale Datenbank umzusetzen, wird bereits beim Modellieren mit Schlüsseln gearbeitet.

Die eindeutigen Schlüssel von Tabellen in relationalen Datenbanken nennt man Kandidatenschlüssel (Candidate Keys), einer von ihnen wird zum Primärschlüssel (Primary Key) bestimmt. Verbindungen zwischen zwei Tabellen werden immer durch Übernahme des Primärschlüsselfelds der einen Tabelle in die andere Tabelle hergestellt. Das übernommene Feld wird als Fremdschlüssel bezeichnet, da es der Primärschlüssel einer Fremdtabelle ist. Mit „Parent“ bezeichne ich im folgenden die Tabelle, deren Primärschlüssel übernommen wird, mit „Child“ die Tabelle, die den Fremdschlüssel aufnimmt.

Primärschlüssel können Felder der Tabelle sein (auch mehrere miteinander verknüpft), die einen für den Anwender sinnvollen Inhalt haben, zum Beispiel Kunden- und Artikelnummern. Solche Schlüssel nennt man natürliche Schlüssel, OMT spricht von einer „value-based identity“ der Objekte.

Häufig sind Primärschlüsselfelder aber Zusatzfelder, die keinen anderen Zweck haben als eben den, Primärschlüssel zu sein. Die Werte, die in diesen Feldern stehen, haben aus der Sicht des Anwenders keinen Sinn. Das sollen sie auch nicht, sie sollen nur eindeutig sein. Solche Schlüssel nennt man künstliche Schlüssel oder Surrogatschlüssel, in OMT spricht man dann von einer „existence-based identity“ der Objekte.

Ob natürliche oder künstliche Schlüssel verwendet werden sollen, ist eine technische Designentscheidung, an der sich gerne die Meinungen teilen. Hier einige Argumente für die beiden Schlüsselarten

Value-based identity = natürliche Schlüssel

+ kein Zusatzfeld notwendig
+ direkte Abfragemöglichkeit durch SQL-SELECT
+ dadurch weniger Views notwendig
- Änderungen müssen in Childtabellen übernommen werden
- Eindeutigkeit muß vom Programm überwacht werden
- Prüfung der Eindeutigkeit offline nicht möglich

Existence-based identity = Surrogatschlüssel

- Zusatzfeld erforderlich
- keine direkte Abfragemöglichkeit
- dadurch werden mehr Views gebraucht
+ können vom Anwender nicht geändert werden
+ Eindeutigkeit kann vom Programm vorausgesetzt werden
+ Eindeutigkeit kann auch bei Offline-Verarbeitung gewährleistet werden

Entscheiden Sie sich nach Abwägung des Für und Wider für eine Schlüsselart, und bleiben Sie - zumindest innerhalb des einen Projektes - dabei. Ein Mischen der beiden Arten ist nicht empfehlenswert, da es leicht zu Verwirrung führt und eine mögliche Fehlerquelle darstellt.

Wenn Sie sich für natürliche Schlüssel entscheiden, so sollten Sie zusammengesetzte Schlüssel möglichst vermeiden, da auch hierbei wieder erhöhte Aufmerksamkeit erforderlich ist und zusammengesetzte Schlüssel Probleme beim Sicherstellen der referentiellen Integrität (siehe unten) bewirken können.

Surrogatschlüssel können auf unterschiedliche Weisen erzeugt werden. Häufig werden Integerfelder als Surrogatschlüssel verwendet, weil der Zugriff darauf sehr schnell ist, ein hinreichend großer Wertebereich zur Verfügung steht und die Bildung eines neuen Schlüssel einfach durch Addition von 1 erfolgt. Allerdings braucht man dazu eine Systemtabelle, d.h. eine Tabelle, in der Zähler für die Schlüssel der Anwendungstabellen mitgeführt werden. Solange eine Anwendung immer direkten Zugriff auf diese Systemtabelle hat - also alle Anwender grundsätzlich online arbeiten - gibt es dabei keine Probleme. Wenn Anwender allerdings auch offline arbeiten sollen, wird das Verwalten einer solchen Systemtabelle sehr kompliziert.

Auf der Begleitdiskette zu dieser Session finden Sie eine Funktion CreateId(), die ohne Systemtabelle arbeitet und von daher auch im offline-Betrieb garantiert eindeutige Schlüssel liefert. Diese sind allerdings 20 Zeichen lang. Einzige Voraussetzung ist, daß alle beteiligten Arbeitsstationen und Nutzer unterschiedliche Namen haben, um auch das letzte Restrisiko von doppelten Werten auszuschließen.

Ein Ding von allen Seiten

ER OMT RDB
Attribute
Eigenschaften
Datenfelder

Entitäten haben Attribute, Objekte haben Eigenschaften. Auch hier ist wieder das gleiche gemeint. Wenn zwei Entitäten die gleichen Attribute haben, gehören sie zwangsläufig zum gleichen Entitätstyp. Bei Objekten kommen da allerdings noch die Methoden in’s Spiel. Zwei Objekte mit gleichen Eigenschaften und gleichen Methoden gehören zur selben Klasse. Da die Methoden allerdings nicht eigentlich zur Datenmodellierung gehören, bleiben sie hier zunächst mal außen vor.

Erste Regel: Redundanzfreiheit

Für die Zuordnung von Eigenschaften gilt als wichtigste Regel: Eine Information an einer Stelle. Wenn Sie eine Klasse „Adresse“ und eine andere Klasse „Kunde“ modellieren, so gehört der Wohnort des Kunden zur Adresse. Eine zusätzliche Eigenschaft „Wohnort“ in der Klasse „Kunde“ wäre demnach ein gravierender Modellierungsfehler. Leider sind redundante Eigenschaften nicht immer so einfach auszumachen. Auf den ersten Blick könnten Sie auch einen Artikelpreis in der Klasse Auftragsposition für redundant halten - der Preis steht ja schon im Artikelstamm. Hier liegt aber keine Redundanz vor, da eine Auftragsposition zu den Belegdaten zählt. Belegdaten sollten grundsätzlich vollständig sein, d.h. für einen Beleg wesentliche Information darf nicht durch Verweis auf einen Stammdatensatz gefunden werden, sondern muß beim Beleg selbst gespeichert werden. Der Artikelpreis im Beleg muß nämlich unverändert bleiben, auch wenn sich die Artikelstammdaten zwischenzeitlich ändern. Das gleiche gilt für alle anderen Daten, die in einen Beleg einfließen.

Domänen und Feldtypen

Die Eigenschaften einer Klasse entsprechen den Datenfeldern eines Datensatzes einer relationalen Datenbank. Wenn eine Datenbanktabelle aufgebaut wird, wird jedem Datenfeld neben seinem Namen zumindest noch ein Typ mitgegeben. Bei der Modellierung könnte man nun ähnlich vorgehen und den Eigenschaften schon gleich einen Typ verpassen, zum Beispiel C für einen Character-String, D für ein Datum und so weiter. Empfehlenswert ist hier jedoch eine andere Vorgehensweise. Legen Sie für Ihr Modell sogenannte Domänen fest. Domänen sind selbst definierte Datentypen, das heißt Datentypen, die noch nicht die Typen der Zieldatenbank sind, sondern diese vertreten. Erst, wenn Ihr Modell in eine Implementation überführt werden soll, legen Sie den genauen Typ und Aufbau jeder Domäne fest. Ihr Datenmodellierungswerkzeug sollte also unbedingt die Verwendung von Domänen statt Feldtypen unterstützen.

Constraints

Visual FoxPro ermöglicht es, in der Datenbank Regeln zu hinterlegen, denen einzelne Felder oder ganze Datensätze entsprechen müssen. Solche Regeln, auch Constraints, Zwänge, genannt, müssen auch im Modell hinterlegt werden können. Obwohl in der ER-Modellierung keine spezielle Notation für Constraints vorgesehen ist, ermöglichen ER-Modeling Tools es doch, diese Regeln im Modell abzulegen. In OMT können Constraints direkt einzelnen Attributen, Klassen oder Verbindungen zugeordnet werden. Umfangreichere Regeln werden aber nicht im Objektmodell sondern im Funktionsmodell hinterlegt.

Constraints werden als logische Ausdrücke formuliert, die .T. oder .F. ergeben. Komplexere Regeln werden als StoredProcedure in der Datenbank abgelegt. Auch eine solche StoredProcedure muß also .T. oder .F. zurückliefern, um als Regel der Feld- oder Satzvalidierung benutzt werden zu können. Die Regeln der Feld- und Satzvalidierung gehören - anders als die RI-Regeln (siehe unten) - zu den sogenannten Businessrules.

Feldvalidierung

Regeln zur Feldvalidierung prüfen die Gültigkeit eines einzelnen Feldes. Typische Beispiele sind Felder vom Typ Datum, deren Werte nicht vor dem aktuellen Tagesdatum liegen dürfen oder Felder mit Preisen, die nicht kleiner Null sein dürfen. Wenn eine Feldvalidierungsregel verletzt wird, verhindert die Datenbank, daß der Feldwert gespeichert wird.

Satzvalidierung

Regeln zur Satzvalidierung prüfen die Gültigkeit eines Datensatzes. Auch hier wird das Speichern eines ungültigen Satzes durch die Datenbank verhindert. Satzvalidierung ist immer dann wichtig, wenn die gültigen Werte für Felder des Datensatzes von einander abhängen. Ein Beispiel wäre eine Auftragsposition, bei der sich Rabatt und Mindermengenzuschlag gegenseitig ausschließen. Das läßt sich auf Feldebene schlecht abprüfen, da der Anwender ja jederzeit noch den einen oder anderen Wert eintragen könnte.

Die Abprüfung, ob alle im Satz vorhandenen Fremdschlüssel auf einen gültigen Satz in der verknüpften Tabelle verweisen, ist nicht Sache der Satzvalidierung sondern der Prüfung auf referentielle Integrität, die weiter unten behandelt wird.

Namenskonvention

Stellen Sie für die von Ihnen benutzten Tabellen und Feldnamen eine Namenskonvention auf. Eine gute Idee ist es, jeder Tabelle zum Beispiel ein dreistelliges Kürzel zuzuordnen, mit dem dann auch jeder Feldname in dieser Tabelle - mit Ausnahme der Fremdschlüsselfelder - beginnt. In einer Tabelle mit Adressen könnten die Felder dann ADR_Name, ADR_Strasse, ADR_Ort und so weiter benannt werden. Das hat zum einen den Vorteil, daß keine Namenskonflikte auftreten können. Fremdschlüsselfelder werden bei der Übernahme in die Childtabelle nicht umbenannt. Sie tragen also weiterhin das Kürzel der Parenttabelle und sind damit in der Childtabelle sofort als Fremdschlüssel identifizierbar. Ein dritter Vorteil dieser Namenskonvention ist, daß Sie auch in Views oder Abfragen über mehrere Tabellen sofort erkennen können, woher ein Feld stammt.

Ein bestimmtes Ding zu einem bestimmten Zeitpunkt

ER OMT RDB
Attributswerte
Status
Feldinhalte

Der Inhalt eines Tabellenfeldes ist der Eigenschaftswert. Alle Eigenschaftswerte zusammengenommen ergeben den aktuellen Status eines Objektes.

Redundante Werte

Ein Wert ist redundant, wenn er sich aus anderen gespeicherten Werten ermitteln läßt. So ist der aktuelle Bestand eines Lagerteils redundant, wenn Sie den Bestand bei der letzten Inventur und alle Zu- und Abgänge seitdem speichern. Das Mitführen von redundanten Werten dient immer der Performancesteigerung, andere Gründe dafür gibt es nicht. Kennzeichnen Sie redundante Werte bereits im Modell, zum Beispiel als Kommentar zu einer Eigenschaft. In OMT werden Eigenschaften, die redundante Werte enthalten, durch einen vorangestellten Schrägstrich gekennzeichnet.

Stellen Sie bei der Implementierung der Datenbank Prozeduren bereit, die redundante Werte aus den Basisdaten auffrischen können. Wenn Sie einen redundanten Wert nicht bei jeder Änderung der Basisdaten automatisch errechnen wollen, bietet sich die Möglichkeit an, in einer separaten Tabelle alle Fremdschlüssel abzulegen, die „dirty“ sind. Erst beim nächsten Aufruf eines Childsatzes wird überprüft, ob er in der Dirty-Table vermerkt ist. Wenn ja, werden die redundanten Werte des Childsatzes aufgefrischt. Bei einem solchen Verfahren sind natürlich systemweit eindeutige IDs von Vorteil.

Berichtsdaten

Alle Eigenschaftswerte sind zeitbezogen, das heißt, die selbe Eigenschaft hat zu unterschiedlichen Zeiten häufig einen unterschiedlichen Wert. Auswertungen der gespeicherten Daten sind ebenfalls zeitbezogen, sie geben den Status Ihrer Daten zu einem genauen Zeitpunkt wieder. Manchmal ist es daher sinnvoll, die für Auswertungen benötigten Daten getrennt von den aktuellen Daten bereitzustellen. Dabei wird nicht einfach eine Kopie der aktuellen Daten angefertigt. Solche Berichtsdaten können nämlich bereits bei der Ermittlung in eine Struktur gebracht werden, die für die Auswertungen leichter zu handhaben ist. Berichtsdaten müssen nicht normalisiert und redundanzfrei sein, ganz im Gegenteil. Häufig läßt sich das Berichtswesen bedeutend einfacher auf nicht-normalisierten Daten aufbauen.

Gute Beziehungen

ER OMT RDB
Relationen
Assoziation
Fremdschlüssel oder Verknüpfungstabelle
Aggregation
Verknüpfungstabelle

Die Dinge der realen Welt, die wir modellieren wollen, stehen zueinander in Beziehung. Die Beziehungen bilden neben den Klassen den zweiten Hauptbestandteil eines jeden Modells. Natürlich können Sie Beziehungen auch im DBC festlegen. Das schöne an einem Modellierungswerkzeug wie xCase ist es aber, daß das Werkzeug alles für Sie erledigt, was mit der Verwaltung dieser Beziehungen zu tun hat. So wird durch das Setzen der Beziehung automatisch der Fremdschlüssel in die Childtabelle eingetragen - und auch wieder gelöscht, wenn Sie die Beziehung später wieder aus Ihrem Modell entfernen. SQL-Selects, die diese Beziehung nutzen wollen, benötigen zur Optimierung einen Index auf dem Fremdschlüsselfeld der Childtabelle. Auch das Anlegen des Index wird von xCase automatisch durchgeführt. Zeitschlüsselfelder und Indizes werden ebenfalls automatisch geändert, wenn Sie am Primärschlüsselfeld der Parenttabelle etwas ändern, etwa den Feldtyp bzw. die Domäne von numerisch auf Character umstellen.

In OMT gibt es zwei unterschiedliche Arten von Beziehungen: Assoziation und Aggregation. Assoziation ist eine „bezieht sich auf“ Beziehung und Aggregation eine „ist enthalten in“ Beziehung. Aggregation ist im ER-Modell nicht darstellbar.

Assoziative Beziehungen werden in der relationalen Datenbank durch Übernahme eines Fremdschlüssels oder durch Aufbau einer Verknüpfungstabelle implementiert. Aggregation wird immer über eine Verknüpfungstabelle dargestellt.

Namen

Beziehungen werden in mit einem Namen versehen. An diesem Namen können Sie dann im Modell gleich erkennen, woher ein Fremdschlüssel oder ein automatisch gebildeter Index stammt. Der Name sollte natürlich etwas mit dem Inhalt der Beziehung zu tun haben. Legen Sie für sich fest, ob Sie Namen aus der Sicht des Parent oder aus der Sicht des Child vergeben wollen. Vermeiden Sie ein Vermischen dieser beiden Sichtweisen. Ich persönlich bevorzuge die Sicht vom Parent zum Child. Die Beziehung zwischen Lieferant und Lagerteil heißt demnach „liefert“, und nicht „wird geliefert durch“.

Rollen

Rollennamen geben an, welche Rolle die eine Klasse für die andere spielt. Sehr oft ist die Rollenverteilung eindeutig, so daß keine besonderen Rollennamen vergeben werden müssen. So ist bei einer Beziehung zwischen Lieferant und Lagerteil klar, welche Rolle der Lieferant für das Lagerteil, und welche das Lagerteil für den Lieferanten spielt. Wenn zwischen zwei Klassen mehrere Beziehungen bestehen, ist es jedoch häufig von Vorteil, Rollennamen vergeben zu können.

Kardinalität

Die Kardinalität einer Beziehung gibt an, mit wievielen Objekten der anderen Klasse ein Objekt in Beziehung stehen kann. In einem Modell wird die Kardinalität grafisch dargestellt, eventuell ergänzt durch spezifischere Zahlenangaben. Bei den für Tabellenbeziehungen üblichen Benennungen, wie 1:1, 1:N oder N:M ist mit der zuerst (links) aufgeführten Seite immer die Parenttabelle gemeint.

1 : 1

Bedeutet, daß jedes Objekt der einen Klasse zu genau einem Objekt der anderen Klasse in Beziehung steht. Oder, in der Sprache der relationalen Datenbanken ausgedrückt, daß zu jedem Parentsatz genau ein Childsatz existiert. Diese Kardinalität ist relativ selten, sie kann aber zum Beispiel für projektspezifische Erweiterungstabellen genutzt werden, die Daten enthalten, die nicht in die Haupttabelle aufgenommen werden sollen.

1 : 0 oder 1 (1 : 0,1)

Hierbei kann das Objekt zu genau einem Objekt der anderen Klasse in Beziehung stehen, muß es aber nicht. In einer Erweiterungstabelle, die 1:0,1 mit der Haupttabelle verknüpft ist, existiert also nicht unbedingt zu jedem Satz der Haupttabelle ein Erweiterungssatz.

1 : N

Das ist wohl die am häufigsten vorkommende Kardinalität. Ein Objekt kann zu einem oder mehreren Objekten der anderen Klasse in Beziehung stehen. Ein typisches Beispiel dafür ist die Beziehung zwischen den Kopfdaten und Positionsdaten eines Belegs.

1 : 0 oder N (1 : 0,N)

Wie bei der 1:0,1 Beziehung gilt auch hier, daß ein Objekt eventuell zu keinem Objekt der anderen Klasse in Beziehung steht. Im Beleg-Beispiel heißt daß, es können Belegkopfdaten existieren, zu denen es (noch) keine Positionen gibt.

N : M

Bei dieser Kardinalität kann nicht nur ein Objekt der ersten Klasse mit mehreren Objekten der zweiten Klasse in Beziehung stehen, sondern jedes Objekt der zweiten Klasse kann auch mit mehreren Objekten der ersten Klasse in Beziehung stehen. Ein Beispiel, daß diesen Satz etwas anschaulicher macht, ist wieder die Beziehung zwischen Lieferant und Lagerteil. Ein Lagerteil kann von mehreren Lieferanten geliefert werden, ein Lieferant kann verschiedene Teile liefern.

N : M Beziehungen werden immer über eine Verknüpfungstabelle aufgelöst. Deshalb bietet xCase gar nicht erst die Möglichkeit an, N : M Beziehungen zu modellieren. Diese Einschränkung ist aber keine, die unbedingt schon im Modell angelegt sein müßte. In OMT und auch im ER-Ansatz sind N : M Beziehungen durchaus zugelassen. Viele ER-Modeling Tools bilden jedoch keine N : M Beziehungen ab, eben weil sie auf relationale Datenbanken ausgerichtet sind.

OMT kennt Assoziationseigenschaften und Assoziationsklassen. Bei der Umsetzung in eine relationale Datenbank entstehen daraus Verknüpfungstabellen, die nicht nur die beiden Primärschlüsselfelder aus den verknüpften Tabellen, sondern auch eigene Felder enthalten. Die Eigenschaften der Assoziation (oder auch Aggregation) entsprechen den Feldern der Verknüpfungstabelle. Wenn im Modell eine Assoziationsklasse (oder Aggregationsklasse) vorliegt, können Sie zwischen dieser Assoziationsklasse und anderen Klassen wiederum Beziehungen aufbauen. Auf Tabellenebene bedeutet daß, daß die Verknüpfungstabelle einen eigenen Primärschlüssel erhalten sollte.

Referentielle Integrität (RI)

Referentielle Integrität bedeutet die Zusicherung, daß alle Fremdschlüssel in Childtabellen auf gültige Sätze in Parenttabellen verweisen, daß also keine der im Modell angelegten Beziehungen in’s Leere zeigt. Ein referentiell nicht integrer Zustand ist mit dem Vorliegen von Pointerfehlern vergleichbar und bildet ähnliche Absturzgefahren für Ihr System.

RI-Regeln gehören nicht zu den Business-Rules. Sie sind also keine Regeln, die inhaltliche Aspekte der Datenbank bestimmen. Wo liegt der Unterschied? Eine Business-Rule kann zum Beispiel lauten, daß kein Kunde gelöscht werden darf, für den im System noch offene Rechnungen vorliegen. Eine RI-Regel hingegen besagt daß, wenn ein Kunde gelöscht wird, auch alle Rechnungen an ihn gelöscht werden müssen. Die RI-Regel entscheidet also nicht darüber, ob der Kunde gelöscht werden darf. Sie legt nur fest, was passieren muß, wenn dieser Kunde gelöscht wird. RI-Regeln und Business-Rules sollten nicht miteinander vermischt werden. Überlassen Sie die Entscheidung, ob ein Kunde gelöscht werden darf, einer Methode der Kundenklasse, stellen Sie in den RI-Regeln nur sicher, daß auch nach dem Löschen des Kunden die referentielle Integrität Ihrer Datenbank gesichert ist.

In VFP wird die referentielle Integrität durch Code sichergestellt, der von den Update- Insert und Delete-Triggern aufgerufen wird. Dieser Code ist jedoch nicht von Hause aus da, sondern Sie müssen ihn erstellen. Entweder, indem Sie ihn selbst schreiben (was nicht ganz trivial ist) oder indem Sie ihn generieren lassen. RI-Code kann zum Beispiel mit dem in VFP integrierten RI-Assistenten generiert werden. Wenn Sie ein Modellierungstool einsetzen, sollte dieses ebenfalls dazu in der Lage sein.

Für die Generierung des RI-Codes müssen Sie entscheiden, was mit verknüpften Childsätzen geschehen soll, wenn ein Parentsatz gelöscht wird oder wenn der Primärschlüssel geändert wird. Außerdem müssen Sie angeben, ob beim Einfügen von Sätzen in die Childtabelle immer ein passender Satz in der Parenttabelle vorhanden sein muß.

Weitergeben (cascade)

Die Option „Weitergeben“ bedeutet, daß eine Änderung des Primärschlüssels an die Childtabellen weitergegeben werden soll. Wenn Sie mit Surrogatschlüssel arbeiten, erübrigt sich das, da diese nicht geändert werden können. Wenn ein natürlicher Primärschlüssel geändert wird, kann das Weitergeben erhebliche Zeiten in Anspruch nehmen.

Bei Löschen eines Satzes der Parenttabelle bedeutet Weitergeben, daß alle mit diesem Satz verknüpften Childsätze ebenfalls gelöscht werden.

Verhindern (restrict)

Das Setzen dieser Option verhindert, daß ein Primärschlüssel eines Satzes der Parenttabelle geändert wird, wenn dieser Satz bereits mit einem Childsatz verknüpft ist. Ebenso wird in diesem Fall das Löschen des Parentsatzes verhindert.

Beim Einfügen von Sätzen in die Childtabelle verhindert diese Option, daß ein Childsatz eingefügt werden kann, zu dem kein passender Satz in der Parenttabelle vorhanden ist.

Ignorieren (ignore)

Ignorieren bedeutet, daß Änderungen oder Löschvorgänge nicht weitergegeben werden und daß Childsätze ohne gültigen Parentsatz erlaubt sind. Ignorieren setzt also die RI-Regeln außer Kraft und ist von daher im allgemeinen zu vermeiden.

Auf .NULL. setzen (Nullify)

Die Nullify-Option wird vom VFP Assistenten für referentielle Integrität nicht angeboten. xCase hingegen stellt Nullify als RI-Option für die DELETE-Regel zur Verfügung. Nullify bedeutet, daß beim Löschen eines Satzes alle Fremdschlüssel in anderen Tabellen, die auf diesen Satz verweisen, auf .NULL. gesetzt werden sollen. Der von xCase erzeugte RI-Code handelt die Situation auch ganz richtig ab, d.h. alle Verweise auf den zu löschenden Satz der Parent-Tabelle werden in den Child-Tabellen auf .NULL. gesetzt. Beim Einfügen eines neuen Satzes in die Child-Tabelle wird ein .NULL. Fremdschlüssel aber leider nicht korrekt behandelt, sondern führt zu einer Fehlermeldung (Datatype-Mismatch). Richtig wäre, auch bei einer Insert Regel RESTRICT Fremdschlüssel, die .NULL. beinhalten, zuzulassen. So bleibt momentan nur der Weg, die Insert-Regel auf IGNORE einzustellen, was aber auch bedeutet, daß der Fremdschlüssel jeden beliebigen Wert annehmen kann. Eine referentielle Integrität ist damit nicht gewährleistet.

Auf Defaultwert setzen (set to default)

Auch das ist eine Option für die DELETE-Regel, die vom VFP Assistenten nicht angeboten wird. Die Option bedeutet, daß bei Löschen eines Parentsatzes alle Fremdschlüsseleinträge, die sich auf diesen Satz beziehen, auf den als DefaultValue in der Datenbank hinterlegten Wert gesetzt werden. Das macht durchaus Sinn, wenn es in der Parenttabelle einen Satz gibt, dessen Primärschlüssel gleich dem DefaultValue der Fremdschlüsselfelder der zugehörigen Childtabellen ist. An einen solchen „Diverse“-Satz wird dann ein Childsatz verknüpft, wenn der eigene Parentsatz gelöscht wird.

Abstammung

ER OMT RDB
Sub- und Supertypen
Vererbungs-Hierarchie
identische Primärschlüssel

Die aus der objektorientierten Programmierung bekannte Vererbung bedeutet, das Eigenschaften einer Elternklasse an die abgeleiteten Kindklassen weitergegeben werden. Etwas ähnliches gibt es in ER-Modellen auch, nur heißt das dort nicht Vererbung. Dabei wird ein Entitätstyp als Spezialfall, Unterkategorie oder Subtyp eines anderen Entitätstyps modelliert. RDB-seitig läuft das darauf hinaus, daß die beiden resultierenden Klassen einen identischen Primärschlüssel haben. Der Primärschlüssel des Supertyps wird als Fremdschlüssel in den Subtyp übernommen und bildet dort wieder den Primärschlüssel.

Auf diese Art und Weise werden auch Vererbungshierarchien aus Objektmodellen in Tabellen einer relationalen Datenbank umgesetzt. Sinnvollerweise arbeitet das Programm auf einem View, der die Tabellen der Vererbungshierarchie wieder zusammenführt. So wird letztendlich ein Objekt einer abgeleiteten Klasse aus dem Objektmodell von einem Datensatz dieses Views repräsentiert.

Verhalten

ER OMT RDB
-
Methoden
-

Hier sind wir an einem Punkt angelangt, der eigentlich nicht mehr zur Datenmodellierung gehört. Wir haben gesehen, wie die Klassen und Objekte eines Objektmodells auf Tabellen und Satzstrukturen einer relationalen Datenbank abgebildet werden. Objekte haben aber nicht nur Eigenschaften, sondern auch ein Verhalten, das in den Methoden der jeweiligen Klasse angelegt ist. Die Frage,die sich nun stellt, ist: wo werden Methoden, die wir in einem Objektmodell einer Klasse zugeordnet haben, bei der Realisierung dieses Objektmodells auf einer relationalen Datenbank angesiedelt.

VFP bietet uns da mehrere Möglichkeiten. Zunächst einmal könnten solche Methoden als Prozeduren zum Beispiel in den StoredProcedures der Datenbank abgelegt werden. Da VFP aber auch über eine objektorientierte Programmiersprache verfügt, besteht die Möglichkeit, die Datensätze zur Laufzeit des Programms auch als Objekte anzusprechen. Dazu erschaffen Sie sich Klassen, die auf jeweils eine bestimmte Tabelle oder einen View zugreifen. Ein Objekt einer solchen Klasse liest bei seiner Instanziierung die Werte der Datenfelder eines Datensatzes aus und legt diese in seinen Eigenschaften ab. Geänderte Werte können zum Beispiel über eine Speichern-Methode wieder in den Datensatz zurückgeschrieben werden. Die Methoden des Klassen Ihres Objektmodells können dann eins zu eins in diesen VFP-Klassen abgebildet werden.

Normalisierung

Das bei der Datennormalisierung angewandte Verfahren ist keine Modellierungstechnik. Normalisierung ist ein Verfahren, das nur auf relationale Datenbanken angewandt wird. Objektorientierte Datenbanken zum Beispiel kennen keine Normalformen, da sie Objektmodelle direkt abbilden. Auch eine Sammlung von Textdateien kann nicht in Normalform gebracht werden.

Da wir mit VFP jedoch eine relationale Datenbank vor uns haben, läßt sich diese normalisieren. Das Normalisierungsverfahren wird aber nicht dazu verwandt, die Datenbank zu entwerfen, sondern lediglich dazu, die aus dem ER oder OMT-Modell entstandene Datenstruktur zu überprüfen. Wenn die aus Ihrem Modell entstandene Datenstruktur nicht der dritten Normalform entspricht, deutet das mit sehr hoher Wahrscheinlichkeit auf Fehler im Modell hin. Es kann natürlich sein, daß Ihr Modell bewußte Designentscheidungen enthält, die zu einer nicht-normalisierten Datenbank führen. Normalerweise ist der Test auf Vorliegen der dritten Normalform aber ein sehr nützlicher Qualitätscheck für Ihr Modell.

In relationalen Datenbanken werden die Daten in Tabellen gespeichert. Eine Tabelle ist eine zweidimensionale Matrix. Die Zeilen dieser Matrix bilden die Datensätze, die Spalten sind die Datenfelder. Um eine Zeile eindeutig wiederfinden zu können, muß mindestens eines der Felder dieser Zeile einen eindeutigen Wert enthalten. Dieser Wert darf in dieser Spalte also nur einmal vorkommen. Eine Spalte, die garantiert keine doppelten Einträge enthält, eignet sich als Identifikationsschlüssel für den eindeutigen Zugriff auf die Tabellenzeilen. Wenn mehrere Identifikationsschlüssel vorliegen, wird einer ausgewählt, der den sogenannten Primärschlüssel bildet. Die anderen, ebenfalls geeigneten Schlüssel heißen Kandidatenschlüssel. Sie sind eben Kandidaten für das ehrenvolle Amt des Primärschlüssels.

Um zwei Tabellen bei Abfragen miteinander verbinden zu können, wird ein Identifikationsschlüssel der einen Tabelle als Spalte der anderen Tabelle übernommen. In dieser Tabelle bildet er damit einen Fremdschlüssel. Ein Fremdschlüssel in einer Tabelle ist also immer ein Primär- oder Kandidatenschlüssel einer anderen Tabelle.

Normalisieren einer relationalen Datenbank heißt, die Tabellenstruktur einer feststehenden Prozedur zu unterziehen, solange, bis sie genau vorgegebenen Kriterien entspricht. Ich will das Vorgehen bei der Normalisierung kurz anhand von Daten ähnlich der VFP-Beispielapplikation Tastrade erläutern.

Die bei einem typischen Bestellvorgang anfallenden unstrukturierten Daten werden zunächst in Tabellenform gebracht:

wer wann was Einzelpreise liefern bis
Fa. Möller
Holzweg 17
D 12345 Berlin
01.11.96 2 Kästen mexikanisches Bier, 1 Flasche Champagner, 10 Gläser Salzhering 14,80; 98,00; 1,75 11.11.96

1. Normalform:

Der Schritt zur ersten Normalform heißt: Informationen separieren. Eine Spalte darf nicht mehrere Angaben gleichzeitig enthalten, wie dies in den Spalten „Was“ und „Einzelpreise“ der Fall ist. Wir nutzen die Gelegenheit um gleichzeitig Spalten, die zusammengesetzte Informationen enthalten, aufzuteilen.
Kunde Adresse PLZ Ort Ld Datum Mg Einheit Artikel Preis Lieferg.
Fa. Möller Holzweg 17 12345 Berlin D 01.11.96 2 Kasten mexikanisches Bier 14,80 11.11.96
Fa. Möller Holzweg 17 12345 Berlin D 01.11.96 1 Flasche Champagner 98,00 11.11.96
Fa. Möller Holzweg 17 12345 Berlin D 01.11.96 10 Glas Gläser Salzhering 1,75 11.11.96

2. Normalform

Zur zweiten Normalform gelangen wir, indem wir die Felder einer Tabelle in der ersten Normalform auf funktionale Abhängigkeit zu Teilen des Identifikationsschlüssels (nicht dem ganzen) hin untersuchen. Diese Tabelle hat einen zusammengesetzten Schlüssel. Welche Informationen brauchen wir, um eine Zeile dieser Tabelle eindeutig zu bezeichnen:

Eine funktionale Abhängigkeit liegt dann vor, wenn eine Spalte automatisch den Wert anderer Spalten festlegt. Zum Beispiel sind alle Spalten mit Adressangaben funktional von der Spalte „Kunde“ abhängig. Die Mengeneinheit und der Einzelpreis sind funktional vom Artikel abhängig. Die Menge und das gewünschte Lieferdatum sind vom Bestelldatum abhängig. Besonderheiten, etwa, daß ein Kunde unterschiedliche Adressen haben oder ein Artikel in verschiedenen Mengeneinheiten und zu verschiedenen Preisen ausgeliefert werden kann, oder daß ein und der selbe Kunde am gleichen Tag den selben Artikel mehrfach bestellen könnte, bleiben dabei zunächst unbeachtet. Dies sind Feinabstimmungen, die später an den normalisierten Tabellen vorgenommen werden.

Funktional von einem Schlüsselteil abhängige Spalten werden zu neuen Tabellen zusammengefasst. Der Teilschlüssel wird dann Identifikationsschlüssel der neuen Tabelle und bleibt als Fremdschlüssel in anderen Tabellen dienen.

Kunden
Kunde Name Adresse PLZ Ort Land
1
Fa. Möller
Holzweg 17
12345
Berlin
D

Artikel
Artikel Bezeichnung Einheit Preis
1
mexikanisches Bier Kasten
14,80
2
Champagner Flasche
98,00
3
Salzhering Glas
1,75

Bestellungen
Kunde Datum Menge Artikel Lieferung
1
01.11.96
2
1
11.11.96
1
01.11.96
1
2
11.11.96
1
01.11.96
10
3
11.11.96

3. Normalform und BCNF

Die dritte Normalform besagt, daß alle Nichtschlüssel-Attribute untereinander funktional unabhängig sein müssen. Die Boyce Codd Normalform (BCNF) geht einen Schritt weiter, indem sie dies für alle Attribute, also auch für Schlüsselattribute, fordert. Sie besagt, daß funktionale Abhängigkeiten nur noch zu Kandidatenschlüsseln bestehen dürfen. Das ist bei der Tabelle „Kunden“ offensichtlich nicht der Fall. Mit „Land“ und „Plz“ steht nämlich auch der Ort fest. „Land“ und „Plz“ zusammen ergeben für die Kundentabelle aber keinen Kandidatenschlüssel.

Befinden sich die anderen Tabellen in der dritten Normalform? Wenn wir die unstrukturierte Information vom Anfang zum Maßstab nehmen, dann nicht. Denn dort ist das Datum der Lieferung funktional abhängig von Kunde und Bestelldatum. Kunde und Bestelldatum zusammen bilden aber keinen Kandidatenschlüssel für die Tabelle „Bestellungen“.

Um zur dritten Normalform zu kommen, teilen wir also nochmal auf:

Kunden
Kunde Name Adresse Land PLZ
1
Fa. Möller
Holzweg 17
D
12345

Orte
Land PLZ Ort
D
12345
Berlin

Artikel
Artikel Bezeichnung Einheit Preis
1
mexikanisches Bier
Kasten
14,80
2
Champagner
Flasche
98,00
3
Salzhering
Glas
1,75

Bestellungs-Kopfdaten
Bestellung Kunde Datum Lieferung
1
1
01.11.96
11.11.96

Bestellpositionen
Bestellung Position Menge Artikel
1
1
2
1
1
2
1
2
1
3
10
3

Wir mussten der Tabelle „Orte“ keinen Identifikationsschlüssel hinzufügen, da mit „Land“+“PLZ“ ein, wenn auch zusammengesetzter Identifikationsschlüssel existiert. Bei der Aufteilung der Tabelle „Bestellungen“ hätten wir ebenso vorgehen können. Das hätte allerdings dazu geführt, daß „Kunde“ und „Datum“ als zusammengesetzter Fremdschlüssel in jeder Bestellposition vorgekommen wäre. Mit der Einführung des Primärschlüssels „Bestellung“ haben wir zugleich ermöglicht, daß ein Kunde an einem Tag mehrere Bestellungen aufgeben kann.

Literaturhinweise