Session D-SQL2

SQL und Referentielle Integrität

Georg Emrich
KHEOPS GmbH


Einführung

Referentielle Integrität (RI) fängt beim  Datenbankdesign an.  Ein gutes Datenbankdesign ist die Voraussetzung, Daten kosistent zu halten.

Gutes Datenbank–Design ist nicht nur mit SQL–Datenbanken wie MS-SQL, ORACLE oder SYBASE wichtig, sondern auch unter VFP. Die Session soll sich folglich nicht nur an (potentielle) Anwender von SQL–Datenbanken richten, sondern auch an Programmierer, die weiterhin auf die VFP–Datenbanken setzen.

Gutes“ Datenbankdesign  - was ist das ?

Auf diese Frage gibt es leider keine eindeutige Antwort. Ähnlich wie bei OOD ist Erfahrung hier sehr wichtig, wenn auch nicht unbedingt notwendig. Es gibt Leute, die sehr schnell eine Datenbank designen können, andere brauchen dafür „Jahre“ !

Woran liegt das ?

Ein wesentlicher  Grund hierfür liegt darin, daß keine definierten „Design – Dogmen“  existieren, sondern „nur“ Hilfswerkzeuge. Die wichtigsten hiervon sind „Normalisierung“ und „ER“– Modelle.  Innerhalb dieser Modelle ist für den individuellen Designer viel Raum, sich und seine Auffassungen einzubringen. Es führen sozusagen „viele Wege nach Rom“ !

Bloß – wo gehen wir lang ?

Wie packen wir’s an ?

Wenn man als Software–Anbieter den Auftrag erhält, in ein oder mehrere Arbeitsgebiete des Auftraggebers (so man einen hat ! ) EDV einzuführen, wird ein Prozeß in Gang gesetzt, an dessen Ende eine mehr oder weniger taugliche Software steht.

Da Anwender und Programmierer mit diesem „Endergebnis“ - so es überhaupt zustande kommt - nie ganz zufrieden sind, kann man aber auch von einem Zwischenergebnis reden.

Der Programmierer kommt z.B. auf zusätzliche Ideen, die man verwirklichen könnte, der Anwender möchte, nachdem er seine Erwartungen erfüllt sieht, das Projekt erweitern, oder ihm fällt etwas ein, was er „ganz vergessen“  und was „klar auf der Hand“ lag.

Dies führt zu Modifikationen - auch am Datenmodell. Schlagartig sind bereits eingeführte Strukturen nicht mehr zu gebrauchen und müssen durch neue ersetzt werden.

Nehmen wir an, im ursprünglichen EDV–Projekt sollte einfach ein Lagerort als Zusatz-information ohne funktionale Bedeutung angegeben werden. Nach Fertigstellung des Gesamtprojektes zeichnet sich aber die Notwendigkeit einer kompletten Lagerverwaltung ab.

Wenn man dieses Ziel umgesetzt hat, kommt der Kunde auf die Idee, einen Artikel an verschiedenen Orten lagern zu wollen u.s.w.

Dies kann auch schon während des Design–Prozesses und nicht nur an dessen vorläufigem (?) Ende erfolgen, was auf ein Modifizierung des Datenbankmodelles hinausläuft.

Man ist folglich bei der Gestaltung eines Datenbankmodelles auch mit den Fragen konfrontiert :

Wohin geht der Weg ?

Was ist zusätzlich denkbar ?

Die Konzeption eines Datenbankmodelles sollte folglich auch zukünftigen potentiellen Anwendungen Rechnung tragen. Dies ist in den meisten Fällen nicht nur eine Software- technische, sondern auch eine betriebswirtschaftliche Entscheidung.

Am Anfang war das Problem !

Am Anfang muß man sich als Programmierer mit der Problemstellung vertraut machen, oder noch besser gesagt: nach dem Problem fahnden !

Man muß die „Informationsinfrastruktur“ des abzubildenden Arbeitsbereiches kennenlernen, Formulare, Berichte, Blätter, Arbeitsabläufe, Informationsbroschüren, ... kurz, sämtliche Daten sammeln.

Danach muß man sie sich erklären lassen ... Dazu sollte man jemanden finden, der hiervon etwas versteht und bereit ist oder damit beauftragt wurde, sich abschließend zu äußern. Letzteres ist ein potentielles Hauptproblem.

Diese Informationen sollten kritisch hinterfragt werden. Insbesondere ist relevant, wie häufig die Informationen einer Änderung unterliegen, wo sie abgefragt werden, ob kritische Antwortzeiten existieren und welche Fragen an das System gestellt werden sollen.

Dies ist  ein essentiell wichtiger Punkt, da insbesondere die Konzeption der Abfragen kombiniert mit kritischen Anwortzeiten das Datenbankdesign entscheidend bestimmen sollten (input – output Analyse) !

Der nächste Schritt ist, dieses „Informationschaos“ zu systematisieren. Zusammenhängende Informationen sollten – ähnlich dem OOD - als Properties (Attribute) Objekten (Entitäten ) zugeordnet werden. Diese Entitäten entsprechen weitgehend den „Tabellen“, die Attribute den Tabellenspalten. Ähnlich dem OOD sollten hier schon Methoden oder Regeln erkannt werden. Beispielsweise in der Entität „Kunde“ darf das Attribut „Name“ nie leer sein, der VK muß immer höher sein als der Ek u.s.w.. In diesem Schritt sollte den Attributen auch eine sog. „Domain“ zugeordnet werden.

Dies läßt sich nach Foxpro mit der Bezeichnung „TYP“ übertragen. Es gibt nur einen wesentlichen Unterschied: SQL - „Domains“ kann  man selbst definieren !

Zu jeder Entität sollte ein sie eineindeutig charakterisierender Schlüssel definiert sein. Dieser Schlüssel sollte bestimmte Kriterien erfüllen :

  • Er sollte eindeutig eine Entität unveränderlich charakterisieren
  • Kürze, Schreibbarkeit
  • laufende Zuteilbarkeit

Beispiel: Das Tupel  Kunde_Schlüssel(Nachmane,Vorname,Geburstort,Geburtsdatum) ist mit hoher Wahrscheinlichkeit eindeutig. Jedoch eignet es sich nicht als eindeutiger Schlüssel, dem sogenannten Primary Key:

  • Die Schlüsselfelder selbst unterliegen Veränderungen (Schreibfehler )
  • Von einem „kurzen, schreibbaren“ Schlüssel kann man nicht mehr reden

Bei  obigem PK handelt es sich aber eindeutig um einen „natural key“, einen Schlüssel, der sich direkt aus den Attributen ergibt. Ein anderes Beispiel für einen solchen Schlüssel ist die PLZ für eine Straßen / Hausnummern / Ort - Kombination. Hier sind wir bei einem interessanten Vergleich angekommen: die Postleitzahlen haben sich vor 3 Jahren geändert. Hatte ein System auf den PK PLZ für einen Ort vertraut, gab es danach Probleme.

Die Lösung, dies zu umgehen, ist der sog. „surrogat Key“, ein rein artifizieller Schlüssel, wie z.B. eine hochgezählte Nummer.

Die einzelnen Tabellen werden in Beziehung zueinander gesetzt. Diese Beziehung nennt man ER–Modell ( Entity – Relationship ). Dazu werden die Beziehungen einzelner Tabellen zueinander untersucht und modellhaft abgebildet. Es ist sinnvoll, spätestens hier über ein entsprechendes Design–Tool zu verfügen. Egal, ob es sich um triggerbasiernde oder deklarative Systme handelt, werden diese Beziehungen immer zwischen einer „Tochtertabelle“ und einer „Vatertabelle“ über eine FK – PK Relation abgebildet.

Diese Beziehungen sind in vier „Grundtypen“ abbildbar:

  • optinal unique
  • optinal multible
  • mandatory unique
  • mandatory multible

Die Integrität stellt sicher, daß diese Beziehungen nicht verletzt werden: einmal als sog. „EI“ auf Tabellenebene und als „RI“ zwischen den Tabellen. Sie stellt z.B. automatisch sicher, daß zu jeder Rechnungsposition ein Rechnungskopf vorhanden sein muß ! ( man erinnere sich an Fox 2.6 ).

Was passiert, wenn die gesamte Rechnung gelöscht wird, also eine Änderung nicht wie oben in den „Sohn- oder Tochter“ - Tabellen erfolgt, sondern direkt in der „Vatertabelle“ ?

Auch hier ist die RI bedroht. Um darauf reagieren zu können, werden für Veränderungen an der „Vatertabelle“ sog. RI–Aktionsregeln definiert ( SQL- 92 ). Diese sind :

  • NO ACTION  ( RESTRICT )
  • CASCADE
  • SET NULL
  • SET DEFAULT

Normalisierung

Es gibt fünf Normalisierungsgrade. Alle beruhen darauf,  Entitäten „sinnvoll“ aufzutrennen und auf mehrere Tabellen zu verteilen. Dabei sollten keine Informationen verlorengehen          ( „non-loss decomposition“ ) und die aufgetrennte Information immer so verfügbar sein, als hätte die Trennung nie stattgefunden  ( „joins“ ).

Was ist aber „sinnvoll“ ?

Um dies entscheiden zu können, sollte man sich mit den Normalisierungsgraden vertraut machen :

  • Erste Normalform
  • Zweite Normalform
  • Dritte Normalform
  • Vierte Normalform
  • Fünfte Normalform

Also alles ganz einfach ?

Bringe alles in die fünfte Normalform und es kann nichts mehr passieren...  Zumindest für die Kriterien der Erweiterbarkeit und der DB–Konsistenz stimmt das auch – aber man schafft sich  neue Probleme !

  • Performance: Man überlege sich, die Entität „Kunde“ in die fünfte Normalform zu bringen....
  • Verständnis des ER – Modells.
  • Zeit und Kosten+

Was nun ?

Gutes Datenbankdesign charakterisiert sich letztlich durch die folgenden Punkte :

  • Datenbanken sind vollständig dokumentiert
  • Die Datenkonsistenz ist gewährleistet
  • Performance ist optimiert
  • Leicht zu gestaltende „intuitive“ Abfragen
  • Nachvollziehbarkeit

Schlechtes Datenbankdesign bedeutet hingegen :

  • Abfragen sind unverständlich, fehlerintensiv und langwierig
  • Datenbanken sind nicht dokumentiert
  • Dateninkonsistenz  ist möglich
  • Daten müssen ständig redundant in unterschiedliche Tabellen eingetragen werden.
  • Erweiterbarkeit der Programmfunktionalität wird durch das Datenmodell eingeschränkt oder verhindert.

sowie

  • Man darf es niemandem zeigen ....

Datenbankdesign ist hauptsächlich eine interne Kosten–Nutzen-Rechnung des Programmierteams oder der Firma. Die Konsistenz der wichtigen Daten muß von der Datenbank durch RI/EI gewährleistet werden können. Dazu ist gutes Datenbankdesign absolut notwendig. Leider führen viele Wege nach Rom.

Was wir haben, sind Hinweisschilder, denen man folgen sollte und Kriterien wie „der schnellste“, der „kürzeste“ oder der „preiswerteste“ Weg. Danach kann man sich richten.

Wenn man sich auf die Reise begibt, sollte man sich auch die entsprechenden Tools leisten – „zu Fuß“ ist der Weg lang und steinig.

Gutes Design ist also – wie üblich – eine Preisfrage !