Relationale Datenbanken und SQL. 9783827320858, 3827320852


241 93 3MB

German Pages 385 Year 2004

Report DMCA / Copyright

DOWNLOAD PDF FILE

Table of contents :
Relationale Datenbanken und SQL......Page 3
2.4.7 Das Kreuzprodukt......Page 5
3.2.14 Übungsaufgaben......Page 6
4.3.9 Übungsaufgaben......Page 7
7.1.2 Transaktionen in SQL......Page 8
9.3.5 Abfragen......Page 9
Stichwortverzeichnis......Page 10
Vorwort zur dritten Auflage......Page 11
Vorwort zur zweiten Auflage......Page 13
Vorwort zur ersten Auflage......Page 15
Hinweise des Herstellers zu den Testversionen......Page 17
1 Datenbanken und Datenbanksysteme......Page 19
1.1 Zentralisierung der Datenhaltung......Page 20
1.2 Die Datenbankarchitektur nach ANSI-SPARC......Page 21
1.3 Integritätsregeln......Page 24
1.4 Architektur von Datenbanksystemen......Page 26
1.5.1 Interaktive Manipulation des Datenbankschemas......Page 29
1.5.2 Interaktive Datenmanipulationssprache......Page 30
1.5.3 Bildschirmorientierte Datenmanipulationssprache......Page 31
1.5.4 Berichtsgenerator......Page 32
1.5.5 Berechnungsvollständige Sprache mit Zugriff auf das Datenmodell......Page 33
2 Einführung in das relationale Datenmodell......Page 35
2.1.1 Attribute......Page 36
2.1.2 Domänen......Page 37
2.1.3 Tupel......Page 40
2.1.4 Relationenschema und Relationen......Page 41
2.2.1 Primärschlüssel und Entitätsintegrität......Page 44
2.2.2 Fremdschlüssel und referenzielle Integrität......Page 45
2.3 Einführung in die Fallstudie (Versandhandel)......Page 47
2.4 Relationenalgebra......Page 48
2.4.1 Die Auswahl (Selektion)......Page 49
2.4.2 Die Projektion......Page 52
2.4.3 Umbenennung von Attribut-Bezeichnern......Page 53
2.4.4 Adjunktion virtueller Spalten......Page 55
2.4.5 Gruppierung von Daten......Page 56
2.4.6 Der Verbund (Join)......Page 59
2.4.7 Das Kreuzprodukt......Page 65
2.4.8 Der äußere Verbund (Outer Join)......Page 67
2.4.9 Mengenoperationen......Page 70
2.4.10 Übungsaufgaben......Page 71
Beispiele für I-Marken......Page 73
I-Marken in Relationen......Page 75
Verbund unter Verwendung von Nullmarken......Page 77
2.5.3 Dreiwertige Logik......Page 78
2.5.4 Übungsaufgaben......Page 79
2.6.1 Multimengen und Tabellen......Page 80
2.6.8 Der natürliche Verbund und der äußere Verbund......Page 81
2.6.11 Anwendung der Tabellenoperationen auf Relationen......Page 82
2.6.12 Übungsaufgaben......Page 83
2.7 Indexe in relationalen Datenbanken......Page 84
2.7.1 Übungsaufgaben......Page 86
3.1 Anwendungsentwicklung, Prozess- und Datenmodell......Page 87
3.2.2 Abhängige Entität......Page 92
3.2.4 Attribut......Page 93
3.2.7 Geschäftsregeln......Page 94
3.2.8 Schlüssel......Page 95
3.2.9 ER-Diagramme......Page 97
3.2.10 Kardinalitäten von zweistelligen Beziehungstypen......Page 99
3.2.11 Domänen......Page 102
3.2.12 Fallbeispiel: Versandhandel als ER-Modell......Page 103
3.2.13 Umsetzung eines ER-Modells in ein relationales Datenmodell......Page 104
3.3 Elemente der UML......Page 111
3.3.1 ER-Diagramme und UML-Klassendiagramme......Page 113
3.3.2 Aggregation und Komposition in UML......Page 114
3.3.3 Das Vererbungskonzept......Page 116
3.3.4 Übungsaufgaben......Page 121
3.4 Normalformen in relationalen Datenbanken......Page 122
3.4.1 Funktionale Abhängigkeiten......Page 123
3.4.2 Schlüssel......Page 126
3.4.3 Normalformen, vereinfachte Version......Page 128
3.4.4 Beispiel für eine Normalisierung......Page 133
3.4.5 Normalformen, exakte Version......Page 139
3.4.6 Übungsaufgaben......Page 140
3.4.7 Die Boyce-Codd-Normalform (BCNF)......Page 141
3.5 Qualitätskriterien für den Datenbankentwurf......Page 144
3.5.2 Logisches Datenmodell als Relationenschema......Page 145
3.5.5 Namenskonventionen......Page 146
3.6.1 Bestimmung eines Mengengerüsts für die Datenbank......Page 147
3.6.4 Datensicherungskonzept......Page 148
3.6.6 Historienführung......Page 149
3.6.7 Auswahl eines Datenbank-Verwaltungssystems......Page 150
4.1.1 Ein kleiner Überblick über die Historie von SQL......Page 151
4.1.2 Elemente von SQL......Page 152
4.2 Schemadefinition......Page 154
4.3 DDL: Datendefinition mit SQL......Page 155
4.3.1 Datentypen und Domänen......Page 156
4.3.2 Datentypen in SQL......Page 158
4.3.3 Operationen mit Datentypen......Page 161
4.3.4 Repräsentation der Datentypen......Page 163
4.3.5 CREATE TABLE......Page 165
4.3.6 Assertions......Page 175
4.3.7 Entfernung von Datenbankobjekten......Page 176
4.3.8 CREATE INDEX......Page 177
4.3.9 Übungsaufgaben......Page 178
5.1.1 Dateneingabe......Page 181
5.1.3 Daten ändern......Page 184
5.1.4 Daten löschen......Page 186
5.2.1 SELECT-Anweisung und Abfrage-Anweisung......Page 188
5.2.2 SELECT-Anweisung mit Projektion......Page 189
5.2.3 Sortieren der Ergebnistabelle......Page 190
5.2.4 SELECT mit Projektion und Selektion......Page 191
5.2.5 SELECT mit BETWEEN, IN, LIKE, SIMILAR......Page 198
5.2.6 SELECT mit virtuellen Spalten......Page 202
5.2.7 Funktionen für virtuelle Spalten......Page 204
5.2.8 SELECT mit Gruppenbildung......Page 209
5.2.9 SELECT mit GROUP BY......Page 212
5.2.10 SELECT mit GROUP BY und HAVING......Page 216
5.2.11 Reihenfolge der Komponenten der SELECT-Anweisung......Page 218
5.3.1 Tabellen und Tabellenalias......Page 219
5.3.2 Der innere Verbund......Page 220
5.3.3 Verbindung einer Tabelle mit sich selbst......Page 225
5.3.4 Outer Join......Page 226
5.4.1 Unterabfragen, die einen Wert liefern......Page 229
5.4.2 Unterabfragen, die eine Relation liefern......Page 232
5.4.4 Korrelierte Unterabfrage......Page 237
5.4.5 EXISTS versus IN......Page 239
5.4.6 Unterabfragen in der CREATE TABLE-Anweisung......Page 240
5.5 Mengenoperationen......Page 241
6 Datensichten in SQL......Page 245
6.2 Verhalten von Datensichten bei Abfragen......Page 246
6.3 Datenmanipulationen an Datensichten......Page 248
6.4 Datensichten mit virtuellen Spalten......Page 249
6.5 Änderbarkeit von Daten über Datensichten......Page 250
7.1 Transaktionen in Datenbanken......Page 253
7.1.1 Eigenschaften von Transaktionen......Page 254
7.1.2 Transaktionen in SQL......Page 256
7.1.3 Parallele Ausführung von Transaktionen......Page 259
7.1.4 Sperrmechanismen......Page 261
7.1.5 Isolation-Level in Transaktionen......Page 264
7.1.6 Explizite Sperrung mit LOCK TABLE......Page 266
7.1.7 Deadlock......Page 267
7.2.1 Allgemeine Zugangsprivilegien......Page 268
7.2.2 Objektbezogene Privilegien......Page 269
7.2.3 Rücknahme von Privilegien......Page 271
7.3 Prozedurale Konzepte in SQL......Page 272
7.3.1 Datenbankprozeduren......Page 273
7.3.2 Funktionen in Datenbanken......Page 280
7.3.3 Trigger in Datenbanken......Page 284
7.3.4 Das Cursor-Konzept......Page 287
7.4 Strategien zur Konsistenzsicherung......Page 291
7.4.1 Statische Geschäftsregeln......Page 292
7.4.2 Dynamische Geschäftsregeln......Page 298
8.1 Der Systemkatalog im SQL-Standard......Page 301
8.2 Systemtabellen in SQL-Implementationen......Page 303
9 Objektorientierung und SQL......Page 311
9.1.2 Typen......Page 313
9.1.3 Vererbung......Page 316
9.1.4 Verhaltensvererbung und Polymorphismus......Page 317
9.1.5 Klassen und Extents......Page 318
9.1.6 Objektidentität und Gleichheit......Page 319
9.1.7 Kapselung......Page 320
9.2.1 Definition von Typen und Tabellen......Page 321
9.2.2 Konstruktoren für komplexe Typen......Page 323
9.2.3 Referenzen......Page 324
9.3 Objektrelationales Modell der Versanddatenbank......Page 325
9.3.1 Abstrakte Datentypen als Wertebereich für Attribute......Page 327
9.3.2 Komplexe Objekttypen und Objekttabellen......Page 329
9.3.3 Vererbung......Page 333
9.3.4 Referenzen......Page 334
9.3.5 Abfragen......Page 336
9.3.6 Eingebettete Objekttypen......Page 338
9.3.7 Schreiboperationen in Objekttabellen......Page 343
9.3.8 Object Views......Page 347
Aufgabe 2.2......Page 349
Aufgabe 2.5......Page 350
Aufgabe 3.2......Page 351
Aufgabe 3.4......Page 352
Aufgabe 3.6......Page 353
Aufgabe 3.7......Page 354
Aufgabe 4.2......Page 355
Aufgabe 5.4......Page 356
Aufgabe 5.11......Page 357
Aufgabe 5.18......Page 358
Aufgabe 5.26......Page 359
Aufgabe 5.33......Page 360
Aufgabe 5.39......Page 361
A.0.5 Kapitel 8......Page 362
B Syntaxnotation......Page 363
C.1 Domänendefinitionen......Page 365
C.2 Anlage der Tabellen......Page 367
MwStSatz......Page 369
Bestellung......Page 370
Position......Page 371
DaDa93......Page 373
Lans90......Page 374
Stic91......Page 375
Zehn85......Page 376
B......Page 377
D......Page 378
I......Page 379
M......Page 380
P......Page 381
S......Page 382
U......Page 383
Z......Page 384
Ins Internet: Weitere Infos zum Buch, Downloads, etc.......Page 0
© Copyright......Page 385
Recommend Papers

Relationale Datenbanken und SQL.
 9783827320858, 3827320852

  • 0 0 0
  • Like this paper and download? You can publish your own PDF file online for free in a few minutes! Sign Up
File loading please wait...
Citation preview

Sandini Bib

Relationale Datenbanken und SQL

Sandini Bib

Sandini Bib

Günter Matthiessen Michael Unterstein

Relationale Datenbanken und SQL

An imprint of Pearson Education München • Boston • San Francisco • Harlow, England Don Mills, Ontario • Sydney • Mexico City Madrid • Amsterdam

Sandini Bib

Bibliografische Information Der Deutschen Bibliothek Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über abrufbar. Die Informationen in diesem Produkt werden ohne Rücksicht auf einen eventuellen Patentschutz veröffentlicht. Warennamen werden ohne Gewährleistung der freien Verwendbarkeit benutzt. Bei der Zusammenstellung von Abbildungen und Texten wurde mit größter Sorgfalt vorgegangen. Trotzdem können Fehler nicht vollständig ausgeschlossen werden. Verlag, Herausgeber und Autoren können für fehlerhafte Angaben und deren Folgen weder eine juristische Verantwortung noch irgendeine Haftung übernehmen. Für Verbesserungsvorschläge und Hinweise auf Fehler sind Verlag und Herausgeber dankbar. Alle Rechte vorbehalten, auch die der fotomechanischen Wiedergabe und der Speicherung in elektronischen Medien. Die gewerbliche Nutzung der in diesem Produkt gezeigten Modelle und Arbeiten ist nicht zulässig. Fast alle Hardware- und Softwarebezeichnungen, die in diesem Buch erwähnt werden, sind gleichzeitig eingetragene Warenzeichen oder sollten als solche betrachtet werden. Umwelthinweis: Dieses Produkt wurde auf chlorfrei gebleichtem Papier gedruckt.

5 05

4

3 04

2

1

03

ISBN 3-8273-2085-2

© 2003 by Addison-Wesley Verlag, ein Imprint der Pearson Education Deutschland GmbH Martin-Kollar-Straße 10–12, D-81829 München/Germany Alle Rechte vorbehalten Einbandgestaltung: Hommer Design, Haar bei München Lektorat: Martin Asbach, [email protected] Korrektorat: Alexandra Müller, Oer-Erkenschwick Herstellung: Anna Plenk, [email protected] Satz: reemers publishing services gmbh, Krefeld, www.reemers.de Druck und Verarbeitung: Bercker, Kevelaer Printed in Germany

Sandini Bib

Inhaltsverzeichnis Vorwort zur dritten Auflage 11 Vorwort zur zweiten Auflage 13 Vorwort zur ersten Auflage 15 Hinweise zur CD 17 1 Datenbanken und Datenbanksysteme 1.1 Zentralisierung der Datenhaltung 1.2 Die Datenbankarchitektur nach ANSI-SPARC 1.3 Integritätsregeln 1.4 Architektur von Datenbanksystemen 1.5 Komponenten eines Datenbank-Verwaltungssystems 1.5.1 Interaktive Manipulation des Datenbankschemas 1.5.2 Interaktive Datenmanipulationssprache 1.5.3 Bildschirmorientierte Datenmanipulationssprache 1.5.4 Berichtsgenerator 1.5.5 Berechnungsvollständige Sprache mit Zugriff auf das Datenmodell 33

19 20 21 24 26 29 29 30 31 32

2 Einführung in das relationale Datenmodell 2.1 Aufbau relationaler Datenbanken 2.1.1 Attribute 2.1.2 Domänen 2.1.3 Tupel 2.1.4 Relationenschema und Relationen 2.1.5 Datenbankschema und Datenbank 2.2 Schlüssel, Primärschlüssel und Fremdschlüssel 2.2.1 Primärschlüssel und Entitätsintegrität 2.2.2 Fremdschlüssel und referenzielle Integrität 2.2.3 Übungsaufgaben 2.3 Einführung in die Fallstudie (Versandhandel) 2.4 Relationenalgebra 2.4.1 Die Auswahl (Selektion) 2.4.2 Die Projektion 2.4.3 Umbenennung von Attribut-Bezeichnern 2.4.4 Adjunktion virtueller Spalten 2.4.5 Gruppierung von Daten 2.4.6 Der Verbund (Join) 2.4.7 Das Kreuzprodukt

35 36 36 37 40 41 44 44 44 45 47 47 48 49 52 53 55 56 59 65

5

Sandini Bib

Inhaltsverzeichnis

2.5

2.6

2.7

2.4.8 Der äußere Verbund (Outer Join) 2.4.9 Mengenoperationen 2.4.10 Übungsaufgaben Nullmarken in Datenbanken 2.5.1 Die Behandlung von fehlenden Attributwerten 2.5.2 Verschiedene Arten von Nullmarken 2.5.3 Dreiwertige Logik 2.5.4 Übungsaufgaben Tabellen und Relationen 2.6.1 Multimengen und Tabellen 2.6.2 Der Distinct-Operator 2.6.3 Die Auswahl (Selektion) 2.6.4 Die Projektion 2.6.5 Umbenennung von Attribut-Bezeichnern 2.6.6 Adjunktion virtueller Spalten 2.6.7 Gruppierung von Daten 2.6.8 Der natürliche Verbund und der äußere Verbund 2.6.9 Das Kreuzprodukt 2.6.10 Multimengen-Operationen 2.6.11 Anwendung der Tabellenoperationen auf Relationen 2.6.12 Übungsaufgaben Indexe in relationalen Datenbanken 2.7.1 Übungsaufgaben

3 Datenbankentwurf 3.1 Anwendungsentwicklung, Prozess- und Datenmodell 3.2 Grundbegriffe des Entity-Relationship-Modells 3.2.1 Entität 3.2.2 Abhängige Entität 3.2.3 Entitätentypen und Entitätenmengen 3.2.4 Attribut 3.2.5 Beziehung 3.2.6 Beziehungstyp (Relationship Type) 3.2.7 Geschäftsregeln 3.2.8 Schlüssel 3.2.9 ER-Diagramme 3.2.10 Kardinalitäten von zweistelligen Beziehungstypen 3.2.11 Domänen 3.2.12 Fallbeispiel: Versandhandel als ER-Modell 3.2.13 Umsetzung eines ER-Modells in ein relationales Datenmodell 3.2.14 Übungsaufgaben

6

67 70 71 73 73 73 78 79 80 80 81 81 81 81 81 81 81 82 82 82 83 84 86 87 87 92 92 92 93 93 94 94 94 95 97 99 102 103 104 111

Sandini Bib

Inhaltsverzeichnis

3.3

Elemente der UML 3.3.1 ER-Diagramme und UML-Klassendiagramme 3.3.2 Aggregation und Komposition in UML 3.3.3 Das Vererbungskonzept 3.3.4 Übungsaufgaben 3.4 Normalformen in relationalen Datenbanken 3.4.1 Funktionale Abhängigkeiten 3.4.2 Schlüssel 3.4.3 Normalformen, vereinfachte Version 3.4.4 Beispiel für eine Normalisierung 3.4.5 Normalformen, exakte Version 3.4.6 Übungsaufgaben 3.4.7 Die Boyce-Codd-Normalform (BCNF) 3.5 Qualitätskriterien für den Datenbankentwurf 3.5.1 Konzeptuelles Modell 3.5.2 Logisches Datenmodell als Relationenschema 3.5.3 Physikalisches Schema für die Zieldatenbank 3.5.4 Normalformen 3.5.5 Namenskonventionen 3.6 Weitere Aufgaben bei der Einführung einer Datenbank 3.6.1 Bestimmung eines Mengengerüsts für die Datenbank 3.6.2 Datenübernahme 3.6.3 Datenschutzkonzept 3.6.4 Datensicherungskonzept 3.6.5 Verteilung der Daten und Verteilung der Verarbeitung 3.6.6 Historienführung 3.6.7 Auswahl eines Datenbank-Verwaltungssystems 4 Datendefinition in SQL 4.1 SQL und SQL-Standard 4.1.1 Ein kleiner Überblick über die Historie von SQL 4.1.2 Elemente von SQL 4.2 Schemadefinition 4.3 DDL: Datendefinition mit SQL 4.3.1 Datentypen und Domänen 4.3.2 Datentypen in SQL 4.3.3 Operationen mit Datentypen 4.3.4 Repräsentation der Datentypen 4.3.5 CREATE TABLE 4.3.6 Assertions 4.3.7 Entfernung von Datenbankobjekten 4.3.8 CREATE INDEX 4.3.9 Übungsaufgaben

111 113 114 116 121 122 123 126 128 133 139 140 141 144 145 145 146 146 146 147 147 148 148 148 149 149 150 151 151 151 152 154 155 156 158 161 163 165 175 176 177 178

7

Sandini Bib

Inhaltsverzeichnis

5 Datenmanipulation in SQL 5.1 Datenmanipulationen an einer Relation 5.1.1 Dateneingabe 5.1.2 Daten ansehen 5.1.3 Daten ändern 5.1.4 Daten löschen 5.2 SELECT-Anweisung mit einer Tabelle 5.2.1 SELECT-Anweisung und Abfrage-Anweisung 5.2.2 SELECT-Anweisung mit Projektion 5.2.3 Sortieren der Ergebnistabelle 5.2.4 SELECT mit Projektion und Selektion 5.2.5 SELECT mit BETWEEN, IN, LIKE, SIMILAR 5.2.6 SELECT mit virtuellen Spalten 5.2.7 Funktionen für virtuelle Spalten 5.2.8 SELECT mit Gruppenbildung 5.2.9 SELECT mit GROUP BY 5.2.10 SELECT mit GROUP BY und HAVING 5.2.11 Reihenfolge der Komponenten der SELECTAnweisung 5.3 Datenabfrage mit mehreren Relationen 5.3.1 Tabellen und Tabellenalias 5.3.2 Der innere Verbund 5.3.3 Verbindung einer Tabelle mit sich selbst 5.3.4 Outer Join 5.4 Unterabfragen 5.4.1 Unterabfragen, die einen Wert liefern 5.4.2 Unterabfragen, die eine Relation liefern 5.4.3 EXISTS 5.4.4 Korrelierte Unterabfrage 5.4.5 EXISTS versus IN 5.4.6 Unterabfragen in der CREATE TABLEAnweisung 5.5 Mengenoperationen

181 181 181 184 184 186 188 188 189 190 191 198 202 204 209 212 216

6 Datensichten in SQL 6.1 CREATE VIEW 6.2 Verhalten von Datensichten bei Abfragen 6.3 Datenmanipulationen an Datensichten 6.4 Datensichten mit virtuellen Spalten 6.5 Änderbarkeit von Daten über Datensichten 7 Konsistenz und Mehrbenutzerbetrieb 7.1 Transaktionen in Datenbanken 7.1.1 Eigenschaften von Transaktionen 7.1.2 Transaktionen in SQL

245 246 246 248 249 250 253 253 254 256

8

218 219 219 220 225 226 229 229 232 237 237 239 240 241

Sandini Bib

Inhaltsverzeichnis

7.2

7.3

7.4

7.1.3 Parallele Ausführung von Transaktionen 7.1.4 Sperrmechanismen 7.1.5 Isolation-Level in Transaktionen 7.1.6 Explizite Sperrung mit LOCK TABLE 7.1.7 Deadlock Zugriffsrechte und Rollen 7.2.1 Allgemeine Zugangsprivilegien 7.2.2 Objektbezogene Privilegien 7.2.3 Rücknahme von Privilegien 7.2.4 Rollen und Gruppen Prozedurale Konzepte in SQL 7.3.1 Datenbankprozeduren 7.3.2 Funktionen in Datenbanken 7.3.3 Trigger in Datenbanken 7.3.4 Das Cursor-Konzept Strategien zur Konsistenzsicherung 7.4.1 Statische Geschäftsregeln 7.4.2 Dynamische Geschäftsregeln

8 Der Systemkatalog 8.1 Der Systemkatalog im SQL-Standard 8.2 Systemtabellen in SQL-Implementationen 9 Objektorientierung und SQL 9.1 Das objektorientierte Datenbankmodell 9.1.1 Grundbausteine 9.1.2 Typen 9.1.3 Vererbung 9.1.4 Verhaltensvererbung und Polymorphismus 9.1.5 Klassen und Extents 9.1.6 Objektidentität und Gleichheit 9.1.7 Kapselung 9.1.8 Lebenszeit von Objekten 9.1.9 Beziehungen 9.2 Objektorientierung im SQL-Standard 9.2.1 Definition von Typen und Tabellen 9.2.2 Konstruktoren für komplexe Typen 9.2.3 Referenzen 9.3 Objektrelationales Modell der Versanddatenbank 9.3.1 Abstrakte Datentypen als Wertebereich für Attribute 9.3.2 Komplexe Objekttypen und Objekttabellen 9.3.3 Vererbung 9.3.4 Referenzen 9.3.5 Abfragen

259 261 264 266 267 268 268 269 271 272 272 273 280 284 287 291 292 298 301 301 303 311 313 313 313 316 317 318 319 320 321 321 321 321 323 324 325 327 329 333 334 336

9

Sandini Bib

Inhaltsverzeichnis

9.3.6 9.3.7 9.3.8

Eingebettete Objekttypen Schreiboperationen in Objekttabellen Object Views

338 343 347

A Ausgewählte Lösungen zu den Aufgaben B Syntaxnotation

349 363

C Beispieldatenbank C.1 Domänendefinitionen C.2 Anlage der Tabellen C.3 Tabellarische Darstellung der Relationen Literaturverzeichnis

365 365 367 369 373

Stichwortverzeichnis

377

10

Sandini Bib

Vorwort zur dritten Auflage Dieses Werk liegt nunmehr in der dritten Auflage vor. Die Erfahrungen, die wir als Autoren mit dem vorliegenden Buch in zahlreichen Lehrveranstaltungen und Firmenseminaren gewonnen haben, die Entwicklungen im SQL-Standard und bei den Datenbanksystemen, insbesondere, was die Umsetzung objektrelationaler Konzepte betrifft, haben uns motiviert, eine gründliche Überarbeitung vorzunehmen. Dabei wird an dem bisher bewährten Konzept und Aufbau festgehalten. Der SQL-Standard steht vor einer »Neuauflage«. Während die der bisherigen Auflage zugrunde gelegte Version SQL:1999 teilweise noch weit davon entfernt ist, in der realen Datenbanktechnologie umgesetzt zu werden, steht die Version SQL:200n ins Haus, wobei das n nach optimistischen Schätzungen eine 3 sein wird. Uns liegt eine Entwurfsversion dieses Standards vor, die wir vor allem in den Kapiteln 4 und 5 berücksichtigt haben. Im Kapitel 3 über den Datenbankentwurf haben wir die Abschnitte, die sich mit dem Entity-Relationship-Modell und mit UML beschäftigen, im Hinblick auf eine möglichst einheitliche Notation überarbeitet, die von einer Anzahl von Softwarewerkzeugen unterstützt wird. Im Abschnitt über Normalformen haben wir zu Gunsten besserer Verständlichkeit die Definitionen modifiziert und einige erläuternde Beispiele hinzugefügt. Neu hinzugekommen ist ein Abschnitt über Qualitätsanforderungen an den Datenbankentwurf – wir haben in der Praxis häufig beobachtet, dass die Fähigkeiten der Datenbanksysteme zur Überwachung der Datenintegrität nur zum Teil ausgenutzt werden, und möchten auf einen intensiveren Gebrauch der Möglichkeiten hinwirken. Aufgrund der gewachsenen Unterstützung objektorientierter Konzepte durch relationale Datenbanksysteme haben wir den entsprechenden Abschnitt in Kapitel 9 gründlich überarbeitet. Auf der anderen Seite ist das »rein« objektorientierte Datenbanksystem O2, auf das wir uns bisher in Abschnitt 9.4 bezogen haben, vom Markt verschwunden, weswegen wir diesen Abschnitt gestrichen haben. Ein Teil der vielen Detailänderungen geht auf Anregungen unserer Leserinnen und Leser zurück, für die wir uns hier noch einmal sehr herzlich bedanken. Wir möchten dazu ermuntern, uns weiterhin Anregungen und Kritik zukommen zu lassen, die dann zur weiteren Verbesserung dieses Produktes beitragen können. Unser Dank gilt Herrn Martin Asbach von der Verlagsgruppe Pearson Education für die engagierte Unterstützung dieser Neuauflage und Frau Anne Spranger für das sorgfältige Lektorat. Sehr dankbar sind wir Herrn Philipp von der Firma iAnywhere-Solutions, der uns wiederum die Beilage einer CD mit einer 60-Tage-Testversion des Datenbanksystems Adaptive Server Anywhere und einer Testversion des Power Designer ermöglicht hat, so dass unsere Leser alle SQL-Übungen und darüber hinaus die Entwurfsübungen auf dem eigenen Rechner nachvollziehen kön-

11

Sandini Bib

Vorwort zur dritten Auflage

nen. Auf der CD finden sich die entsprechenden SQL-Scripts, die wir ebenfalls mit Adaptive Server Anywhere erstellt haben, so dass die Beispiele im Text ohne weitere Anpassungen »laufen«. Ebenfalls dabei sind Skripte zur Erstellung einer OracleVersion unserer Beispieldatenbank und eine Version für MS-Access. Des Weiteren sind Scripts für die Anlage und Abfrage einer objektrelationalen Version unseres Beispiel enthalten. Bremen und Bremerhaven im März 2003 Günter Matthiessen: [email protected] Michael Unterstein: [email protected]

12

Sandini Bib

Vorwort zur zweiten Auflage Nicht ganz drei Jahre nach der ersten Auflage haben wir uns entschlossen, die zweite Auflage vollständig zu überarbeiten. Zum einen konnten so neuere Entwicklungen in die Überarbeitung einfließen. Im Kapitel über den Datenbankentwurf haben wir zusätzlich zu den »klassischen Entity-Relationship-Diagrammen« UML-Klassendiagramme als Beschreibung für relationale Datenbanken eingeführt und gezeigt, dass es auch im klassischen Anwendungsbereich der relationalen Datenbanken sehr wohl Anwendungen gibt, bei denen das Vererbungsprinzip produktiv angewandt werden kann. Zum anderen sind inzwischen objektrelationale SQL-Datenbanken auf dem Markt erhältlich, so dass durch Einbeziehung dieser Ansätze der Ausblick der ersten Auflage auf die objektorientierten Datenbanken näher an das Thema »SQL« herangerückt ist. Als letzte Entwicklung ist der schon seit etwa fünf Jahren diskutierte Standard SQL-3 jetzt unter der Bezeichnung »SQL:1999« verabschiedet worden. Wir haben uns in der Einführung in SQL jeweils auf den neuesten Standard bezogen. Nichtsdestotrotz ist dieses Buch keine enzyklopädische Einführung in SQL:1999, sondern eine Einführung in die Arbeit mit relationalen Datenbanken unter Verwendung von SQL. Außerdem haben wir uns aufgrund von Anregungen, die an uns herangetragen worden sind, und aus den Erfahrungen, die wir bei Seminaren mit dem Buch gesammelt haben, entschlossen, den Aufbau der ersten drei Kapitel zu ändern. Obwohl natürlich vor dem Arbeiten mit einer Datenbank ein professioneller Datenbankentwurf notwendig ist, scheint es uns doch sinnvoll zu sein, zuerst die Grundlagen der relationalen Datenbanken zu beschreiben und darzustellen, welche »Arbeitsmöglichkeiten« (Relationenalgebra) sie bieten. Bevor ein Architekt sich mit dem Entwurf eines Hauses befasst, muss er auch fundierte Kenntnisse über die möglichen Baumaterialien und ihre Eigenschaften haben. Wir haben auch viele Anfragen und Anregungen über E-Mail bekommen. Wir möchten uns für die Anregungen bedanken und die Leser auffordern, auch in Zukunft nicht mit Anfragen und Kritik zu sparen. Unser Dank für die sehr engagierte Unterstützung dieser überarbeiteten Neuauflage unseres Buchs gilt unserer Lektorin Frau Lauer. Frau Daenecke danken wir wiederum für das sorgfältige Korrektorat. Des Weiteren möchten wir unseren Dank der Firma Sybase, besonders Herrn Philipp, aussprechen. Aufgrund ihrer Unterstützung liegt dem Buch eine CD mit einer vollständigen Testversion des Datenbanksystems Sybase SQL Adaptive Server Anywhere Studio bei. Der Leser erhält dadurch anhand des Buches die Gelegenheit, alle SQL-Übungen auf dem

13

Sandini Bib

Vorwort zur zweiten Auflage

eigenen Rechner nachzuvollziehen. Unsere im Buch verwendete Beispieldatenbank ist ebenfalls mit SQL Anywhere realisiert worden, so dass alle Beispiele in den Kapiteln 4, 5, 6 und 7 ohne weitere Anpassungen »laufen«. Bremen und Bremerhaven im November 1999

Günter Matthiessen Michael Unterstein

14

Sandini Bib

Vorwort zur ersten Auflage Bunt, grafisch und vielfältig präsentiert sich die Datenverarbeitung heute dem Laien wie dem Experten. Ein paar Mausklicks, und schon hat man seine Probleme gelöst – komplizierte Datenreihen werden als Säulendiagramm oder mehrdimensional dargestellt, Verteilungsprobleme sind als Tortendiagramm veranschaulicht. Wer Informationen benötigt, »browst« durchs Internet und holt sich die Multimedia-Show auf den Arbeitsplatz. All diese Beispiele stehen für einen im Vergleich zu früher stark vereinfachten, intuitiven Zugriff auf Informationen aller Art. Dass diese verfügbar sind und sich nach verschiedensten Gesichtspunkten auswerten und darstellen lassen, muss allerdings erst einmal gewährleistet werden. Dafür gibt es Datenbanken. Richtig eingesetzt, eröffnen sie alle Möglichkeiten der Informationsverarbeitung. In unverstandener, unvollkommener Weise genutzt, verkommen sie zum Datenfriedhof, aus dem sich nach dem Zufallsprinzip taugliche oder unbrauchbare Informationen ziehen lassen. Dieses Buch erklärt Datenbanken aus der Sicht des Anwendungsentwicklers und des Benutzers. Es erläutert grundlegende Konzepte der Datenbanktechnologie und ihre Umsetzung bei der Entwicklung und Anwendung von praxistauglichen Informationssystemen. Im Mittelpunkt stehen dabei die relationalen Datenbanken. Systeme, die auf dem relationalen Datenmodell basieren, haben mittlerweile einen hohen Reifegrad erlangt, der es gestattet, verlässliche Informationssysteme beliebiger Größenordnungen zu erstellen und zu erhalten. Die dabei gesetzten Maßstäbe werden von anderen Systemen bisher nicht erreicht. Andererseits haben manche Forderungen des relationalen Datenmodells noch keine durchgängige Umsetzung in verfügbaren Systemen erfahren, so dass hier noch erhebliches Entwicklungspotenzial besteht. Unbestreitbar hat das relationale Datenmodell einige Mängel, die seine Brauchbarkeit speziell für die Verarbeitung komplexer Datenstrukturen einschränken. Hier setzen neue Konzepte, speziell die Objektorientierung, an. Ein Einblick in die Fundamente der relationalen wie der objektorientierten Technologie – wie er auch in diesem Buch gegeben wird – zeigt, dass eine differenzierte Beurteilung der Konzepte im Hinblick auf den Einsatzzweck und nicht die euphorische Identifizierung mit dem »Neuen« oder dem »Bewährten« das Richtige ist. Das Relationenmodell enthält Regeln für die Abbildung von interessierenden Ausschnitten der Realität in einer Datenbank und beschreibt Möglichkeiten der Verarbeitung solcher Abbilder zum Zweck der Informationsgewinnung. Erst die Kenntnis dieser theoretischen Grundlagen versetzt den Entwickler – zum Teil aber auch den Anwender – in die Lage, aussagefähige und stabile Datenbanken zu schaffen oder auszuwerten. Dabei geht es um mehr als das Ablegen und Wiederfinden von

15

Sandini Bib

Vorwort zur ersten Auflage

Daten. Ebenso sollten die zwischen verschiedenen Daten existierenden logischen Zusammenhänge in der Datenbank ihr Abbild finden. Nur dann kann langfristig gewährleistet werden, dass die gesammelten Daten »konsistent« – also widerspruchsfrei und aussagefähig – bleiben. Die Autoren haben sich das Ziel gesetzt, den Lesern das für die Gestaltung von Informationssystemen und den Umgang mit Datenbanken erforderliche Wissen zu vermitteln. Wir legen dabei gleichermaßen Wert auf theoretische Exaktheit wie auf Anschaulichkeit und Verständlichkeit. Eine durchgängig verwendete Fallstudie liefert das Anschauungsmaterial. Zahlreiche Übungsaufgaben geben dem Leser Gelegenheit, das angeeignete Wissen zu festigen und den Grad des erworbenen Verständnisses selbst zu überprüfen. Dieses Buch ist sowohl zum Selbststudium wie auch als Begleitscript für Seminare und Lehrveranstaltungen in Betrieben und Hochschulen geeignet. Es richtet sich vor allem an 왘 Entwickler von Datenbanken für betriebliche Anwendungen, darunter System-

analytiker und Anwendungsprogrammierer, 왘 Verantwortliche der betrieblichen Datenverarbeitung, darunter Datenbank-

administratoren, 왘 EDV-Organisatoren, die Endanwender beim Zugriff auf zentrale Daten beraten

und betreuen, 왘 Nutzer von existierenden Datenbanken, die über flexibel einsetzbare Arbeits-

platzsoftware auf eine Datenbank zugreifen, sowie 왘 Studenten an Fachhochschulen und Universitäten mit Studienschwerpunkten

im Bereich Informatik oder Wirtschaftsinformatik. Das vorliegende Werk geht auf zwei Grundlagen zurück: zum einen auf das seit vielen Semestern im Einsatz befindliche und beständig fortentwickelte Vorlesungsscript Matthiessen: Datenbanken und Informationssysteme, zum anderen auf das Buch Finkenzeller, Kracke, Unterstein: Systematischer Einsatz von SQL/ORACLE, das als eines der ersten deutschsprachigen Bücher speziell zu ORACLE 1989 bei Addison-Wesley erschienen ist. Beide Autoren bringen nun erstmals gemeinsam ihre zahlreichen Erfahrungen in Datenbankpraxis, Veröffentlichung und Lehre zu Papier. Unser Dank für die engagierte Unterstützung unseres Buchs gilt Herrn Pereira und Frau Lucht beim Verlag Addison Wesley Longman. Frau Daenecke danken wir für das sorgfältige Lektorat. Kommentare, Anregungen und Kritik bitten wir per E-Mail an die Autoren ([email protected] bzw. [email protected]) oder an den Verlag zu senden. Bremen und Bremerhaven im Januar 1997

Günter Matthiessen Michael Unterstein

16

Sandini Bib

Hinweise zur CD Die CD enthält eine Testversion des Datenbanksystems Sybase SQL Adaptive Server Anywhere Studio. Interessierte Leserinnen und Leser können damit auf ihrem Rechner die Beispieldatenbank installieren und bearbeiten. Wir haben außerdem im Verzeichnis \Versand verschiedene Versionen unserer Beispieldatenbank abgelegt. Wer mag, kann auch unter Oracle oder Access üben und unsere Ausführungen verfolgen. Diejenigen unter den Leserinnen und Lesern, die das Buch als Lehrunterlage in eigenen Kursen und Seminaren verwenden wollen oder die aus anderen Gründen eigene Präsentationen vorbereiten müssen, finden im Verzeichnis \Grafik die Grafikdateien, die wir in unseren Text eingebunden haben. Sie stehen Ihnen unter dem Vorbehalt des Copyrights und mit der Verpflichtung zum korrekten Zitieren zur Verfügung.

Haftungsausschluss Alle Beispiele, die auf der CD enthalten sind, sind reines Übungsmaterial. Wir haben sie mit der größten Sorgfalt erstellt und getestet. Für mögliche Probleme, die aus ihrem Einsatz durch den Leser entstehen, übernehmen wir keine Verantwortung. Dasselbe gilt für die Datenbanksoftware Adaptive Server Anywhere und Power Designer. Sie ist eine freundliche Beigabe der Firmen Sybase und iAnywhere Solutions und dient lediglich zur Unterstützung des Lernens mit dem Buch. Für Probleme, die aus jedwedem Gebrauch des Produkts entstehen, sind weder wir noch die genannten Firmen zur Verantwortung zu ziehen.

Hinweise des Herstellers zu den Testversionen Sehr geehrte Leserinnen und Leser, wir freuen uns, Ihnen mit der aktuellen Ausgabe des vorliegenden Buches eine 60Tage- Vollversion des Datenbankproduktes Sybase SQL Anywhere Studio 8.0 zur Verfügung stellen zu dürfen.

17

Sandini Bib

Hinweise zur CD

Die Datenbank Adaptive Server Anywhere ist sowohl auf Windows-Plattformen (Windows NT, Windows 2000, Windows XP, Windows CE) als auch auf Linux installierbar. Die Installationsroutinen liegen in separaten Ordnern auf der CD bereit. Ab dem Zeitpunkt der Installation steht die Datenbank mit dem vollen Funktionsumfang zur Verfügung. Damit können Sie die Übungen des Buches sofort in die Tat umsetzen. SQL Anywhere Studio beinhaltet darüber hinaus die UltraLite-Datenbank, die auf Pocket PC, Palm OS oder Symbian lauffähig ist. Adaptive Server Anywhere eignet sich sowohl für Einzelplatz- als auch Mehrbenutzeranwendungen. Die Datenbank bietet Funktionalitäten der High-End Enterprise Datenbanken wie z.B. echte Transaktionsverarbeitung, Stored Procedures und Java in der Datenbank. ASA benötigt dafür aber im laufenden Betrieb keine Administration. Das System bietet mit seinen eingebauten Replikationsmechanismen eine ideale Technologie zum automatischen Datenabgleich zwischen zentralen Datenbanken und Außendienstsystemen. Sybase Adaptive Server Anywhere ist aufgrund ihrer hervorragenden Eigenschaften mit einem Marktanteil von 73 % Marktführer im Bereich Mobile Computing. Sollten Sie weitere Informationen zum Produkt Sybase Adaptive Server Anywhere benötigen, finden Sie diese unter www.ianywhere.de. Für technische Fragen und kostenlosen Support registrieren Sie sich bitte im Sybase Developer Netzwerk unter http://sdn.sybase.com. Viel Erfolg bei der Arbeit mit diesem Buch und vor allem mit der Datenbank Sybase Adaptive Server Anywhere wünscht Ihnen Tobias Philipp Business Development Manager Europa IAnywhere Solutions – A Sybase Company

18

Sandini Bib

1

Datenbanken und Datenbanksysteme

Der Computer ist ursprünglich als das eingeführt worden, was er heute noch im Englischen bedeutet, nämlich als Rechner. Er wurde zur Berechnung umfangreicher technisch-wissenschaftlicher Systeme benutzt. Aber schon in den 60er-Jahren verbreitete sich der Computer vorwiegend als Datenverarbeitungsanlage. Dies hat folgende Ursachen: 왘 Die Daten stehen im Mittelpunkt des Interesses der Anwender. 왘 Es sind vielfältige maschinelle Auswertungen von Daten möglich. 왘 Geschäftsprozesse führen zu Änderungen der entsprechenden Daten.

Die Daten sind nicht mehr nur Eingaben, Zwischenergebnisse und Ausgaben von Programmen, sondern sie haben auch eine eigene Existenz unabhängig von Programmen. Ein Kunde hat auch dann einen Namen und eine Adresse, wenn wir ihm gerade keine Rechnung schicken. Dies führte schon Ende der 60er-Jahre zur Entwicklung von Datenbanksystemen. Hier wird zwischen die Daten und das Programm, das die Daten verarbeitet, ein Datenbank-Verwaltungssystem (abgekürzt DBMS für Data Base Management System) gesetzt, das alle Zugriffe auf die Daten verwaltet. Im Deutschen wird das Datenbank-Verwaltungssystem – sprachlich nicht korrekt – häufig als Datenbanksystem bezeichnet. Der Datenbankansatz führt zu folgenden Eigenschaften: 왘 Die Daten werden in einem Format abgelegt, so dass ihre Struktur unabhängig

von speziellen Programmen vom DBMS interpretiert werden kann. 왘 Das DBMS ist der einzige Prozess, der unmittelbar auf die Daten zugreifen und

sie manipulieren darf. Auswertungen und Verarbeitungsprogramme laufen grundsätzlich über das DBMS. 왘 Das DBMS organisiert einen Mehrbenutzerbetrieb unter Verwendung von indi-

viduellen Zugriffsrechten. 왘 Das DBMS organisiert die Koordination von Zugriffen von mehreren Benut-

zern gleichzeitig. 왘 Das DBMS enthält Maßnahmen zur Unterstützung der Datenkonsistenz durch

Mechanismen der Datensicherung und der Wiederherstellung der Daten nach einer Betriebsstörung. PC-DBMS erfüllen hiervon in der Regel nur den Punkt 1. Für operative Datenbanken in Unternehmen sind dagegen die weiteren Punkte unverzichtbar.

19

Sandini Bib

1 Datenbanken und Datenbanksysteme

1.1 Zentralisierung der Datenhaltung Ein wichtiger Grund für die Einführung von Datenbanken im Unternehmen ergibt sich aus der betriebswirtschaftlichen Notwendigkeit, die gesamten Unternehmensdaten so zu organisieren, dass für die gesamten Daten eine verantwortliche Stelle vorhanden ist (Zentralisierung der Datenhaltung). Das muss nicht heißen, dass eine Stelle für alle Daten verantwortlich ist, sondern dass es einen Verantwortlichen (»Datenbankadministrator«) gibt, der für die gesamte Datenorganisation verantwortlich ist und der mit der Unternehmensführung gemeinsam festlegt, wer für einzelne Datenbereiche (z.B. Personal, Kunden, Produktionsdaten, Lieferantendaten, Lagerhaltung, ...) verantwortlich ist. Durch das Benutzen einer Datenbank ergibt sich eine Reihe von Vorteilen, unter anderem: 왘 Verringerung bzw. systematische Kontrolle der Redundanz

So müssen z.B. Artikeldaten nur an einer Stelle gepflegt werden. Falls sie dennoch mehrfach (auf verschiedenen Knoten) gespeichert werden sollen, hat das DBMS dafür zu sorgen, dass alle Kopien auf demselben Stand sind. 왘 Konsistenzüberprüfung vom DBMS

So kann das DBMS z.B. verhindern, dass Kundendaten gelöscht werden, wenn noch Rechnungen offen sind. Bei der Erfassung eines Auftrags stellt das DBMS hingegen sicher, dass eine eingegebene Kundennummer auch tatsächlich einem Kunden zugeordnet ist. Eine Kundennummer in der Auftragstabelle, der kein Kundensatz in der Kundentabelle entspricht, wäre nämlich eine Verletzung der Konsistenz der Datenbank. Diese Überprüfung durch das DBMS ist auch durch unabsichtlich oder böswillig fehlerhafte Programme nicht zu umgehen. 왘 Auswertungen nach neuen Gesichtspunkten werden möglich (da Daten zentral vor-

handen sind!) Das Problem des »Anwendungsstaus« kann dadurch abgemildert werden, dass die Datenbank über interaktive Abfrageprogramme nach beliebigen Gesichtspunkten durchsucht werden kann. Hier tritt andererseits das Problem des Datenschutzes auf. 왘 Datenunabhängigkeit

Erweiterungen des Datenbankaufbaus erfordern keine Änderung von Programmen. Hierauf gehen wir näher in Abschnitt 1.2 ein.

20

Sandini Bib

Datenbankbeschreibung

Daten

Daten

Datenbank-Verwaltungssystem

Programm 1

Programm 2

Auswertung

Abbildung 1.1: Datenbank-Verwaltungssystem zwischen Programm und Daten

1.2 Die Datenbankarchitektur nach ANSI-SPARC ANSI / X3 /SPARC / SGDBMS: 왘 ANSI:American National Standards Institute 왘 X3:Computer and Information Processing 왘 SPARC: Standards Planning and Requirements Committee 왘 SGDBMS:Study Group on Data Base Management Systems

Die ANSI/X3/SPARC-Gruppe hat 1975 einen Report erstellt, wie ein Datenbanksystem aufgebaut sein soll (siehe Abbildung 1.2). Dabei ist die dort beschriebene Architektur unabhängig von der Frage, ob das dem Datenbanksystem zugrunde liegende Datenbankmodell relational oder netzwerkartig oder an einem anderen Modell orientiert ist.

21

Sandini Bib

1 Datenbanken und Datenbanksysteme

Externes Schema: Präsentation Kundenverwaltung

Auftragsverwaltung

Artikelverwaltung

Konzeptionelles Schema: Information

Unternehmens-Datenmodell (Daten, Integritätsregeln)

Internes Schema: Daten-Speicherung

RDBMS 1

RDBMS 2

Datei-System

Abbildung 1.2: ANSI-SPARC-Architektur

Konzeptionelles Schema Im Zentrum steht das konzeptionelle Schema. Dieses Schema enthält die Beschreibung aller unternehmensrelevanten Datenstrukturen für die Datenbank. Dabei ist es unerheblich, auf welche Weise diese Daten abgelegt werden. Auch für Datenbanken, die physikalisch auf mehreren Rechnern gespeichert werden, gibt es nur ein konzeptionelles Schema. Das konzeptionelle Schema ist sehr stark vom Datenbankentwurf und von dem benutzten Datenmodell (relational, objektorientiert, hierarchisch, ...) abhängig. Zum konzeptionellen Schema gehören neben allen relevanten Beschreibungen für die Sammlung der Daten insbesondere auch alle Beschreibungen von Konsistenzbedingungen (z.B. für jeden Artikel im Lager gibt es genau einen Artikel-Stammsatz; ein Zug kann nicht gleichzeitig an mehreren Orten sein; die Kundennummer muss eindeutig sein; jeder Kunde muss eine Kundennummer haben; ...). Auf die Realisierung dieser Konzepte gehen wir später ein – insbesondere in den Kapiteln 4.3 und 7. Das konzeptionelle Schema ist nicht unbedingt identisch mit dem logischen Schema der Datenbank oder dem Datenbankkonzept, wie wir es in Kapitel 3 einführen.

22

Sandini Bib

Die Datenbankarchitektur nach ANSI-SPARC

Internes Schema Im internen Schema sind die Einzelheiten der Implementierung beschrieben, z.B. die Aufteilung der Datenbank auf verschiedene Platten, das Anlegen von SpiegelPlatten oder das Anlegen von Indexen zur Beschleunigung der Zugriffe.

Externes Schema In den externen Schemata (Benutzersichten) werden Teilbereiche der Datenbank für verschiedene Benutzergruppen definiert. Hier werden auch die Nutzungsrechte der verschiedenen Benutzer festgelegt. Zum Teil können (für den lesenden) Zugriff abgeleitete Daten (z.B. die Summe der Gehälter in einer Abteilung) in ein externes Schema eingetragen werden, ohne dass die zugehörenden Grunddaten sichtbar gemacht werden.

Datenunabhängigkeit Zwischen den Schemata bestehen natürlich inhaltliche, sachlogische Abhängigkeiten. So kann eine Information aus der Datenbank nur dargestellt werden, wenn sie aus gespeicherten Daten auf irgendeine Weise erzeugt werden kann. Die Art und Weise, wie die Daten von der Festplatte auf den Bildschirm kommen – also der Transfer zwischen den verschiedenen Schemata –, wird aber durch Zugriffsfunktionen (Schnittstellen) geregelt, die im Datenbanksystem implementiert sind. Die technische Frage des Datenzugriffs – beispielsweise wie aus Datenfragmenten, die auf der Festplatte wild verstreut sind, eine Tabelle zusammengesetzt wird – spielt daher bei der Nutzung von Datenbanken so gut wie keine Rolle, und auch bei der Anwendungsentwicklung muss man sich kaum einmal damit beschäftigen. Wird die physikalische Speichertechnik geändert, so muss die entsprechende Zugriffsfunktion angepasst werden, damit am Ende dieselbe Tabelle wie vorher an das konzeptionelle Schema weitergereicht wird. Die DBMS verschiedener Hersteller können das Konzept auf ganz unterschiedliche Weise realisieren, und auch bei Produkten eines Herstellers kann es von Version zu Version erhebliche Unterschiede in der Art der Speicherstrukturen geben, ohne dass dies laufende Anwendungen tangiert. Die drei Schemata oder Ebenen der Datenbankarchitektur können daher in gewissen Grenzen unabhängig voneinander gestaltet und betrachtet werden. Das bezeichnet man als Datenunabhängigkeit. 왘 Physische Datenunabhängigkeit

Ein Programmierer oder Benutzer braucht für die Verarbeitung der Daten keine Kenntnis der Datenspeicherung (Blöcke, physische Schlüssel, ...). Damit müssen spätere Änderungen des physischen Datenbankaufbaus in den Programmen nicht berücksichtigt werden. 왘 Logische Datenunabhängigkeit

Ein Programmierer oder Benutzer muss nur die Beziehungen zwischen den Daten kennen, die auch tatsächlich für dieses Programm benötigt werden. Damit

23

Sandini Bib

1 Datenbanken und Datenbanksysteme

müssen spätere Änderungen im logischen Aufbau (neue Felder, Löschen von Feldern, kompatible Änderungen von Datentypen), die das jeweilige Programm nicht unmittelbar betreffen, nicht berücksichtigt werden. Für Datenbanken, die auf nicht vernetzten Einzelplatzrechnern installiert sind, gibt es häufig nur ein externes Schema, das mit dem konzeptionellen Schema identisch ist; mit anderen Worten: »Es gibt kein externes Schema.«

1.3 Integritätsregeln Wie wir in Abschnitt 1.1 erwähnt haben, gehören zum konzeptionellen Schema auch eine Reihe von Integritätsregeln. Beispiele: 왘 Der Kontostand darf das Kreditlimit nicht unterschreiten. 왘 Der Verkaufspreis muss größer als der Einkaufspreis sein – außer bei Sonder-

angeboten. 왘 Es können nur Waren bestellt werden, deren Artikelnummern in der Artikel-

datei enthalten sind. 왘 Studenten an einer Hochschule können nur Studiengänge studieren, die an der

Hochschule angeboten werden. 왘 Ein Student gehört dem Fachbereich an, der den Studiengang enthält, in dem er

studiert. 왘 Eine Matrikel-Nummer darf nicht doppelt vergeben werden. 왘 Bei der Stundenplanung ist für einen Vorlesungsblock pro Raum nur maximal

eine Veranstaltung vorzusehen. Das Ziel ist es, dass das DBMS – unabhängig von Anwendungsprogrammen – im Betrieb dafür sorgt, dass diese Integritätsbedingungen eingehalten werden. Das relationale Modell selbst kennt 왘 Domänenregeln, durch die die möglichen Werte für die Attribute eingeschränkt

werden, 왘 Primärschlüssel, durch die festgelegt wird, dass jedes Tupel eindeutig identifi-

zierbar ist, 왘 weitere Schlüssel, die ebenfalls eindeutig sein müssen, 왘 Fremdschlüssel, durch die die Beziehungen zwischen verschiedenen Relationen

auf sichere Weise hergestellt werden können (es kann in einer Bestellung keine Kundennummer geben, die nicht in der Kundenrelation vorhanden ist), und 왘 weitere Geschäftsregeln – Integritätsregeln, die sich durch logische Bezüge von

Daten auf andere Daten ergeben.

24

Sandini Bib

Integritätsregeln

In der nicht sehr fernen Vergangenheit konnten diese und weitere Arten von Integritätsbedingungen nur dadurch gewährleistet werden, dass sie in Anwendungsprogrammen implementiert wurden. Damit wurden natürlich viele Regeln mehrfach im Programmcode repräsentiert. Die Folge waren unter Umständen Widersprüche in verschiedenen Programmen und auf jeden Fall verschlechterte Wartbarkeit. Schlimmer noch: Das Problem der Integritätskontrolle ist sehr schwer in den Griff zu bekommen, wenn es jedem einzelnen Anwender überlassen bleibt. Dem sind bestimmte Regeln entweder gar nicht bekannt, oder sie werden nicht immer konsequent befolgt und möglicherweise in ihrer Auswirkung auf die gesamte Datenbank nicht überschaut. Dieses Problem wächst noch mit zunehmender Verfügbarkeit an Client-Software aller Art, die den direkten Zugriff von Anwendern auf Datenbanken gestattet. Die Forderung lautet daher: Alle Integritätsbedingungen, die die Daten unabhängig von etwaigen Abläufen betreffen, müssen als Eigenschaften der Daten selbst behandelt werden. Folglich müssen sie in der Datenbank selbst niedergelegt werden, also: »Integrität in die Datenbank!« Konsistenzüberprüfungen in den Anwendungsprogrammen (z.B. in Datenerfassungsformularen) sind zwar ein wichtiges Hilfsmittel, um die Konsistenz sicherzustellen; die Anwendungsprogramme sind aber in den externen Schemata angesiedelt. Der Endanwender oder der Entwickler für ein Endanwenderprogramm ist dann dafür verantwortlich, dass die Unternehmensregeln eingehalten werden. In einer unternehmensweiten Datenbank kann die Konsistenz damit nicht sichergestellt werden, so lange ein Benutzer die Möglichkeit hat, (absichtlich oder unabsichtlich) Anwendungen zu entwickeln, in denen Konsistenzbedingungen verletzt werden.

Datenbank zentrale Integritätsregeln

App 1

App 2

App 3

App 4

App 5

verschiedene Anwendungen

Abbildung 1.3: Zentral verwaltete Integritätsbedingungen

25

Sandini Bib

1 Datenbanken und Datenbanksysteme

Andererseits bedeutet die Eintragung von Konsistenzbedingungen in das konzeptionelle Schema nicht, dass der Anwendungsprogrammierer die Konsistenzregeln außer Acht lassen muss. Eine potenzielle Verletzung einer Konsistenzbedingung wird zwar vom Datenbanksystem abgewiesen; wenn aber keine spezielle Fehlerbehandlung im Programm vorgesehen ist, wird das Programm möglicherweise mit einer Fehlermeldung beendet, die für den Endanwender nicht akzeptabel ist.

1.4 Architektur von Datenbanksystemen Wenn mehrere Endanwender Zugriff auf eine Datenbank haben, ist es üblich, dass die Anwendungsprogramme nicht unmittelbar auf die Daten zugreifen (wie es ja bei selbst programmierten Anwendungen mit z.B. VSAM und Cobol ist). Hier wird üblicherweise eine Trennung in Front-End und Back-End vorgenommen. Front-End und Back-End sind eigenständige Prozesse (im Sinne von Unix). Der Front-End-Prozess kommuniziert mit dem Benutzer, der Back-End-Prozess mit der Datenbank, und beide kommunizieren miteinander (vgl. Abbildung 1.4). Diese beiden Prozesse können auf demselben Rechner laufen oder auf verschiedenen Rechnern installiert sein. Wegen ihrer komplementären Rollen bezeichnet man diese Prozesse auch als Client und Server. Falls das Front-End auf einem anderen Rechner läuft als das Back-End, werden diese beiden Rechner als Client und Server bezeichnet.

Front-End Benutzerprogramm mit GUI Benutzer

Back-End DB-Server Datenbank Abbildung 1.4: Client-Server-Architektur

Die Aufteilung von Anwendung und Datenzugriff auf zwei Prozesse dient zum einen der Datensicherheit, da die Prozesse sich nicht gegenseitig in die Daten sehen können und die Kommunikation nur über vom Betriebssystem gesicherte Kanäle möglich ist. Daneben ermöglicht diese Architektur einen effizienten Zugriff von vielen Benutzern, die gleichzeitig auf die Daten lesend oder auch ändernd zugreifen können.

26

Sandini Bib

Architektur von Datenbanksystemen

Für Leser, die sich ein wenig mit dem Konzept von Prozessen in Betriebssystemen auskennen, noch einige Anmerkungen: Die Zuordnung zwischen Front-End und Back-End kann 1:1 oder n:1 sein. Im ersteren Fall ist jedem Benutzer (über das Front-End) ein eigener Back-End-Prozess zugeordnet. Die Kommunikation zwischen diesen beiden Prozessen ist dann einfacher – dafür müssen die verschiedenen Back-End-Prozesse Informationen über die benutzten Tabellen austauschen. Im letzteren Fall kommunizieren alle Benutzer mit demselben Front-End. Dieses kann dann die Datenbankzugriffe besser optimieren, muss aber eine Verwaltung der verschiedenen Benutzer führen. Eine weitere Variante ist ein Back-End mit verschiedenen Threads, d.h. parallelen Aufträgen, die von diesem Back-End verwaltet werden. Ein Thread ist einfacher zu verwalten als ein Prozess, da er nicht wie ein Prozess die gesamte Umgebung speichern muss, sondern intern innerhalb eines Prozesses verwaltet wird. Die Client-Server-Architektur hat in Netzwerken bei Unternehmen und Institutionen eine weltweite Verbreitung gefunden. Auf der einen Seite existiert der Datenbankserver, dem die gesamte Aufgabe der Datenverwaltung und der Erledigung der Abfragen zufällt. Daneben gibt es den Client als Endanwender-Rechner, der die gesamte Dialogführung für die Abfragen und die Aufbereitung der Ergebnisse für den Endanwender übernimmt. Durch diese Architektur wird zum einen das zu übertragende Datenvolumen geringer, als wenn die Datenselektion und Ermittlung der Ergebnisse im Anwenderprozess erfolgen würden. Andererseits ist es hier möglich, im Client grafische Benutzeroberflächen zu verwenden; dies funktioniert nur, wenn die Logik der Oberfläche vom Client verwaltet wird. Zuletzt wird durch eine solche Lösung bei stark frequentierten Datenbanken der Server als zentraler Rechner weniger belastet. Durch die Verbreitung des World Wide Web sind neue Anforderungen entstanden. Der Zugriff auf Datenbanken soll unabhängig davon möglich sein, dass ein Benutzer eine bestimmte Client-Software installiert hat. Nur die Verfügung über einen Java-fähigen Browser ist vorausgesetzt, für alle Rechnerklassen und Betriebssysteme ist dies heute selbstverständlich. Es gibt höchst unterschiedliche Arten von Anwendungen, die über das Web auf Datenbanken zugreifen: von der einfachen Abfrage eines Datenbestands bis hin zur interaktiven Bearbeitung von komplexen Transaktionen. Daraus ergeben sich auch sehr unterschiedliche Anforderungen an die Anbindung einer Datenbank. Eine populäre Möglichkeit besteht darin, auf dem Web-Server kleine Java-Programme – sogenannte Applets – abzulegen, die zusammen mit einer HTML-Seite zum Anwender übertragen werden und auf dessen Web-Browser ausgeführt werden können. Applets können vom Client aus auf Datenbanken zugreifen, wobei ein eigenes von HTML unterschiedenes Protokoll, z.B. JDBC, benutzt wird. Ein Nachteil dieser Lösung ist, dass die ganze Applikation über das Web auf den Client geladen werden muss.

27

Sandini Bib

1 Datenbanken und Datenbanksysteme

Front-End Web-Browser

Benutzer

Java Virtual Machine

Applet Web-Server

Back-End DB-Server Datenbank

Abbildung 1.5: Datenbankzugriff über das Web mittels Java-Applet

Ein anderes Konzept sieht wegen der Nachteile der Applets bei komplexeren Anwendungen vor, die Darstellung der Daten und die Benutzerinteraktion noch einmal getrennt von der Anwendungssoftware zu implementieren, es ergibt sich dann eine Architektur mit drei oder sogar noch mehr Ebenen (»Multi-Tier«): Der Datenbankserver bleibt erhalten, der Client ebenfalls, aber nur mit reduzierter Funktionalität. Dazwischen tritt ein so genannter Applikationsserver, der die Anwendungssoftware – die nun beliebig komplex sein kann – beherbergt und ausführt. Er reicht die Anfragen des Clients an den Datenbankserver weiter und sendet dessen Ergebnisse beispielsweise als HTML-Seiten an den Client. Front-End Web-Browser HTML Benutzer Applikations-Server

Web-Server

Back-Eend DB-Server Datenbank

Abbildung 1.6: 3-Tier-Architektur mit Applikations-Server

Eine ausführliche Darstellung der diversen Architekturvarianten findet sich in [RaVo03 Kapitel 4].

28

Sandini Bib

Komponenten eines Datenbank-Verwaltungssystems

1.5 Komponenten eines DatenbankVerwaltungssystems Ein Datenbanksystem sollte neben den Systemen zur sicheren Datenverwaltung eine Reihe von Komponenten besitzen, die es ermöglichen, auf komfortable Weise Anwendungen zu realisieren. Dazu gehören: 왘 ein System zur interaktiven Manipulation des Datenbankschemas. Unter dem

Datenbankschema verstehen wir allgemein die Struktur der Datenbank, die abstrakte Beschreibung von Eigenschaften, die die Daten erfüllen müssen. Die konkreten Daten selbst gehören nicht zum Datenbankschema.1 왘 eine interaktive Datenmanipulationssprache 왘 eine bildschirmorientierte Datenmanipulationssprache 왘 ein Berichtsgenerator 왘 eine berechungsvollständige Sprache mit Zugriff auf das Datenmodell

Wir illustrieren einige dieser Aspekte durch Bildschirmdarstellungen des Datenbank-Verwaltungssystems MS Access.

Abbildung 1.7: Fenster mit den Datenbankobjekten

1.5.1 Interaktive Manipulation des Datenbankschemas Es muss möglich sein, die Definition der Datenbank interaktiv aufzubauen, sich anzeigen und ausdrucken zu lassen. Mit gewissen Einschränkungen muss es auch möglich sein, das Schema zu ändern, wenn die Datenbank in Betrieb ist. Es muss allerdings darauf geachtet werden, 1 Der Begriff Datenbankschema wird im nächsten Kapitel ausführlich behandelt.

29

Sandini Bib

1 Datenbanken und Datenbanksysteme

dass vorhandene externe Schemata, auf die sich produktive Programme beziehen, weiterhin verfügbar sind. Die ihnen zugrunde liegenden konzeptionellen Schemata und internen Schemata sind aber änderbar. Das System muss die gegebenenfalls notwendigen Änderungen der Speicherstruktur automatisch durchführen.

Abbildung 1.8: Tabellendefinition

1.5.2 Interaktive Datenmanipulationssprache Die Anweisungen können üblicherweise als Text gespeichert, modifiziert und aufgerufen werden. Im Bereich der relationalen Datenbanken ist SQL die am weitesten verbreitete Datenmanipulationssprache. SQL hat einen Sprachumfang, der die Definition, Auswahl und Änderung der Daten unterstützt, nicht aber die weitergehende Darstellung der ausgewählten Daten. Auf der anderen Seite enthält der XBase-Standard auch ähnliche Möglichkeiten wie SQL, aber darüber hinaus eine vollständige Programmiersprache. Mit dieser interaktiven Datenmanipulationssprache können ohne großen Aufwand einfache Auswertungen geschrieben werden, die in der Form des Datenmodells ausgegeben werden können (z.B. bei relationalen Datenbanken als Liste, bei objektorientierten durch eine Darstellung von Objekten).

Abbildung 1.9: SQL-Fenster

30

Sandini Bib

Komponenten eines Datenbank-Verwaltungssystems

Abbildung 1.10: Tabellenartige Datendarstellung

1.5.3 Bildschirmorientierte Datenmanipulationssprache Eine bildschirmorientierte Datenmanipulationssprache besteht in der Regel aus zwei Teilen: 왘 dem Maskengenerator 왘 dem maskenorientierten Datenmanipulationsprogramm

Im einfachsten Fall gibt es für jede Tabelle (gegebenenfalls für jede Benutzersicht) eine Standardmaske, die für jedes Attribut den Attributnamen und ein Ein-/Ausgabefeld für den Attributwert enthält. Hier sind Dateneingabe und Datenänderungen sowie einfache Abfragen möglich. Als Erweiterung kann die Maske für eine oder mehrere Tabellen beliebig verändert werden. Das kann interaktiv über einen »Masken-Editor« durchgeführt werden (z.B. in den relationalen Datenbanksystemen unter Windows) oder über eine Masken-Definitionssprache als ASCII-Datei, die für die Standard-Maske generiert wird und beliebig abgeändert werden kann (z.B. bei Unix-Datenbanksystemen). Es kann auch beides vorhanden sein.

Abbildung 1.11: Maske zur Dateneingabe

Neben Änderungen im Layout können auch Bedingungen in die Maske mit aufgenommen werden, die bei Datenänderungen gewisse Konsistenzüberprüfungen fordern, z.B.: 왘 die Festlegung, dass für bestimmte Attribute Eingaben erforderlich sind, 왘 die Festlegung, dass die Werte in vorgegebenen Bereichen liegen müssen, 왘 Abhängigkeiten zwischen Attributen auf Satzebene,

31

Sandini Bib

1 Datenbanken und Datenbanksysteme 왘 die Überprüfung, ob die eingegebenen Schlüssel zulässig sind, 왘 die automatische Verknüpfung mit weiteren Tabellen und 왘 die Darstellung von Tabellen zur Auswahl von Werten.

Dieses ist kein Widerspruch zu dem in Abschnitt 1.3 Gesagten, dass die Konsistenz in der Datenbank zu überprüfen ist: Die Überprüfung in der Maske kann unmittelbar während der Eingabe erfolgen und zu sinnvollen Hilfestellungen und ggf. Fehlermeldungen führen – die Datenbankmaschine überprüft die Datensätze anschließend entsprechend den Konsistenzregeln. Eine Überprüfung auf der Maske ist schneller und effizienter, eine Überprüfung durch das DBMS ist sicherer.

1.5.4 Berichtsgenerator Ein Berichtsgenerator (Report-Generator) ermöglicht es, das Ergebnis einer Datenbankabfrage in übersichtlicher Form auszudrucken. In relationalen Datenbanken kann die Abfrage z.B. eine SELECT-Anweisung von SQL sein, gegebenenfalls mit einer ORDER BY-Klausel. Für jedes Tupel dieser Abfrage wird festgelegt, wie es auszugeben ist. Als Kontrollstruktur steht die Fallunterscheidung zur Verfügung sowie die Möglichkeit, bestimmte Ausgaben bei Gruppenwechsel (z.B. Beendigung eines Zeitintervalls – wie Woche, Monat, Quartal, Jahr – oder Änderung eines Sortierfeldes) durchzuführen (z.B. Zwischensummen, Zwischenüberschriften u.Ä.).

Abbildung 1.12: Formulierung einer Abfrage

Abbildung 1.13: Ergebnis einer Abfrage

32

Sandini Bib

Komponenten eines Datenbank-Verwaltungssystems

Abbildung 1.14: Bericht

Mögliche Leistungen eines Berichtsgenerators sind: 왘 Formatierung der Überschriften 왘 Formatierung der ausgewählten Werte 왘 Ausgabe von Gesamtüberschriften und Seitenüberschriften 왘 Bildung von Datengruppen mit Zwischenüberschriften und Zwischensummen

Im Vergleich zu prozeduralen Sprachen fehlen im Berichtsgenerator in der Regel eine explizite Schleifenkonstruktion (implizit enthält die Definition der Abfrage eine Schleife) und ein Prozedurkonzept.

1.5.5 Berechnungsvollständige Sprache mit Zugriff auf das Datenmodell Für die Entwicklung von Anwendungssystemen benötigen wir eine berechnungsvollständige Programmiersprache, um beliebige Anwendungen mit Zugriffen auf das Datenbanksystem zu schreiben. Es gibt hier im Wesentlichen zwei Konzepte: 왘 Erweiterung einer allgemeinen Programmiersprache um Zugriffsmöglichkei-

ten für das Datenmodell. Beispiele hierfür sind Embedded SQL bei relationalen Datenbanksystemen sowie die Benutzung von Klassenbibliotheken für objektorientierte Programmiersprachen, z.B. JDBC für Java.

33

Sandini Bib

1 Datenbanken und Datenbanksysteme 왘 Eigenständige Sprache, die neben Anweisungen für Datenbankzugriffe und

Datenrepräsentation auf Bildschirm und Drucker weitere Kontroll- und Datenstrukturen enthält. Im Bereich der relationalen Datenbanken werden solche Sprachen als Sprachen der vierten Generation bezeichnet (4GL). Dieser Begriff ist allerdings nicht geschützt, und es verbergen sich dahinter unterschiedliche Konzepte.

Abbildung 1.15: Datenbankprogrammierung

34

Sandini Bib

2

Einführung in das relationale Datenmodell

Die erste Arbeit, in der Relationen als mögliche Gegenstände einer mathematisch fundierten Datenbanktheorie untersucht werden, ist der 1970 in den Communications of the ACM erschienene Artikel »A Relational Model of Data for Large Shared Data Banks« von E.F. Codd. Es hat etwa zehn Jahre gedauert, bis die ersten relationalen Datenbank-Verwaltungsysteme kommerziell verfügbar waren. Hier folgt ist eine sehr knappe Definition relationaler Datenbanksysteme, die Codd 1981 in seiner Rede anlässlich der Verleihung des Turing-Preises gegeben hat.1 Ein System ist relational, wenn 왘 alle Daten als Werte in Relationen dargestellt sind und jeder Benutzerzugriff

auf die Daten über die Werte der Daten erfolgt (und somit der Benutzer keine Kenntnis von Zeigern und Verkettungen haben muss), und 왘 es relationale Operatoren für die Selektion, die Projektion und den Verbund unterstützt.

Jahreszahlen zum relationalen Modell 1970: Codd veröffentlicht erste Arbeiten zur Relationentheorie als Grundlage einer Datenbanktheorie. 1975: Ingres wird mit der Sprache QUEL auf PDP implementiert. 1976: IBM veröffentlicht Studien zum System R und SEQUEL. 1977: Oracle beginnt die Implementierung auf Mainframes mit SEQUEL. 1979: Oracle liefert ein erstes relationales Datenbanksystem mit SQL aus. 1982: Ingres wird als Datenbanksystem auf Mini-Rechnern ausgeliefert. 1982: IBM bringt SQL/DS auf den Markt. 1982: IBM veröffentlicht das R*-Konzept für verteilte Datenbanken. 1989: Sybase, Ashton-Tate und Microsoft bringen SQL-Server auf den Markt. 1992: Neue Versionen einiger DBMS erhalten Trigger und Datenbankprozeduren. 1997: Objektorientierte Erweiterungen von relationalen Datenbanksystemen werden unter der Bezeichnung objektrelationale Datenbanken von Informix, DB2 und Oracle angeboten. 1999: Objektrelationale Datenstrukturen werden in den SQL-Standard aufgenommen. 1 veröffentlicht in [ACM 87; S. 391])

35

Sandini Bib

2 Einführung in das relationale Datenmodell

Im Folgenden lernen wir den Begriff der Relationen und die darauf beruhenden Operationen und Verknüpfungen kennen, die sog. Relationenalgebra . Hieraus können wir schon sehr komplexe Abfragen an die Datenbank stellen. Viele PC-basierte Datenbanksysteme (z.B. Access, Paradox) erlauben unmittelbar die Formulierung von Anfragen in einer grafischen Implementierung der Relationenalgebra. Statt der Begriffe des relationalen Datenbankmodells werden in bestimmten Zusammenhängen Begriffe verwandt, die sich an die Anschauung einer zweidimensionalen Tabelle anlehnen (z.B. in SQL) oder die aus der klassischen DateiOrganisation stammen (z.B. Cobol, XBase). relational

SQL

Cobol, XBase

Relation

Tabelle (table)

Datei (file)

Tupel

Zeile (row)

Datensatz (record)

Attribut

Spalte (column)

Feld (field)

2.1 Aufbau relationaler Datenbanken Als Grundgerüst für die Definition von Relationen (im Sinne des relationalen Datenmodells – die Definition in der logischen Programmiersprache Prolog oder in der Prädikatenlogik weicht hiervon zum Teil ab) benötigen wir zum einen eine Menge von Bezeichnern für die Attribute, Tabellen und anderen Datenbankobjekte. Wir gehen davon aus, dass diese Bezeichner ähnlich wie in vielen Programmiersprachen aus Buchstaben, Ziffern und gegebenenfalls einigen Sonderzeichen wie dem Unterstrich gebildet werden; das erste Zeichen muss ein Buchstabe sein. Des Weiteren ist die Benutzung von Groß- und Kleinbuchstaben beliebig. Ihnen kommt keine Unterscheidungsrelevanz zu; d.h. die Bezeichner PLZ, Plz und plz sind als identisch anzusehen.

2.1.1 Attribute In einer Datenbank werden die Objekte, über die wir Daten sammeln, durch Attribute beschrieben. Ein Attribut besteht aus einem Attribut-Bezeichner und einem Wert. Wir schreiben ein Attribut immer in der Form Attribut-Bezeichner = wert

Beispiele für Attribute: kunden_nr = 101 name = 'Stein' vorname = 'Peter' geburtstag = DATE '1967-09-13'

36

Sandini Bib

Aufbau relationaler Datenbanken

größe = 184 cm straße = 'Moordamm 24' plz = '23863' ort = 'Kayhude' personenstand = ledig

2.1.2 Domänen Zur Beschreibung von Daten benötigen wir in der Praxis unterschiedliche Wertebereiche (Domänen), aus denen die Attribute ihre Werte beziehen. In vielen Fällen reichen Standarddomänen wie 왘 CARDINAL

natürliche Zahlen (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, ...) 왘 INTEGER

ganze Zahlen (0, 1, 2, 3, ... -1, -2, -3, ...) 왘 NUMERIC

numerische Werte in Dezimaldarstellung 왘 STRING

Zeichenketten 왘 BOOLEAN

logische Werte (falsch/wahr, nein/ja, aus/ein, 0/1, ...) 왘 CHAR

einzelne Zeichen (z.B. A, B, C, a, b, c, 0, 1, 2, +, –, *, ...) Des Weiteren können zum Beispiel eine Rolle spielen : 왘 Messwerte und Kapazitäten 왘 Geldbeträge, 왘 Bezeichnungen für

• Personen, • Geräte, • Firmen, • Artikel, • ... 왘 Bilder und Konstruktionszeichnungen 왘 Töne 왘 Datum, Uhrzeit und Zeitpunkt (= Datum + Uhrzeit), 왘 Statusvariablen:

• Familienstatus = {ledig, verheiratet, geschieden, verwitwet} • Verleihstatus = {ausgeliehen, vorbestellt, verfügbar, verlegt}

37

Sandini Bib

2 Einführung in das relationale Datenmodell

• Geschlecht = {männlich, weiblich} • Rechnungsstatus = {ohne, Rechnung geschrieben, erinnert, gemahnt, zweimal gemahnt, Zwangsverfahren} 왘 Mengen mit festgelegten Werten: • Gehaltsgruppen, • Steuerklassen, • Studiengänge an der Hochschule 왘 Adressdaten: Straße, Postfach, PLZ, Ort, Staat 왘 Telefonnummern Domänen

Name

Ort Anrede

Chen Codd Date von Friedeburg Matthiessen McNamara Meyer-Niemann Nürnberg Unterstein O'Neill Turvenpää ...

Herr Frau

Beijing Bremen Hamburg Kayhude Moskau New York Nürnberg Övelgönne Ostereistedt Paris ...

Abbildung 2.1: Domänen

Für die Werte der Domänen gibt es jeweils eine Repräsentation, in denen sie den Benutzern angezeigt werden (z.B. Datumsformat, Darstellung von Bildern und Zeichnungen). Ebenso sind gewisse Repräsentationen zu benutzen, wenn entsprechende Daten eingegeben werden. Diese Repräsentationen müssen nicht unbedingt etwas mit der internen Darstellung der Daten im Rechner zu tun haben. 2 Wir können sogar noch weiter gehen und sagen, dass die interne Darstellung der Daten für den Datenbankentwurf so gut wie keine Rolle spielt.

2 So wird in Tabellenkalkulationsprogrammen wie StarCalc oder Excel, aber auch im PC-Datenbanksystem Access, der Zeitpunkt '13.9.1967 21:00' durch die Zahl 24728,875 dargestellt, wobei 24728 die Anzahl der Tage seit dem 30.12.1899 ist und 0,875 ist 7/8 von 24 Stunden, also 21 Stunden seit Mitternacht.

38

Sandini Bib

Aufbau relationaler Datenbanken

Für Domänen sind in der Regel Operationen definiert, die in der Datenbankanwendung benutzt werden können. Es handelt sich hierbei um: 왘 homogene Operationen, z.B.:

• die Summe von Messwerten, • die Summe von Geldbeträgen, • die Multiplikation eines Geldbetrages mit einer festen (Bruch-)Zahl, • die Verkettung von Zeichenketten 왘 heterogene Operationen

d.h. Operationen, deren Argumente und Ergebnisse nicht aus derselben Domäne stammen, z.B.: • Datum/Uhrzeit + Zeitintervall • Länge einer Zeichenkette (ist eine natürliche Zahl) 왘 Vergleichsoperationen und andere logische Operationen

(können als Spezialfall der heterogenen Operationen angesehen werden): • Vergleich zweier Messwerte (, ≥, =, ≠), • Vergleich von zwei Zeitpunkten, • Ähnlichkeit von zwei Namen 왘 Konvertierungsoperationen

gesteuerte Umwandlung verschiedener Datentypen über ihre Repräsentation, z.B.: • • •

Tag: Datum → Numerisch Monat: Datum → Numerisch Jahr: Datum → Numerisch

• • •

Wochentag: Datum → Numerisch3 Datum → Zeichenkette Zahl → Zeichenkette

In der Regel können sinnvollerweise nur Werte einer Domäne mit Werten derselben Domäne verglichen werden. Verschiedene Domänen, die durch dieselbe Menge von Werten repräsentiert werden, sind als nicht vergleichbar aufzufassen. Zum Beispiel können wir Kundennummern und Artikelnummern durch natürliche Zahlen repräsentieren. Dennoch muss die Domäne der Kundennummern von der Domäne der Artikelnummern unterschieden werden. Eine Kundennummer kann auch nicht ohne weiteres mit einer Artikelnummer verglichen werden, sondern nur über eine Standardkonvertierungsfunktion.

3 Nach ISO 8601 gilt folgende Zuordnung der Wochentage: 1 für Montag, 2 für Dienstag, ... , 7 für Sonntag.

39

Sandini Bib

2 Einführung in das relationale Datenmodell

2.1.3 Tupel Ein Tupel t ist gegeben durch eine Menge von Attributen. Ein Beispiel für ein Tupel ist im folgenden dargestellt: t ::= [kunden_nr = 101, name = 'Stein', vorname = 'Peter', geburtstag = DATE '1967-09-13', größe = 184 cm, straße = 'Moordamm 24', plz = '23863', ort = 'Kayhude', personenstand = ledig]

Beachte: 왘 Die Reihenfolge der Attribute in den Klammern spielt keine Rolle. 왘 Ein Attribut-Bezeichner darf in einem Tupel jeweils nur einmal auftreten. Falls

es für ein Attribut mehrere Werte gibt, ist dann der entsprechende Wert als Menge zu bezeichnen, z.B.: Hobby = {Fahrradfahren, Fremdsprachen, Lesen}. 왘 Wir weisen allerdings hier schon darauf hin, dass in relationalen Datenbanken

die Domänen nicht strukturiert sein dürfen, also insbesondere keine Mengen oder Folgen sein können. 4 왘 Zwei Tupel sind dann identisch, wenn sie genau dieselben Attribute mit jeweils denselben Werten haben. Für ein Tupel t und einen Attribut-Bezeichner r ist t.r der Wert des Attributes r in dem Tupel t. So hat in dem obigen Beispiel t.ort den Wert 'Kayhude'. Zwei Tupel r und s sind widersprüchlich, wenn es einen Attribut-Bezeichner a gibt, der sowohl in r als auch in s vorkommt und für den r.a ≠ s.a ist. So sind die Tupel r1 ::= [name='Meyer', vorname='Peter']

und s1 ::= [name='Meyer', vorname='Hans', ort='Bremerhaven']

widersprüchlich, da r2.vorname ≠ s2.vorname. Zwei Tupel, die nicht widersprüchlich sind, werden als widerspruchsfrei bezeichnet. So sind die Tupel r2 ::= [name='Meyer', vorname='Peter', geburtstag = DATE'1966-10-16']

und

s2 ::= [vorname='Peter', name='Meyer', ort='Bremerhaven']

widerspruchsfrei. 4 Auf die Möglichkeiten, strukturierte Datentypen in objektrelationalen Datenbanken zu definieren, gehen wir in Kapitel 9 ein.

40

Sandini Bib

Aufbau relationaler Datenbanken

Widerspruchsfreie Tupel r und s können zu r+s zusammengefasst werden, wobei r+s genau die Attribute enthält, die in r enthalten sind, und auch die Attribute, die in s enthalten sind. Attribute, die in beiden Tupeln enthalten sind, treten nur einmal auf. Da die Tupel widerspruchsfrei sind, ist der Wert dieser Attribute auch jeweils eindeutig festgelegt. So ist r2+s2 = [name='Meyer', vorname='Peter', geburtstag = DATE'1966-10-16', ort = 'Bremerhaven']

Wenn r und s widersprüchlich sind, ist r+s nicht definiert.

2.1.4 Relationenschema und Relationen Üblicherweise werden Relationen als eine Menge von Tupeln mit denselben Attribut-Bezeichnern eingeführt; im Nachhinein werden als Ausnahme von dieser Regel sogenannte Nullmarken zugelassen. Wir führen dagegen von vornherein Relationen als spezielle Mengen von Tupeln ein, die einem gewissen Relationenschema genügen. Hierbei lassen wir auch zu, dass in einem Tupel gewisse Attribute fehlen können, d.h. für sie ist kein Wert angegeben. Ein Relationenschema S ist durch eine (endliche) Menge A von Bezeichnern (Attribut-Bezeichner) und eine Zuordnung gegeben, die jedem Attribut-Bezeichner a aus A eine Domäne d(a) zuordnet. Wir beschreiben ein Relationenschema durch Aufzählung der Attribut-Bezeichner mit ihren Domänen, die paarweise nebeneinander in einer Klammer aufgezählt werden, z.B.: (kunden_nr name strasse plz ort letzte_bestellung

Kunden_Nummern, Namen, Straßen, DECIMAL(5), Orte, DATE)

Als Kurzschreibweise in Zusammenhängen, wo die Domänen nicht interessieren, verzichten wir auf die Angabe der Domänen und schreiben nur die AttributBezeichner in Klammern. In unserem Beispiel also: (kunden_nr, name, strasse, plz, ort, letzte_bestellung) Wir gehen davon aus, dass die Reihenfolge der Attribute keine Rolle spielt und die Zugriffe auf die Attribute jeweils über die Attribut-Bezeichner erfolgen. Dieser Begriff einer Relation ist ein anderer als der in der Mathematik übliche Begriff der Relation, besonders, wenn es um zweistellige Relationen geht: In der Mathematik werden üblicherweise die Paare als Folgen von zwei Elementen beschrieben: dem ersten und dem zweiten Element. Auch größere Tupel werden als Folgen beschrieben mit einem ersten, zweiten, dritten usw. Element. Das heißt jetzt nicht, dass der

41

Sandini Bib

2 Einführung in das relationale Datenmodell

von uns gewählte Ansatz mathematisch weniger exakt ist, sondern er ist nur allgemeiner und für das vorgesehene Anwendungsgebiet besser geeignet. 5 Ein Tupel t ist kompatibel zu einem Relationenschema S, wenn folgendes gilt: 1) t enthält nur Attribut-Bezeichner, die auch in S vorkommen, 2) Für jeden Attribut-Bezeichner a von t gilt: Der Wert t.a ist ein Element von d(a). Es ist jedoch zulässig, dass ein Attribut-Bezeichner im Relationenschema in dem Tupel nicht auftritt. In diesem Fall sagen wir auch: »Das Attribut hat eine Nullmarke« (vgl. Abschnitt 2.5). So ist z.B. [kunden_nr = 101, name = 'Peter Stein', strasse = 'Moordamm 24', plz = 23863, ort = 'Kayhude']

kompatibel zu dem oben definierten Relationenschema. Dagegen ist [kunden_nr = 101, name = 'Peter Stein', strasse = 'Moordamm 24', plz = 23863, ort = 'Kayhude', telefon = '04535 / 4711']

nicht kompatibel zu dem oben definierten Relationenschema, da ein Attribut telefon enthalten ist, das nicht im Relationenschema vorkommt. Das Tupel [kunden_nr = 101, name = 'Peter Stein', strasse = 'Moordamm 24', plz = 23863, ort = 'Kayhude', letzte_bestellung = '12 Möhren']

ist nicht kompatibel zu dem Relationenschema, da der Wert des Attributes letzte_bestellung nicht der vorgegebenen Domäne angehört. 5 Mathematisch gesehen ist ein Tupel in unserem Sinne eine partielle Abbildung aus der Menge der Attribut-Bezeichner des Relationenschemas in die Vereinigungsmenge der entsprechenden Domänen. Nach dem klassischen Relationenbegriff ist ein Tupel eine Abbildung einer natürlichen Zahl n = {0,1,...,n-1} in die Vereinigungsmenge der entsprechenden Domänen.

42

Sandini Bib

Aufbau relationaler Datenbanken

Die Unterscheidung kompatibler und nicht kompatibler Tupel im Verhältnis zu einem Relationenschema ist von praktischer Bedeutung für die Konsistenz und Verlässlichkeit einer Datenbank. Man fordert von einem DBMS, dass es den Versuch, ein nicht kompatibles Tupel in ein Relationenschema einzufügen, zurückweist. Das unterscheidet ein Datenbanksystem zum Beispiel von einem Kalkulationsblatt. Tabellen mit Daten kann man in beiden speichern, das Tabellenkalkulationsprogramm lässt aber in jeder Zelle jede Art von Eintrag zu, womit seine Tauglichkeit als Datenbankersatz recht bescheiden ist. Die Möglichkeiten der Schemadefinition haben sich im Verlauf der Entwicklung von DBMS erweitert, so dass die Grenze zwischen kompatiblen und nicht kompatiblen Tupeln immer schärfer und strenger gezogen werden kann. Dennoch sind technisch noch längst nicht alle Möglichkeiten realisiert, die theoretisch wünschenswert wären. Es ist beispielsweise eine Tatsache, dass die Möglichkeiten der Domänendefinition in SQL-Datenbanken bis heute noch nicht befriedigend sind. In Systemen der künstlichen Intelligenz (z.B. in Prolog-Systemen) können Mengen von Tupeln verwaltet werden, in denen jedes Tupel einen anderen Aufbau hat. Dagegen werden in Datenbanksystemen sehr große Mengen von »strukturierten« Daten verwaltet, die aus Gründen der effizienten Verwaltung und der einfachen Formulierung von Abfragen einen gleichartigen Aufbau haben müssen. Wenn das Relationenschema eines Tupels aus dem Zusammenhang bekannt ist, benutzen wir an manchen Stellen eine Notation, die die Attribut-Bezeichner in der Reihenfolge des Relationenschemas benutzt und nicht explizit hinschreibt – nicht vorhandene Attribute werden gegebenenfalls durch ein Sternchen dargestellt. Das erste Tupel auf Seite 42 ist dann kürzer zu schreiben als: [101, 'Peter Stein', 'Moordamm 24',

23863, 'Kayhude', *]

Dies ändert nichts an der Tatsache, dass die Reihenfolge der Attribut-Bezeichner irrelevant ist – wir brauchen uns nicht an die Anordnung der Attribute halten, wie wir sie in den obigen Beispielen aufgeschrieben haben; wir müssen dann aber explizit jeweils die Attribut-Bezeichner mitschreiben. Aber wozu – manchmal ist es halt kürzer und einfacher. Allerdings ist ein (impliziter) Bezug auf die Reihenfolge der Attribute nur bei Ad-hoc-Anfragen sinnvoll, da wir dann nicht die Menge der Attribute kennen müssen. Bei gespeicherten Anwendungen ist in jedem Falle davon abzuraten!

Zusammenfassung Eine Relation ist 왘 eine Menge von Tupeln, 왘 die jeweils kompatibel zum Relationenschema sind.

Für zwei Relationen, die zu demselben Relationenschema kompatibel sind, sagen wir auch, sie sind vom selben Typ.

43

Sandini Bib

2 Einführung in das relationale Datenmodell

Die Eigenschaft einer Relation, eine Menge zu sein, hat zwei wesentliche Konsequenzen: 왘 Es können nicht zwei identische Tupel in einer Menge enthalten sein, d.h. je

zwei Tupel müssen sich in mindestens einem Attributwert unterscheiden; 왘 Die Reihenfolge der Tupel spielt keine Rolle.

2.1.5 Datenbankschema und Datenbank Ein Schema für eine relationale Datenbank wird durch folgende Angaben festgelegt: 1) eine Menge von Bezeichnern für Relationen, 2) für jede Relation ein Relationenschema, 3) für jede Relation weitere Konsistenzbedingungen Wir werden die weiteren Konsistenzbedingungen in den folgenden Kapiteln kennen lernen. Unter anderem gehören dazu: 왘 Die Festlegung von Schlüsselfeldern, die die Tupel der Relation jeweils eindeu-

tig beschreiben (vgl. den folgenden Abschnitt). 왘 Die Festlegung, dass ein Attribut in den auftretenden Tupeln einen Wert haben

muss, also keine Nullmarke besitzen darf. 왘 Die Einschränkung auf die möglichen Beziehungen zwischen den Werten (z.B.

liefermenge ≤ bestellmenge). 왘 Einschränkungen, die sich durch Beziehungen auf die Werte anderer Rela-

tionen ergeben. Eine relationale Datenbank ist somit durch eine Menge von Relationen gegeben, die jeweils durch das entsprechende Relationenschema bestimmt sind und die die jeweiligen Integritätsregeln erfüllen.

2.2 Schlüssel, Primärschlüssel und Fremdschlüssel 2.2.1 Primärschlüssel und Entitätsintegrität Nach der Codd’schen Charakterisierung ist ein Wesensmerkmal von relationalen Datenbanken, dass alle Beziehungen zwischen den Daten über Werte hergestellt werden. Um an einzelne Tupel einer Relation heranzukommen, müssen wir die Tupel eindeutig identifizieren können. Dazu benötigen wir einen Schlüssel. Ein Schlüssel einer Relation ist durch eine Menge von Attributen festgelegt. Bei einem Schlüssel, der aus einem Attribut besteht, darf in einer Relation zu einem

44

Sandini Bib

Schlüssel, Primärschlüssel und Fremdschlüssel

bestimmten Zeitpunkt jeder Wert für das Attribut nur einmal auftreten. Bei Schlüsseln, die aus mehreren Attributen bestehen, dürfen die entsprechenden Kombinationen der Attributwerte nur jeweils einmal auftreten. Bei Relationen, die konkrete Entitäten (z.B. Gegenstände, Personen, Dokumente, Ereignisse,…) bezeichnen, ist der Schlüssel in der Regel durch den Entitätenschlüssel gegeben (vgl. Kapitel 3) und ergibt sich damit aus fachlichen Gegebenheiten. Da natürliche (oder kulturell vereinbarte) Attribute wie Name und Vorname in der Regel nicht die erforderliche Eindeutigkeit bieten, werden üblicherweise künstliche Schlüssel eingeführt wie Matrikelnummern bei Studierenden, Kundennummern in Geschäftsbeziehungen, Personalnummern in Unternehmen, Kfz-Kennzeichen im Straßenverkehr oder Postleitzahlen in der Postadressierung. Bei Relationen, die Beziehungen zwischen verschiedenen Entitäten bezeichnen, ist der Schlüssel üblicherweise zusammengesetzt. Hier können als Beispiele {bestell_nr, artikel_nr} bei Bestellungen genannt werden. Die Eigenschaft, Schlüssel zu sein, sagt hier aus, dass in einer Bestellung ein Artikel nur einmal auftreten kann. Dagegen ist es zulässig, dass in einer Bestellung mehrere verschiedene Artikel auftreten (sonst würde bestell_nr allein schon einen Schlüssel bilden). Ebenso ist es zulässig, dass ein Artikel in mehreren Bestellungen auftritt (sonst würde die artikel_nr für sich schon einen Schlüssel bilden). Es kann mehrere Schlüssel geben. Einer davon kann als Primärschlüssel ausgezeichnet werden. So können zu einem festen Zeitpunkt z.B. Fahrzeuge durch ihre Motornummer, durch ihre Fahrgestellnummer oder durch ihr Kfz-Kennzeichen eindeutig identifiziert werden (durch Ummeldung oder Einbau eines Austauschmotors können sich allerdings diese Schlüssel nachträglich ändern). Die Bedingung, dass es keine zwei Tupel in einer Relation geben kann, die denselben Primärschlüssel haben, wird als Entitätsintegrität bezeichnet.

2.2.2 Fremdschlüssel und referenzielle Integrität Wie wir an anderer Stelle schon gesagt haben, erfolgen im relationalen Datenmodell Verknüpfungen zwischen Relationen über Werte. Es gibt keine vordefinierten Verknüpfungspfade zwischen Relationen. Die Schlüsselwerte, die Beziehungen zwischen verschiedenen Relationen beschreiben, werden als Fremdschlüssel bezeichnet. Ein Fremdschlüssel ist eine Folge von Attributen. Die Werte dieser Attribute beziehen sich jeweils auf die Schlüsselwerte des Primärschlüssels einer anderen (gegebenenfalls derselben) Relation. Die Relation mit dem Primärschlüssel nennen wir Vaterrelation, die mit dem Fremdschlüssel abhängige Relation. Eine Beziehung zwischen einem Tupel der abhängigen Relation und einem Tupel der Vaterrelation wird dargestellt, indem der Schlüsselwert des Tupels in der Vaterrelation in den Fremdschlüssel der abhängigen Relation eingesetzt wird. Falls die Vaterrelation einen zusammengesetzten Schlüssel hat, ist auch der Fremdschlüssel der abhängigen Relation zusammengesetzt (hier müssen wir allerdings eine Reihenfolge der Attribute im Schlüssel sowie im Fremdschlüssel vorgeben).

45

Sandini Bib

2 Einführung in das relationale Datenmodell

Für eine Beziehung über einen Fremdschlüssel wird allgemein die referenzielle Integrität gefordert, was bedeutet, dass der Wert bzw. die Wertekombination des Fremdschlüssels in der abhängigen Relation auf jeden Fall als Schlüssel in der Vaterrelation enthalten sein muss. Es ist dann ausgeschlossen, dass ein neues Tupel in die abhängige Relation eingefügt wird, für das der Fremdschlüsselwert nicht in der Vaterrelation enthalten ist. Ebenso kann der Schlüsselwert nicht auf einen Wert geändert werden, der in der Vatertabelle nicht vorhanden ist. Ein Beispiel hierzu ist durch die beiden folgenden Relationen gegeben, die die Bestellungen in einem Versandhandel beschreiben und wo kunden_nr in der Relation Bestellung ein Fremdschlüssel auf die Relation Kunde ist. In den entsprechenden Tabellen im Anhang C können Sie sehen, dass die Werte von kunden_nr in der Relation Bestellung jeweils genau ein Tupel in der Relation Kunde beschreiben. Bestellung (bestell_nr, kunden_nr, bestelldatum, lieferdatum, rechnungsbetrag) FK: kunden_nr → Kunde Kunde (kunden_nr, status, name, straße, plz, ort, letzte_bestellung, letzte_werbeaktion)

Primärschlüsselattribute sind jeweils unterstrichen. Durch die Angabe FK: attributliste → Relation geben wir an, dass die angegebene Folge von Attributen einen Fremdschlüssel in die angegebene Relation darstellt. In den entsprechenden Tabellen in Anhang C können Sie sehen, dass für die Werte von kunden_nr in der Relation Bestellung jeweils genau ein Tupel in der Relation Kunde existiert. Umgekehrt sehen wir hier auch, dass ein Fremdschlüssel in einer Relation nicht eindeutig sein muss (wie hier die Kundennummer 103, die in zwei Bestellungen auftritt). Ein Fremdschlüssel ist eben kein Schlüssel, sondern eine Beziehung zu einem Schlüssel in einer fremden Relation. Ein Problem kann aber auftreten, wenn ein Tupel in der Vaterrelation gelöscht oder geändert werden soll, auf das sich ein Attributwert in der abhängigen Relation bezieht (z.B. ein Kundensatz, dessen Kundennummer in einer offenen Rechnung auftritt). Hier gibt es drei mögliche Verhaltensweisen: 왘 restricted (nicht zulässig):

Ein Tupel mit einer offenen Referenz darf nicht gelöscht werden (z.B. ein Kundensatz, auf den eine Rechnung verweist). Der Wert des referenzierten Schlüssels darf nicht geändert werden. 왘 cascade (weitergeben):

Wenn ein Tupel mit einer offenen Referenz gelöscht wird, ist die offene Referenz mit zu löschen (z.B. sind beim Löschen einer Bestellung alle Positionen zu löschen, die sich auf diese Bestellung beziehen). Wenn der Wert des referenzierten Schlüssels geändert wird, wird das Attribut in der abhängigen Tabelle genauso geändert.

46

Sandini Bib

Einführung in die Fallstudie (Versandhandel) 왘 set null (auf Null setzen) / set default (auf Vorgabewert setzen):

Wenn ein Tupel in der Vatertabelle mit einer offenen Referenz gelöscht wird, sind die Verweise auf dieses Tupel auf NULL bzw. auf einen vorher festgelegten Standardwert zu setzen (z.B.: Wenn in einem Unternehmen eine Abteilung aufgelöst wird, ist für die betroffenen Mitarbeiter als Abteilung – vorläufig – eine Nullmarke zu setzen).

2.2.3 Übungsaufgaben Aufgabe 2.1 Beschreiben Sie das sinnvolle Verhalten eines Fremdschlüsselattributs im Zusammenhang mit dem Löschen des entsprechenden Satzes der Vaterrelation an Hand folgender Beispiele: a) Relation der Abteilungen mit der Personalnummer des Abteilungsleiters als Fremdschlüssel. b) Relation der studentischen Prüfungsleistungen mit der Matrikelnummer des Studenten als Fremdschlüssel. c) Relation der Bestellpositionen mit der Bestellnummer als Fremdschlüssel. d) Relation der Rechnungen mit der Kundennummer als Fremdschlüssel.

2.3 Einführung in die Fallstudie (Versandhandel) In Anhang C ist das Datenbankschema einer Beispieldatenbank Versandhandel dargestellt. Als Schreibweise haben wir die entsprechende CREATE TABLE-Anweisung von SQL verwendet. In Kurzform ist das Schema der Beispieldatenbank wie folgt darzustellen: 왘 Artikel (artikel_nr, mwst , bezeichnung, listenpreis, bestand, mindestbe-

왘 왘 왘 왘

stand, verpackung, lagerplatz, kann_wegfallen, bestellvorschlag, nachbestellung, nachbestellmenge) FK: mwst → MWSt_Satz MWSt_Satz (mwst, prozent, beschreibung) Kunde (kunden_nr, status, name, straße, plz, ort, letzte_bestellung, letzte_werbeaktion, zahlungsart) Girokonto (kunden_nr, konto_inhaber, blz, konto_nr) FK: kunden_nr → kunde Bestellung (bestell_nr, kunden_nr, bestelldatum, lieferdatum, rechnungsbetrag) FK: kunden_nr → kunde

47

Sandini Bib

2 Einführung in das relationale Datenmodell 왘 Position (bestell_nr, artikel_nr, bestellmenge, liefermenge, gesamtpreis)

FK: bestell_nr → Bestellung FK: artikel_nr → Artikel

Hier sind die Primärschlüssel jeweils unterstrichen, Fremdschlüssel sind durch den Zusatz FK dargestellt mit Angabe der jeweiligen Vaterrelation. Wir sehen hier, dass ein Primärschlüssel oder Teil eines Primärschlüssels gleichzeitig Fremdschlüssel sein kann.

2.4 Relationenalgebra In der Relationenalgebra werden aus vorhandenen Relationen neue Relationen erzeugt. In den Abfragesprachen der kommerziell verfügbaren Datenbanksysteme (z.B. in SQL) sind Konstruktionen enthalten, die die Operationen der Relationenalgebra realisieren. Wir benutzen hier eine kompakte Sprache, die im Gegensatz zu SQL die einzelnen Operationen der Relationenalgebra direkt beschreibt. Diese neuen Relationen können in folgender Weise verwandt werden: Snapshot Es wird eine neue Relation (im Hauptspeicher oder auf der Platte) angelegt, die aus den aktuell gültigen Daten abgeleitet wird. Auf diese Relation kann anschließend zugegriffen werden. Zwischenzeitliche Änderungen in den benutzten Ursprungsdaten bleiben dabei unberücksichtigt. Datenausgabe Die erzeugte Relation wird lediglich auf dem Bildschirm, Drucker oder in eine Datei ausgegeben und kann anschließend vom Datenbanksystem nicht mehr verarbeitet werden. Virtuelle Datensicht Die neue Relation wird nicht sofort angelegt, sondern bei jedem Zugriff auf diese Datensicht wird sie aus den aktuell gültigen Daten erzeugt; diese Relation muss daher auch nicht gespeichert werden. Im folgenden werden wir die Relationen und abgeleiteten Relationen tabellarisch im Text darstellen. Wir verwenden die Relationen mit den Daten entsprechend dem Anhang C. Da die Anzahl der Attribute aber eine übersichtliche Darstellung im Text nicht mehr erlaubt, werden wir bei der Relation »Artikel« die letzten vier Attribute nicht mehr darstellen. Die Schreibweise lehnt sich an die Darstellung von [HeSa95] an. Wir verwenden folgende Operationen der Relationenalgebra: Sel

für Auswahl (Selektion)

Proj für Projektion

48

Sandini Bib

Relationenalgebra

Ren

für Umbenennung von Attribut-Bezeichnern

Adj

für die Hinzufügung von virtuellen Spalten

Grp

für Datengruppierung (wird üblicherweise nicht zu den relationalen Operationen gezählt – aber jedes Datenbanksystem hat Operatoren, die auf dieser Operation beruhen.)

Join für den natürlichen Verbund zweier Relationen, sowie für den äußeren Verbund ×

für das Kreuzprodukt zweier Relationen



für Vereinigungsmenge



für Durchschnittsmenge

\

für Differenzmenge

Die Schreibweise ist jeweils Operator [Spezifikation] (Relation) für die einstelligen Operationen und Relation Operator Relation für die zweistelligen Operationen. Zusätzlich ergänzen wir den Verbund-Operator durch die (eigentlich überflüssige – da als Schnittmenge der Attribute der verknüpften Relationen schon festgelegte) Angabe der Verbindungsattribute. Falls mehrere zweistellige Operatoren enthalten sind, sind gegebenenfalls noch Klammern zu setzen.

2.4.1 Die Auswahl (Selektion) Sei R eine Relation, bedingung sei ein logischer Ausdruck (entsprechend einem booleschen Ausdruck in Programmiersprachen wie Pascal oder Java), der 왘 aus Attribut-Bezeichnern von R (als Variablen), 왘 aus Konstanten, 왘 aus den entsprechenden Operatoren und Funktionen, 왘 aus den Vergleichsoperatoren =, ≠, , ≥, 왘 aus den logischen Operatoren ∧, ∨, ¬, die für und, oder und nicht stehen,

gebildet wird. Durch Sel [bedingung] (R)

wird eine Relation definiert, die genau die Tupel enthält, die die Bedingung erfüllen (d.h. für die der boolesche Ausdruck den Wert TRUE ergibt).

49

Sandini Bib

2 Einführung in das relationale Datenmodell

Der einfachste Fall der logischen Bedingung ist der Vergleich eines Attributes mit einer Konstanten der entsprechenden Domäne, z.B. name = 'Meyer', listenpreis < 100,00 DM ankunft < TIME '12:00' ort ≠ 'Bremen'

Des Weiteren können mehrere Attribute miteinander verglichen werden, z.B. ankunft < abfahrt listenpreis > einkaufspreis wohnort ≠ arbeitsort

Bedingungen können des weiteren mit logischen Operatoren verknüpft werden, z.B. wohnort = 'Bremen' ∨ arbeitsort = 'Bremen' name = 'Matthiessen' ∧ vorname = 'Günter'

Schließlich können in die Vergleiche auch berechnete Ausdrücke eingehen, wie z.B. ankunft + INTERVAL '8' MINUTE < abfahrt

oder länge ≥ 1,41 * breite ∧ länge ≤ 235 mm ∧ breite ≤ 125 mm ∧ höhe ≤ 5 mm ∧ gewicht ≤ 20 g ∧ länge ≥ 140 mm ∧ breite ≥ 90 mm

Beispiel Relation, die die Artikel enthält, die nachbestellt werden müssen: Sel[bestand < mindestbestand] (Artikel) Artikel_ Nr

MWSt Satz

Bezeichnung

Listenpreis

Bestand

Mindestbestand

Verpackung

Lagerplatz

K003

2

Damenhut

65,70

12

20

Karton

2

L002

1

China-Tee

8,35

42

50

125 g

5

L005

2

Butterkekse

1,72

234

250

250 g

2

Beispiel Relation, die die Kunden aus dem PLZ-Bezirk 23863 sowie die Kunden aus Husum enthält: Sel[plz = '23863' ∨ ort = 'Husum'] (Kunde)

50

Sandini Bib

Relationenalgebra Kunden_ Nr

Status

Name

Straße

PLZ

Ort

Letzte_ Bestellung

102

W

Berger, Uwe

Allee 12 b

25813

Husum



100

S

Voss, Hans

Kuhdamm 12

23863

Nienwohld



101

S

Stein, Peter

Moordamm 34

23863

Kayhude

106

W

Staack, Hannes

An der Alster 1

23863

Kayhude

28.04.2000



… …

Eine Selektion besteht also darin, dass in einer Relation einige Zeilen gestrichen werden und nur die übrig bleiben, die die angegebene Bedingung erfüllen: Kunden_ Nr

Status

Name

Straße

PLZ

Ort

Letzte_ Bestellung



102

W

Berger, Uwe

Allee 12 b

25813

Husum



104

G

Andresen, Ute

Am Abhang

24558

Ulzburg



100

S

Voss, Hans

Kuhdamm 12

23863

Nienwohld



101

S

Stein, Peter

Moordamm 34

23863

Kayhude

28.04.2000



103

S

Randers, Nis

Am Seeufer 12

23845

Oering

15.05.2000



105

S

Stuff, Werner

Tarper Weg

24853

Eggebek

12.05.2000



106

W

Staack, Hannes

An der Alster 1

23863

Kayhude



Im Spezialfall dient die Selektion auch dazu, einen einzelnen Satz zu selektieren, indem ein eindeutiges Merkmal angegeben wird (z.B. der Schlüssel). Falls dieses Merkmal dann nicht in der Relation vorhanden ist, erhalten wir als Ergebnis die leere Relation, die also nur aus den Spaltenüberschriften besteht.

Beispiel Relation, die genau das Tupel mit den Kundendaten 103 enthält. Sel[kunden_nr = 103] (Kunde) Kunden_ Nr

Status

Name

Straße

PLZ

Ort

Letzte_ Bestellung



103 enthält. 103

S

Randers, Nis

Am Seeufer 12

23845

Oering

15.05.2000



Beispiel Relation, die genau das Tupel mit den Kundendaten des Kunden 128 enthält. Sel[kunden_nr = 128] (Kunde) KundenNr

Status

Name

Straße

PLZ

Ort

Letzte Bestellung



51

Sandini Bib

2 Einführung in das relationale Datenmodell

Es handelt sich hierbei um eine leere Relation, die aussagt, dass kein Tupel die geforderte Bedingung erfüllt.

2.4.2 Die Projektion Sei R eine Relation und {r1,…,rm} eine Teilmenge der Attribut-Bezeichner von R. Dann ist Proj[r1,…,rm] (R)

eine Relation mit den Attribut-Bezeichnern {r1,…,rm}, die für jedes Tupel t ∈ R genau ein Tupel [t.r1,…,t.rm] enthält. (Tupel, die mehrfach auftreten, werden einfach gezählt!). Das heißt, es zählt nur die Information der angegebenen Attribute – die übrigen Attribute werden ignoriert. Dadurch können Tupel der Relation R zusammenfallen – wenn sie nämlich in allen Attributen r1,… ,rm übereinstimmen, sich aber in mindestens einem Attribut, das nicht in der Projektion auftritt, unterscheiden.

Beispiel Relation, die für jeden Artikel neben der Artikelnummer und der Bezeichnung den Lagerplatz und den Bestand angibt (Bestandsliste). Proj[artikel_nr, bezeichnung, lagerplatz, bestand] (Artikel) Artikel_ Nr

Bezeichnung

Lager- platz

G001

Whisky

7

G002

Portwein

7

473

G003

Bier

7

1250

K001

Schuhe

2

120

K002

Hose

2

62

K003

Damenhut

2

12

K004

Sonnenbrille

2

50

L001

Ceylon-Tee

5

356

L002

China-Tee

5

42

L003

Naturreis

4

345

L004

Schokolade

2

2101

L005

Butterkekse

2

234

52

Bestand 397

Sandini Bib

Relationenalgebra

Beispiel Relation, die alle Orte mit PLZ enthält, in denen Kunden wohnen. Hierbei tauchen Orte mit mehreren Kunden nur einmal auf. Proj[plz, ort] (Kunde) PLZ

Ort

23845

Oering

23863

Kayhude

23863

Nienwohld

24558

Ulzburg

24853

Eggebek

25813

Husum

Die Projektion besteht also darin, dass gewisse Spalten ausgeblendet werden; nur die angegebenen Spalten bleiben übrig. Dabei kann es als Folgeaktion notwendig werden, bei mehrfach auftretenden identischen Zeilen jeweils alle bis auf eine zu streichen. Kunden_ Nr

Status

Name

Straße

PLZ

Ort

Letzte_ Bestellung



102

W

Berger, Uwe

Allee 12 b

25813

Husum



104

G

Andresen, Ute

Am Abhang

24558

Ulzburg



100

S

Voss, Hans

Kuhdamm 12

23863

Nienwohld



101

S

Stein, Peter

Moordamm 34

23863

Kayhude

28.04.2000



103

S

Randers, Nis

Am Seeufer 12

23845

Oering

15.05.2000



105

S

Stuff, Werner

Tarper Weg

24853

Eggebek

12.05.2000



106

W

Staack, Hannes

An der Alster 1

23863

Kayhude



2.4.3 Umbenennung von Attribut-Bezeichnern Die Umbenennung von Attributen ist in folgenden Fällen notwendig: Änderung der Überschrift einer auszugebenden Tabelle Zwei Tabellen sollen miteinander verknüpft werden (wird in Kapitel 2.4.6 eingeführt). Dazu müssen die korrespondierenden Attribute in den beiden Relationen jeweils denselben Bezeichner haben.

53

Sandini Bib

2 Einführung in das relationale Datenmodell

Zwei Tabellen sollen miteinander verknüpft werden. Dazu müssen die nicht korrespondierenden Attribute in den beiden Relationen jeweils unterschiedliche Bezeichner haben. Wenn a ein Attribut einer Relation R ist und b ein Bezeichner, der nicht als AttributBezeichner von R auftritt, wird durch Ren[b ::= a] (R)

eine Relation definiert, in der das Attribut a jetzt b heißt. Falls mehrere Umbenennungen erfolgen, schreiben wir diese hintereinander in eckige Klammern, wie im folgenden Beispiel. Ren [KNr ::= kunden_nr, St ::= status, LBest ::= letzte_bestellung, LWerb ::= letzte_Werbung, ZArt := Zahlungsart] (Kunde) KNr

St

Name

Straße

PLZ

Ort

LBest

LWerb 01.12.1999

ZArt

102

W

Berger, Uwe

Allee 12 b

25813 Husum

104

G

Andresen, Ute

Am Abhang

24558 Ulzburg

N

100

S

Voss, Hans

Kuhdamm 12

23863 Nienwohld

101

S

Stein, Peter

Moordamm 34 23863 Kayhude

28.04.2000

103

S

Randers, Nis

Am Seeufer 12

23845 Oering

15.05.2000

B

105

S

Stuff, Werner

Tarper Weg

24853 Eggebek

12.05.2000

R

106

W

Staack, Hannes

An der Alster 1

23863 Kayhude

N 01.12.1999

N

01.12.1999

B

01.12.1999

N

Da eine Umbenennung häufig im Zusammenhang mit einer Projektion erfolgt, schreiben wir in Zukunft als Kurzschreibweise die umbenannten Attribute in die Liste der Projektionsattribute mit hinein. Die umbenannten Attribute sind grundsätzlich mit in die Liste der zu projizierenden Attribute einzubeziehen (sonst bräuchten wir sie ja nicht erst umzubenennen). So wird Proj[ArtNr,Bezeichnung,Lager,Ist] ( Ren[ArtNr::=artikel_nr, lager::=Lagerplatz, ist::=bestand] (Artikel) )

zu: Proj[ArtNr::=artikel_nr, bezeichnung, lager::=lagerplatz, Ist::= bestand] (Artikel)

54

Sandini Bib

Relationenalgebra

ArtNr

Bezeichnung

Lager

Ist

G001

Whisky

7

397

G002

Portwein

7

473

G003

Bier

7

1250

K001

Schuhe

2

120

K002

Hose

2

62

K003

Damenhut

2

12

K004

Sonnenbrille

2

50

L001

Ceylon-Tee

5

356

L002

China-Tee

5

42

L003

Naturreis

4

345

L004

Schokolade

2

2101

L005

Butterkekse

2

234

2.4.4 Adjunktion virtueller Spalten Sei R eine Relation, und sei a ein Ausdruck, der aus Attribut-Bezeichnern der Relationen und Operationen, die für die Domänen definiert sind, sowie Konstanten gebildet ist, und s sei ein Bezeichner, der nicht als Attribut-Bezeichner in R auftritt; dann wird durch Adj[s ::= a] (R)

eine Relation definiert, die eine zusätzliche Spalte enthält, in der als Wert jeweils die Auswertung von a enthalten ist. Diese Spalte wird als virtuelle Spalte bezeichnet. Für ein Tupel t hängt also der Wert von s von den Werten der (echten) Attribute ab. Üblicherweise wird daher der Wert von s nicht mit in der Datenbank gespeichert, sondern bei jedem Aufruf neu berechnet. Auch hier übernehmen wir üblicherweise die adjungierten Spalten mit in die Liste der Projektionsattribute (vgl. hierzu das folgende Beispiel).

Beispiel Relation, die für jeden Artikel die angegebenen Attribute sowie das Produkt aus Bestand und Listenpreis enthält.

55

Sandini Bib

2 Einführung in das relationale Datenmodell

Proj[artnr, bezeichnung, bestand, listenpreis, wert] ( Ren[artnr ::= artikel_nr] ( Adj[wert ::= bestand * listenpreis] (Artikel) ) )

oder kürzer: Proj[artNr ::= artikel_nr, bezeichnung, bestand, listenpreis, wert ::= bestand * listenpreis] (Artikel) Artikel_ Nr

Bezeichnung

Bestand

Listen- Preis Wert

G001

Whisky

397

38,40

15.244,80

G002

Portwein

473

12,45

5.888,85

G003

Bier

1250

5,20

6.500,00

K001

Schuhe

120

98,50

11.820,00

K002

Hose

62

112,80

6.993,60

K003

Damenhut

12

65,70

788,40

K004

Sonnenbrille

50

76,00

3.800,00

L001

Ceylon-Tee

356

6,35

2.260,60

L002

China-Tee

42

8,35

350,70

L003

Naturreis

345

1,78

614,10

L004

Schokolade

2101

0,98

2.058,98

L005

Butterkekse

234

1,72

402,48

2.4.5 Gruppierung von Daten Wie wir gesehen haben, werden bei der Projektion gegebenenfalls mehrere Tupel jeweils zusammengefasst: wenn sie in den Projektionsattributen identisch sind, sich aber in anderen Attributen noch unterscheiden. Hier bilden die Tupel, die in den Projektionsattributen identische Werte haben, jeweils eine Datengruppe, wobei die Werte in den nicht projizierten Attributen unterschiedlich sein können. Häufig möchten wir für diese Datengruppen weitere Werte haben, die sich aus den Tupeln der jeweiligen Gruppen berechnen lassen. Im einfachsten Fall möchten wir nur die Anzahl der Tupel der jeweiligen Gruppen haben. Des Weiteren möchten wir z.B. die Summen der Artikelbestände in den einzelnen Lagern wissen. In diesen Fällen verwenden wir statt der Projektion die Datengruppierung. Zusätzlich zu den zu projizierenden Attributen hat die neue Relation weitere adjungierte Attribute, die durch die Anwendung von Aggregatfunktionen auf die Attribute, die nicht in der Projektion auftreten, entstehen. Formal schreiben wir die Anwendung der Aggregatfunktionen hinter die Projektionsattribute, durch einen senkrechten Strich getrennt.

56

Sandini Bib

Relationenalgebra

Grp[plz,ort| anzahl::=COUNT(*)] (Kunde) PLZ

Ort

Anzahl

23845

Oering

1

23863

Kayhude

2

23863

Nienwohld

1

24558

Ulzburg

1

24853

Eggebek

1

25813

Husum

1

Die Aggregatfunktion COUNT(*) ergibt für jede Datengruppe die Anzahl ihrer Tupel. Die weiteren Aggregatfunktionen haben jeweils eine Spalte oder virtuelle Spalte als Argument. Als Aggregatfunktionen können beliebige Funktionen auftreten, die Mengen von Werten als Argumente annehmen. In SQL sind das neben COUNT(*) folgende Aggregatfunktionen, die als Argument jeweils ein Attribut annehmen (z.B. SUM(Bestand)): COUNT COUNT DISTINCT SUM AVG MIN MAX

Anzahl definierter Werte Anzahl verschiedener Werte Summe Average, Durchschnitt Minimum Maximum

Als weitere Funktionen (die nicht in SQL definiert sind) kämen z.B. noch das Produkt von numerischen Werten oder statistische Kenngrößen wie Varianz, Median, geometrisches Mittel in Frage.

Beispiel Die folgende Relation gibt für jeden Lagerplatz die Summe der Artikelbestände an. Grp[lagerplatz | gesamtbestand ::= SUM(bestand)] (Artikel) Lagerplatz

Gesamtbestand

2

2579

4

345

5

398

7

2120

57

Sandini Bib

2 Einführung in das relationale Datenmodell

Beispiel Relation aller Lagerplätze, die einen Bestand von höchstens 1000 haben: Sel[gesamtbestand ≤ 1000] (Grp[lagerplatz| gesamtbestand::=SUM(bestand)] (Artikel)) Lagerplatz

Gesamtbestand

4

345

5

398

An diesem Beispiel ist zu beachten, dass hier die Selektion nach der Gruppierung durchzuführen ist.

Beispiel Im folgenden Beispiel tritt sowohl eine Selektion auf Tupel-Ebene als auch eine Selektion auf Gruppenebene auf. Es werden nur die selektierten Tupel in die Gruppe aufgenommen und anschließend die relevanten Gruppen ausgewählt: Wir wollen eine Liste der Lager mit dem jeweiligen Gesamtbestand haben, wobei wir uns nur für Artikel interessieren, die für mindestens 5,00 DM verkauft werden, und nur für Lager, in denen der Gesamtbestand dieser Artikel höchstens 1000 ist. Sel[gesamtbestand ≤ 1000]( Grp[lagerplatz | gesamtbestand ::= SUM(bestand)] ( Sel[listenpreis ≥ 5.00] (Artikel) ) ) Lagerplatz

Gesamtbestand

2

244

5

398

Ein Sonderfall der Datengruppierung tritt auf, wenn kein Gruppierungsattribut angegeben wird, sondern nur Aggregatfunktionen. In diesem Fall werden die Aggregatfunktionen auf die gesamte Tabelle angewandt. So eine Relation hat naturgemäß nur ein Tupel. Grp[|

gesamtwert maxbestand minpreis sortiment

::= ::= ::= ::=

SUM(bestand * listenpreis), MAX(bestand), MIN(listenpreis), COUNT(artikel_nr)] (Artikel)

Gesamtwert

MaxBestand

MinPreis

Sortiment

56.722,51

2101

0,98

12

58

Sandini Bib

Relationenalgebra

In diesem Fall können wir Varianten der Aggregatfunktionen definieren, die als Ergebnis keine Relation liefern, sondern einen Wert. So ist: SUM(bestand * listenpreis;Artikel) = 56722,51 MAX(bestand; artikel) = 2101 MIN(listenpreis; artikel) = 0,98 COUNT(artikel_nr; artikel) = 12

Ein weiterer Sonderfall ist gegeben, wenn hinter dem senkrechten Strich keine Anwendung einer Aggregatfunktion steht. In diesem Fall ist die Datengruppierung nichts anderes als die normale Projektion6.

2.4.6 Der Verbund (Join) Der Verbund ist eine sehr wichtige Operation im relationalen Datenbankmodell, da durch ihn die Möglichkeit gegeben ist, mehrere Relationen miteinander zu verknüpfen. In dieser abstrakten Darstellung des relationalen Datenmodells betrachten wir in erster Linie den sog. natürlichen Verbund (engl. natural join). Hieraus können wir den allgemeineren Gleichheitsverbund (equi join) erhalten, indem wir gegebenenfalls vorher die entsprechenden Attribute umbenennen. Den noch allgemeineren Verbund (θ-Join im Sinne von Codd, wobei der griechische Buchstabe Theta für eine beliebige zweistellige Operation wie =,, ≥ steht) behandeln wird hier nicht weiter, da er als Selektion auf dem Kreuzprodukt dargestellt werden kann und außerdem in der Praxis nur eine geringe Rolle spielt. Wie merken hier an, dass der natürliche Verbund, wie wir ihn hier einführen, für die theoretische Definition der Relationenalgebra hervorragend geeignet ist, da er einfacher zu definieren ist als die anderen Verbundoperationen. In der Praxis hat der natürliche Verbund allerdings einen sehr großen Nachteil: Er ist empfindlich gegen nachträgliche Änderungen des Datenbankschemas. Da sich die Verknüpfung auf alle Attributbezeichner bezieht, die (absichtlich oder zufälligerweise) in beiden Relationen auftreten, kann durch die Einführung eines neuen Attributs (z.B. mit der Bezeichnung Bemerkung), das eigentlich mit der geplanten Verknüpfung nichts zu tun hat, das Ergebnis völlig geändert werden: Es werden dann keine Tupel mehr verknüpft, da z.B. die Bemerkungen in der Relation Bestellung nicht mit den Bemerkungen in der Relation Kunden übereinstimmen. Folgende Voraussetzungen müssen gegeben sein, damit ein Verbund definiert werden kann: 왘 R und S sind Relationen. 왘 a1,… an sind genau die Attribut-Bezeichner, die in R und S vorkommen (also

Durchschnittsmenge der Attribut-Bezeichner);

6 So ist in dem relationalen Datenbanksystem Microsoft Access in einer Abfrage eine Projektion formal als Gruppierung zu beschreiben.

59

Sandini Bib

2 Einführung in das relationale Datenmodell 왘 Für i = 1..n sind die Domänen von ai in R und in S jeweils widerspruchsfrei,

d.h. sie sind identisch oder es ist zumindest möglich, Werte dieser entsprechenden Domänen auf Gleichheit zu überprüfen; 왘 Die übrigen Attribut-Bezeichner von R und S sind jeweils verschieden.

Die Bedingungen 2 und 4 sind gegebenenfalls durch Umbenennungen von Attributen zu erzwingen. An dieser Stelle ist die Operation der Umbenennung essenziell.7 Es ist dann R Join[a1,…an] S

eine neue Relation, die wie folgt definiert ist: 1) Die Attribute von R Join[a1,… an] S sind genau die Attribute von R und S. 2) Die Verbindungsattribute a1,… an werden also genau einmal gezählt. 3) R Join[a1,… an]S enthält für alle Paare von Tupeln von r∈R und s∈S, die für alle Attribute von a1,… an definiert sind und jeweils identische Werte besitzen, jeweils das Tupel r+s. 4) Da nach der Voraussetzung für zu verknüpfende r und s alle Attribute von a1,… an identische Werte besitzen, sind r und s widerspruchsfrei8, und somit ist r+s definiert. Ein Tupel r∈R kann mit einem Tupel s∈S, mit mehreren Tupeln s∈S oder mit keinem Tupel s∈S verbunden werden.

Beispiel Bestellung Join[kunden_nr] Kunde Bestell_ Nr

Bestelldatum

Lieferdatum

Rechnungs- Kunden_ Status Name betrag Nr

Straße …

151

28.04.2000 02.05.2000 196,75

101

S

Stein, Peter

152

30.04.2000 02.05.2000 2270,86

103

S

Randers, Nis …

153

12.05.2000

105

S

Stuff, Werner

154

15.05.2000

103

S

Randers, Nis …

… …

7 In XBase fehlt diese Operation. Die JOIN-Anweisung enthält zwar die Möglichkeit, entsprechend Punkt 2 die Verbindungsbedingung zu formulieren, aber gleichnamige Feld-Bezeichner können nicht umbenannt werden. Somit sind die Operationen der Relationenalgebra in XBase nicht vollständig formulierbar (außer durch explizite Programmierung mit verschachtelten Programmschleifen – das können wir aber auch in jeder »normalen« Programmiersprache). 8 Vgl. Abschnitt 2.1.3.

60

Sandini Bib

Relationenalgebra

Diese Relation enthält für jedes Tupel der Relation Bestellung die Angaben (bestell_nr, bestelldatum, lieferdatum, rechnungsbetrag) sowie alle Kundendaten für die entsprechenden Kunden. Falls allerdings eine in der Relation Bestellung angegebene Kundennummer in der Relation Kunde nicht enthalten ist, wird diese Bestellung – ohne Warnung – ignoriert. (Dies kann nicht auftreten, da wir als Konsistenzbedingung eine referenzielle Konsistenz angegeben haben – hier sehen Sie auch, wozu diese referenzielle Konsistenz wichtig ist). Grafisch können wir diese Verknüpfung auch in folgender Form darstellen, indem wir die zu verknüpfenden Attribute durch eine Linie verbinden: Bestell_ Nr

Kunden_ Nr

Bestell- datum

Liefer- datum

Rechnungsbetrag

151

101

28.04.2000

02.05.2000

196,75

152

103

30.04.2000

02.05.2000

2.270,86

153

105

12.05.2000

154

103

15.05.2000

= Kunden_ Nr

Status

Name

Straße

PLZ

Ort

Letzte_ Bestellung



102

W

Berger, Uwe

Allee 12 b

25813

Husum



104

G

Andresen, Ute

Am Abhang

24558

Ulzburg



100

S

Voss, Hans

Kuhdamm 12

23863

Nienwohld



101

S

Stein, Peter

Moordamm 34

23863

Kayhude

28.04.2000



103

S

Randers, Nis

Am Seeufer 12

23845

Oering

15.05.2000



105

S

Stuff, Werner

Tarper Weg

24853

Eggebek

12.05.2000



106

W

Staack, Hannes

An der Alster 1

23863

Kayhude



Beispiel (Self Join) Verbindungen müssen nicht immer über Schlüsselattribute hergestellt werden. Durch entsprechende Umbenennung können auch Relationen mit sich selbst verknüpft werden. Hierzu sei die folgende Relation Kaiser gegeben: Kaiser

61

Sandini Bib

2 Einführung in das relationale Datenmodell

Name

Beiname

Vater

Karl I

der Große

Ludwig I

der Fromme

Todesjahr 814

Lothar I

Karl I

840

Ludwig I

855

Ludwig II

der Deutsche

Ludwig I

876

Karl II

der Kahle

Ludwig I

877

Ludwig II

880

Ludwig II

882

Karlmann Ludwig III

der Jüngere

Karl III

Ludwig II

888

Arnulf

Karlmann

899

Arnulf

911

Ludwig IV

das Kind

Durch Proj[a_name::=name, vater] (Kaiser) Join[Vater] Proj[b_name::=name, vater] (Kaiser)

bekommen wir die Relation der Brüder – wobei hier allerdings noch jeder, der einen Vater hat, als sein eigener Bruder gilt, d.h. Tupel der Form [a_name='Ludwig I', b_name='Ludwig I', vater='Karl I']

sind zugelassen. Um diese auszuschließen, müssen wir anschließend eine Selektion vornehmen: Sel[a_Name ≠ b_Name] ( Proj[a_name::=name, vater] (Kaiser) Join[vater] Proj[b_name::=name, vater] (Kaiser) ) A_Name

Vater

B_Name

Karl II

Ludwig I

Ludwig II

Karl II

Ludwig I

Lothar I

Lothar I

Ludwig I

Karl II

Lothar I

Ludwig I

Ludwig II

Ludwig II

Ludwig I

Karl II

Ludwig II

Ludwig I

Lothar I

Karl III

Ludwig II

Ludwig III

Karl III

Ludwig II

Karlmann

Karlmann

Ludwig II

Karl III

62

Sandini Bib

Relationenalgebra

A_Name

Vater

B_Name

Karlmann

Ludwig II

Ludwig III

Ludwig III

Ludwig II

Karl III

Ludwig III

Ludwig II

Karlmann

Die Verbundoperation ist kommutativ, d.h. es kommt nicht auf die Reihenfolge der Relationen an – beide Relationen in einem Verbund sind vollständig gleichberechtigt. Es gilt grundsätzlich: R Join[rs] S

= S Join[rs] R

Die Verbundoperation ist assoziativ, d.h. für drei Relationen R, S, T mit den entsprechenden Mengen von Verbindungsattributen rs und st gilt stets (R Join[rs] S) Join[st] T = R Join[rs] (S Join[st] T )

Wir können somit vollständig auf die Angabe von Klammern verzichten und den letzteren Ausdruck durch R Join[rs] S Join[st] T

darstellen. In der grafischen Darstellung auf Seite 65 bedeutet das, dass auch mehrere Relationen verknüpft werden können und es nur auf die Existenz der Linien ankommt – nicht auf eine irgendwie geartete Pfeilrichtung oder Nummerierung der Verbindungen.

Beispiel Die Liste aller Artikel aus Lager 2, die von Kunden aus Kayhude geordert wurden, bekommen wir durch Proj[artikel_nr, bezeichnung] ( Sel[lagerplatz = 2 ∧ ort = 'Kayhude'] ( Kunde Join[kunden_nr] Bestellung Join[bestell_nr]Position Join[artikel_nr]Artikel ) )

oder Proj[artikel_nr, bezeichnung] ( Sel[ort = 'Kayhude' ] (Kunde) Join[kunden_nr] Bestellung Join[bestell_nr]Position Join[artikel_nr]Sel[lagerplatz = 2] (Artikel) )

63

Sandini Bib

2 Einführung in das relationale Datenmodell

oder Proj[artikel_nr, bezeichnung] ( Sel[lagerplatz = 2](artikel) Join[artikel_nr]Position Join[bestell_nr]Bestellung Join[kunden_nr] Sel[ort = 'Kayhude' ] (Kunde) ) Artikel_nr

Bezeichnung

K002

Hose

K003

Damenhut

Alle drei Ausdrücke liefern dasselbe Ergebnis – allerdings ist der Rechenaufwand unterschiedlich. Am höchsten ist er für die erste Formulierung, da hier erst alle Tupel verknüpft werden und die Selektion am Schluss erfolgt. Für die zweite und dritte Formulierung ist a priori nicht klar, welche Formulierung weniger Rechenaufwand erfordert – es ist dort nur die Reihenfolge der Verbundoperation unterschiedlich – , möglicherweise ergibt sich daraus überhaupt kein Unterschied. Dieses Beispiel zeigt auch, dass ein Datenbanksystem sinnvollerweise einen Abfrage-Optimierer benötigt. Dieser soll in der Lage sein, eine gegebene Abfrage so in eine äquivalente Abfrage (d.h. eine Abfrage mit derselben Ergebnismenge) umzuformen, dass der Rechenaufwand möglichst gering wird. Hierzu stehen dem Abfrage-Optimierer Informationen über die physikalische Speicherorganisation sowie über die Anzahl der Tupel in den beteiligten Relationen und gegebenenfalls Erfahrungen aus vergangenen Abfragen zur Verfügung. Meistens sind die automatisch erzeugten Abfragepläne relativ gut – bei komplexen Anfragen kann gegebenenfalls ein manuelles Tuning überlegen sein.

Beispiel Im Folgenden soll eine Liste der Bestellungen mit dem Bestelldatum, Lieferdatum und der Kundennummer sowie dem Rechnungsbetrag ausgegeben werden. Grp[bestell_nr, bestelldatum, lieferdatum, kunden_nr | rechnungsbetrag ::= SUM (gesamtpreis * (1+ MWSt))] ( Bestellung Join[bestell_nr] Position Join[artikel_nr] Artikel )

64

Sandini Bib

Relationenalgebra

Bestell_nr

Bestelldatum

Lieferdatum

Kunden_Nr

Rechnungsbetrag

151

28.04.2000

02.05.2000

101

196,75

152

30.04.2000

02.05.2000

103

2270,86

153

12.05.2000

105

154

15.05.2000

103

2.4.7 Das Kreuzprodukt In der Datenbankpraxis spielt das Kreuzprodukt nur eine geringe Rolle – es ist aber im ursprünglichen Codd'schen Modell vor dem Verbund eingeführt worden, da das Kreuzprodukt mathematisch einfacher ist als der Verbund. Der Verbund kann als Selektion auf dem Kreuzprodukt definiert werden. Umgekehrt ist das Kreuzprodukt ein Spezialfall des natürlichen Verbundes: wenn nämlich die Menge der Verbindungsattribute leer ist, d.h. R X S = R Join[ ] S .

Die Voraussetzung für das Kreuzprodukt ist also, dass die Attribut-Bezeichner der beteiligten Relationen jeweils verschieden sind – gegebenenfalls sind sie vorher umzubenennen.

Beispiel Es seien die beiden Relationen Werktag und Unterrichtsblock gegeben. Werktag TagNr

TagName

1

Montag

2

Dienstag

3

Mittwoch

4

Donnerstag

5

Freitag

Unterrichtsblock BlockNr

Anfang

Ende

1

08:00

09:30

2

09:45

11:15

3

11:30

13:00

65

Sandini Bib

2 Einführung in das relationale Datenmodell

BlockNr

Anfang

Ende

4

13:45

15:15

5

15:30

17:00

6

17:15

18:45

Werktag X Unterrichtsblock TagNr

TagName

BlockNr

Anfang

Ende

1

Montag

1

08:00

09:30

1

Montag

2

09:45

11:15

1

Montag

3

11:30

13:00

1

Montag

4

13:45

15:15

1

Montag

5

15:30

17:00

1

Montag

6

17:15

18:45

2

Dienstag

1

08:00

09:30

2

Dienstag

2

09:45

11:15











4

Donnerstag

5

15:30

17:00

4

Donnerstag

6

17:15

18:45

5

Freitag

1

08:00

09:30

5

Freitag

2

09:45

11:15

5

Freitag

3

11:30

13:00

5

Freitag

4

13:45

15:15

5

Freitag

5

15:30

17:00

5

Freitag

6

17:15

18:45

Diese Relation enthält für jeden Tag jeden Unterrichtsblock. Bei fünf Tagen und sechs Unterrichtsblöcken also 5 * 6 = 30 Tupel. Dieses sind genau die möglichen Kästchen auf einem Stundenplan für einen Schüler oder Dozenten. Wenn wir nur die Tupel jeweils durch ein Paar aus den ersten beiden Anfangsbuchstaben des Tages und der Nummer des Blocks beschreiben und für die beiden Ausgangsrelationen die horizontale bzw. vertikale Achse nehmen, bekommen wir ein Rechteck, das genau die Kombinationen der beiden Ausgangsrelationen enthält, wie in der folgenden abgewandelten Darstellung sichtbar wird:9

9 Eine solche sogenannte »Kreuztabelle« zu erstellen, ist nicht Aufgabe der Relationenalgebra, sondern von Report-Werkzeugen, mit denen wir uns hier nicht weiter beschäftigen.

66

Sandini Bib

Relationenalgebra

Mo

Di

Mi

Do

Fr

1

[Mo,1]

[Di,1]

[Mi,1]

[Do,1]

[Fr,1]

2

[Mo,2]

[Di,2]

[Mi,2]

[Do,2]

[Fr,2]

3

[Mo,3]

[Di,3]

[Mi,3]

[Do,3]

[Fr,3]

4

[Mo,4]

[Di,4]

[Mi,4]

[Do,4]

[Fr,4]

5

[Mo,5]

[Di,5]

[Mi,5]

[Do,5]

[Fr,5]

6

[Mo,6]

[Di,6]

[Mi,6]

[Do,6]

[Fr,6]

Allgemeiner R1 und R2 seien Relationen; alle Attribut-Bezeichner von R1 und R2 seien verschieden. Die Relation R1 × R2 enthält alle Attribut-Bezeichner von R1 und R2. Für jedes Tupel t1∈ R1 und jedes t2 ∈ R2 ist t1+t2 ∈ R1 × R2. Insbesondere ist die Anzahl der Tupel von R1 × R2 das Produkt der Anzahlen der Tupel von R1 und R2, d.h. die Zahl

kann sehr groß werden. Eine nicht erwünschte Rolle spielt das Produkt aus folgendem Grund: vergisst ein Benutzer, die Verbindungsattribute anzugeben, erhält er statt einer Verbundoperation das Produkt. Leider waren im SQL-Standard vor 1992 die Verbundattribute im Zusammenhang mit den Selektionskriterien festzulegen, so dass diese leicht vergessen werden konnten. In SQL-92 ist dies nicht mehr so problematisch, da hier der Verbund als eigene Operation in der Abfrage-Anweisung auftritt. 10 Falls das Produkt einer Relation mit sich selbst gebildet werden soll, sind vorher mindestens in einer der beteiligten Relationen die Attribute umzubenennen.

2.4.8 Der äußere Verbund (Outer Join) Der Nachteil des natürlichen Verbundes ist, dass nur solche Tupel aufgenommen werden, für die explizit (mindestens) eine Verknüpfung existiert. Wenn wir in unserem Versandhandelbeispiel aber zum Beispiel eine Liste aller Kunden haben wollen, jeweils verknüpft mit ihren Bestellungen, so bekommen wir für die Kunden, für die keine Bestellung eingetragen ist, keine Ausgabe. Dies ist in der folgenden Relation dargestellt.

Beispiel Proj[name, bestell_nr, bestelldatum]( Kunde Join[kunden_nr] Bestellung)

10 vgl. hierzu Kapitel 5.3.2

67

Sandini Bib

2 Einführung in das relationale Datenmodell

Name

Bestell_Nr

Bestelldatum

Stein, Peter

151

28.04.2000

Randers, Nis

152

30.04.2000

Stuff, Werner

153

12.05.2000

Randers, Nis

154

15.05.2000

Nicht alle Kunden erscheinen in dieser Auflistung, sondern nur die, für die Bestellungen eingetragen sind. Wenn wir dagegen alle Kunden in der Aufstellung sehen wollen, müssen wir den äußeren Verbund benutzen. Es ist allerdings zu berücksichtigen, dass der äußere Verbund nur eingeführt werden kann, wenn ein Konzept von Nullmarken (vgl. Kapitel 2.5) eingeführt ist. Einige Attribute haben dann keine Werte, was durch sogenannte Nullmarken gekennzeichnet wird. Für die Relationen, deren Tupel auf jeden Fall erscheinen sollen, werden Sternchen an den eckigen Klammern nach dem Join-Operator angebracht. Somit gibt es drei verschiedene äußere Verbunde: Join*[…], Join[…]* und Join*[…]*. Diese werden als Left Outer Join, Right Outer Join und Full Outer Join bezeichnet. Häufig werden sie auch abgekürzt als Left Join, Right Join und Full Join bezeichnet; der oben eingeführte Verbund wird dann als Inner Join bezeichnet. Die obige Abfrage wird dann wie folgt dargestellt: Proj [name, bestell_nr, datum]

(Kunde Join*[kunden_nr] Bestellung)

Name

Bestell_Nr

Bestelldatum

Berger, Uwe

*

*

Andresen, Ute

*

*

Voss, Hans

*

*

Stein, Peter

151

28.04.2000

Randers, Nis

154

15.05.2000

Randers, Nis

152

30.04.2000

Stuff, Werner

153

12.05.2000

Staack, Hannes

*

*

Wenn der äußere Verbund mit dem natürlichen Verbund gemischt wird, dann kommt es gegebenenfalls auf die Reihenfolge der Operationen an. Wir können hier also nicht so sorglos auf Klammern verzichten wie bei dem natürlichen Verbund.

68

Sandini Bib

Relationenalgebra

Beispiel Um die Liste aller Artikel zusammen mit einer Liste aller Kunden zu bekommen, die diese Artikel gekauft haben, können wir folgenden Verbund verwenden: Artikel Join*[artikel_nr] (Position Join[bestell_nr] Bestellung Join[kunden_nr] Kunde)

Wir stellen dabei zuerst den inneren Verbund zwischen Position, Bestellung und Kunde her. Damit haben wir alle »gültigen« Positionen mit den uns interessierenden Daten. Der anschließende äußere Verbund mit der Relation Artikel stellt sicher, dass alle Artikel in der Liste erscheinen. Von diesem Verbund bilden wir die Projektion auf die interessierenden Attribute und erhalten: Proj[artikel_nr, bezeichnung, lieferdatum, kunden_name::=Name] ( Artikel Join*[artikel_nr] (Position Join[bestell_nr] Bestellung Join[kunden_nr] Kunde) ) Artikel_Nr

Bezeichnung

Lieferdatum

Kunden_Name

G001

Whisky

G001

Whisky

Randers, Nis

G002

Portwein

Randers, Nis

G002

Portwein

G003

Bier

Stuff, Werner

02.05.2000

Stein, Peter Randers, Nis

G003

Bier

02.05.2000

Stein, Peter

K001

Schuhe

02.05.2000

Randers, Nis

K002

Hose

02.05.2000

Stein, Peter

K003

Damenhut

02.05.2000

Stein, Peter

K003

Damenhut

02.05.2000

Randers, Nis

K004

Sonnenbrille

02.05.2000

Randers, Nis

L001

Ceylon-Tee

L002

China-Tee

L002

China-Tee

L003

Naturreis

Stuff, Werner

L004

Schokolade

Stuff, Werner

L005

Butterkekse

Stuff, Werner 02.05.2000

Stein, Peter

69

Sandini Bib

2 Einführung in das relationale Datenmodell

Die Klammerung (Artikel Join*[artikel_nr] Position) Join[bestell_nr] Bestellung Join[kunden_nr] Kunde

würde für den Fall, dass irgendeine Position nicht zu einer Bestellung gehört (ungültige Bestellung in der Relation Position) oder dass eine ungültige Kundennummer in der Relation Bestellung enthalten ist, die entsprechenden Artikel nicht mit aufführen, da für Artikel ohne Positionen das Verbindungsattribut NULL ist.

Hinweis: Wie wir eben gesehen haben, ist die Verwendung von mehreren verschiedenen (inneren und äußeren) Verbunden in einem relationalen Ausdruck problematisch. Voraussetzung dafür ist eine sehr genaue Analyse, und es sind dann Klammern zu setzen.

2.4.9 Mengenoperationen Seien R1 und R2 Relationen vom gleichen Typ (d.h. die Attribut-Bezeichner und ihre entsprechenden Domänen sind gleich, vgl. Kap. 2.1). Dann sind durch R1 ∪ R2 für die Vereinigungsmenge der Tupel von R1 und R2, d.h. die Menge der Tupel, die in R1 oder in R2 oder in beiden Mengen enthalten sind, R1 ∩ R2 für die Durchschnittsmenge, d.h. die Menge der Tupel, die sowohl in R1 und R2 enthalten sind, und R1 \ R2

für die Differenzmenge, d.h. die Menge der Tupel von R1, die nicht in R2 enthalten sind,

rein mengentheoretisch weitere Relationen definiert. 11

Beispiele Sel[lagerplatz=5](Artikel) ∪ Sel[lagerplatz=7](Artikel) Sel[verpackung='Karton'](Artikel) ∩ Sel[lagerplatz=7](Artikel) Sel[lagerplatz=7](Artikel) \ Sel[verpackung='Karton'](Artikel)

11 Wir können die Bedingung der Homogenität der Relationen bei der Vereinigungsbildung fallen lassen. Wir bekommen dann eine Relation, die als Attribute die Vereinigungsmenge der Attribute der zu vereinigenden Relationen enthält und die die Vereinigungsmenge der Tupel enthält – die jeweils nicht definierten Attribute enthalten dann Nullmarken. Dieses ist als OUTER UNION in SQL definiert. Für den Durchschnitt macht diese Erweiterung wenig Sinn, da dann immer eine leere Relation herauskommt – eben so wenig macht sie bei der Differenz Sinn, da dann nichts abzuziehen ist.

70

Sandini Bib

Relationenalgebra

Diese Beispiele können auch jeweils durch eine einfache Selektion beschrieben werden: Sel[lagerplatz=5 ∨ lagerplatz=7] (Artikel) Sel[verpackung='Karton' ∧ lagerplatz=7] (Artikel) Sel[lagerplatz=7 ∧ verpackung≠'Karton'] (Artikel)

Wenn dagegen zwei Relationen verknüpft werden sollen, die sich nicht von einer gemeinsamen Oberrelation ableiten lassen, können die Mengenoperationen Vereinigung und Differenz nicht durch andere Operationen ersetzt werden. Der Durchschnitt zweier Mengen kann allerdings als natürlicher Verbund dargestellt werden, wobei alle Attribute als Verbindungsattribute zu nehmen sind (vgl. die Relation im folgenden Beispiel 2). So können wir durch Verknüpfung der Relation Kunde mit der Relation Lieferant u.a. folgende Relationen bilden:

Beispiel 1 Proj[name,straße,plz,ort](Kunde) ∪ Proj[name,straße,plz,ort] (Lieferant)

ist die Relation der Geschäftspartner.

Beispiel 2 Proj[name,straße,plz,ort](Kunde) ∩ Proj[name,straße,plz,ort] (Lieferant)

ist die Relation der Lieferanten, die gleichzeitig Kunden sind. Dies ist äquivalent zu: Proj[name,straße,plz,ort] (Kunde) Join[name,straße,plz,ort] Proj[name,straße,plz,ort] (Lieferant)

Beispiel 3 Proj[name,straße,plz,ort] (Kunde) \ Proj[name,straße,plz,ort](Lieferant)

ist die Relation der Lieferanten, die keine Kunden sind.

2.4.10 Übungsaufgaben Die folgenden Aufgaben können gegebenenfalls auch mit einem DBMS gelöst werden, das die relationalen Operationen – wenigstens teilweise – über eine grafische Benutzeroberfläche für die Gestaltung von Abfragen anbietet. Beispiele sind Access und Paradox oder auch Query von Microsoft und der Discoverer von Oracle.

71

Sandini Bib

2 Einführung in das relationale Datenmodell

Aufgabe 2.2 Beschreiben Sie folgende Fragen durch Verknüpfung der Relationen aus dem Anhang C. a) An welchen (verschiedenen) Lagerplätzen haben Sie Artikel? b) An welchen Orten mit PLZ wohnen Kunden? c) Bei welchen Positionen sind Artikel mit den Nummern 'G001', 'G002' oder 'G003' geliefert worden? d) Bei welchen dieser Positionen ist die Liefermenge größer als 2? e) Bei welchen Positionen sind keine Artikel mit den oben genannten Nummern geliefert worden? f) Welche Kunden sind keine Stammkunden? Geben Sie die Kundennummer, den Namen, den Ort und den Status aus. g) Welche Kunden sind keine Stammkunden und nicht aus Husum? h) Welche Bestellungen sind vom Mai 2000? i) Es sollen die Positionen aufgelistet werden, in denen die Artikel 'K001' oder 'G003' vorkommen. j) Bei welchen Artikeln liegt der Listenpreis zwischen 6 und 15 DM? k) Lassen Sie pro MWSt-Satz die Anzahl der davon betroffenen Artikel anzeigen. l) Geben Sie jeweils die größte Kundennummer der Kunden mit demselben Status aus. m) Zeigen Sie je Lagerplatz den kleinsten, den größten und den durchschnittlichen Listenpreis der dort gelagerten Artikel an. n) Wie viele Kunden haben Sie jeweils mit gleicher Postleitzahl? o) Unter welcher Postleitzahl haben Sie mehr als einen Kunden? p) Zu welcher Zahlungsart haben Sie mehr als zwei Kunden? q) Zeigen Sie zu jedem Artikel den Mehrwertsteuersatz an. r) Zeigen Sie mit Hilfe des Mehrwertsteuersatzes den Bruttopreis je Artikel an. s) Zeigen Sie zu jeder Bestellung den Lieferort an. t) Zeigen Sie zu jeder Bestellposition die Bestellmenge, Bestellnummer und den Lieferort an. u) Zeigen Sie je Ort die Anzahl der bestellten Artikel an. v) Ermitteln Sie den billigsten Artikel (nicht nur den Preis des billigsten Artikels!). w) Welcher Kunde hat die letzte Bestellung aufgegeben? Zeigen Sie die Attribute kunden_nr, name und bestell_nr an. x) Welche Bestellungen sind nicht von Kunden aus Kayhude? y) Welche Artikel haben einen höheren Listenpreis als alle Artikel aus Lager 7?

72

Sandini Bib

Nullmarken in Datenbanken

2.5 Nullmarken in Datenbanken 2.5.1 Die Behandlung von fehlenden Attributwerten In relationalen Datenbanken ist es möglich, dass für ein Tupel ein Attribut fehlt. Wir sagen auch: »Das Attribut ist NULL« (vgl. [Codd86]). Wir sagen hier bewusst nicht: »Das Attribut hat den Wert NULL«. NULL ist nicht identisch mit dem numerischen Wert 0 oder dem Leerzeichen. Die Tatsache, dass kein Attribut vorhanden ist, wird durch eine Markierung in der Datenbank festgehalten. Diese Markierung kann abgefragt werden. Von daher ist es sinnvoll, von Nullmarken statt von Nullwerten zu sprechen. In der Literatur ist allerdings häufig noch von »Nullwerten« oder »null values« die Rede.

2.5.2 Verschiedene Arten von Nullmarken Nullmarken können unter anderem zweierlei Bedeutung haben: Sie können für Attribute stehen, die in der Realität einen Wert haben, der aber nicht bekannt ist (sog. A-Marken – für applicable). Sie können für Attribute stehen, für die in der Realität kein Wert existiert (sog. I-Marken – für inapplicable) In tabellarischen Darstellungen stellen wir A-Marken durch ein Fragezeichen und I-Marken durch ein Sternchen dar. Daneben sind weitere semantische Interpretationen von fehlenden Werten möglich.

Beispiele für I-Marken 왘 Abfahrtszeit eines Intercity-Zuges in einem Durchgangsbahnhof 왘 Telefonnummer für Personen ohne Telefon

I-Marken treten auch auf, wenn für ein Attribut noch kein Wert existiert – dieses Faktum an sich ist aber schon eine Aussage, die relevant sein kann, z.B. 왘 das fehlende Todesdatum als Information, dass die entsprechende Person noch

lebt 왘 das fehlendes Lieferdatum als Information, dass ein Auftrag noch nicht erfüllt

ist A-Marken treten in Bereichen auf, in denen Daten aus verschiedenen Quellen gesammelt werden. Beispiele dafür sind wissenschaftliche Datenbanken, wo Messergebnisse gespeichert werden.

73

Sandini Bib

2 Einführung in das relationale Datenmodell

A-Marken können auch in Datensammlungen auftreten, die zur Entscheidungsunterstützung angelegt werden, z.B. bei der Kriminalpolizei oder in Datenbanken, die der Marktbeobachtung dienen. In operativen Datenbanken von Unternehmen dürften A-Marken dagegen seltener sein, da dort die Vertragsbedingungen und Produktionsabläufe jeweils klar definiert sein müssen. Leider wird die Unterscheidung von A-Marken und I-Marken bislang nicht durch existierende Datenbanksysteme, insbesondere nicht durch SQL, unterstützt. Bei Benutzung von Nullmarken ist immer besondere Vorsicht notwendig, da beide (und weitere) Semantiken nebeneinander und ohne besondere Unterscheidung benutzt werden. Grundsätzlich müssen wir, wenn wir Nullmarken zulassen, festlegen, welche Semantik diese haben sollen. Beachten Sie, dass in der folgenden Tabelle die zweite Zeile die Bedeutung »Martin Venus hat kein Telefon« hat, während die vierte Zeile »Juppi Saturnus hat ein Telefon, aber die Nummer ist nicht bekannt« bedeutet. Person_1 PersNr

Name



Telefon

201

Adams, Eva

0471 / 12 34 56

202

Venus, Martin

*

203

Mondschein, Stella

0471 / 48 23 13

204

Saturnus, Juppi

?

Aussagen wie »Es ist nicht bekannt, ob Castor Pollux ein Telefon hat« können in der obigen Tabelle so nicht ausgedrückt werden. Hierzu wäre eine weitere Nullmarke einzuführen, beispielsweise ?*. Person_2 PersNr

Name



Telefon

201

Adams, Eva

0471 / 12 34 56

202

Venus, Martin

*

203

Mondschein, Stella

0471 / 48 23 13

204

Saturnus, Juppi

?

205

Pollux, Castor

?*

Falls diese Unterscheidung nicht zur Verfügung steht, können wir uns dadurch helfen, dass wir eine weitere Spalte einführen, etwa in folgender Form:

74

Sandini Bib

Nullmarken in Datenbanken

Person_3 PersNr

Name

201



hat_Telefon

Telefon

Adams, Eva

Ja

0471 / 12 34 56

202

Venus, Martin

Nein

*

203

Mondschein, Stella

Ja

0471 / 48 23 13

204

Saturnus, Juppi

Ja

?

205

Pollux, Castor

?

Nach [Date90a S. 219 ff. und Date00 S. 585] gibt es beliebig viele unterschiedliche Semantiken für Nullmarken. Die Behandlung von Nullmarken ist im ursprünglichen Codd'schen relationalen Datenmodell nicht vorgesehen. Da aber in vielen Anwendungen die Notwendigkeit auftrat, hierfür eine Behandlung zu haben, sind viele Ad-hoc-Erweiterungen in relationalen Systemen eingefügt worden, so auch in SQL. Der Ansatz in SQL führt zu verschiedenen Inkonsistenzen, auf die Date ab 1986 hingewiesen hat (vgl. z.B. [Date90a S. 339 ff.]). A-Marken und I-Marken spielen eine exotische Rolle in der Theorie der relationalen Datenbanken. Eine Erweiterung des relationalen Datenmodells um A-Marken und I-Marken wird z.B. in [Codd90] vorgeschlagen. Doch auch dieser Ansatz hat nicht die Konsistenz des relationalen Datenmodells ohne Nullmarken. Das liegt daran, dass aus pragmatischen Gründen eine einfache Behandlung dieser Marken sinnvoll ist – andererseits lassen sich viele Beispiele finden, in denen dieser Ansatz zu kurz greift. Eine Theorie dagegen, die alle vorhandenen semantischen Informationen im Zusammenhang mit Nullmarken auswertet, verliert die effiziente Berechenbarkeit des relationalen Modells, und eben diese ist eines der hervorragenden Eigenschaften dieses Datenmodells. Wir zeigen nun einige Probleme im Zusammenhang mit A-Marken und I-Marken auf. Als wichtigstes Ergebnis kommt dabei heraus, dass diese beiden Marken logisch unterschiedlich zu handhaben sind. Da aber auch die in [Codd90] vorgeschlagene vierwertige Logik nur ein Hilfsmittel ist, um eine große Menge von Anwendungen darstellen zu können, ohne Probleme bei der Berechenbarkeit zu bekommen, gilt nur eines: Jeder Anwender, der Abfragen formuliert, in denen gegebenenfalls Nullmarken miteinander verglichen werden können, muss sich genau darüber im Klaren sein, was herauskommen soll, wenn A-Marken oder I-Marken in den Vergleich eingehen. Falls das nicht mit der vom Datenbanksystem unterstützten Logik übereinstimmt, müssen gegebenenfalls präzisere und differenzierte Datendarstellungen und Abfragen gefunden werden.

I-Marken in Relationen In Relationen mit I-Marken sind Tupel zugelassen, für die gegebenenfalls einige Attribute nicht auftreten.

75

Sandini Bib

2 Einführung in das relationale Datenmodell

Grundsätzlich können Attribute, in denen I-Marken zugelassen sind, als äußerer Verbund von normalen Relationen dargestellt werden. Die Relation Bestellung, in der das Lieferdatum und der Rechnungsbetrag eine Nullmarke enthalten können, können wir als äußeren Verbund folgender zwei Tabellen aufbauen: Bestellung_2 Bestell_Nr

Kunde

Bestelldatum

151

101

28.04.2000

152

103

30.04.2000

153

105

12.05.2000

154

103

15.05.2000

und Lieferung Bestell_Nr

Lieferdatum

151

02.05.2000

Rechnungsbetrag 196,75

152

02.05.2000

2270,86

Die Relation Bestellung lässt sich darstellen als: Bestellung_2 Join*[bestell_nr] Lieferung

Bei der Selektion liefern Vergleiche mit I-Marken grundsätzlich nicht den Wert TRUE. So erhalten wir im Folgenden die Relation aller Lieferungen, die vor dem 8. Mai 2000 ausgeliefert worden sind: Sel[lieferdatum < DATE'2000-05-08'] (Bestellung) Bestell_Nr

Kunde

Bestelldatum

Lieferdatum

Rechnungsbetrag

151

101

28.04.2000

02.05.2000

196,75

152

103

30.04.2000

02.05.2000

2270,86

Auch die Selektion mit der komplementären Bedingung Sel[lieferdatum ≥ DATE'2000-05-08'] (Bestellung)

führt zu einer Ergebnisrelation, in der die Zeilen mit I-Marke beim Lieferdatum nicht enthalten sind. Codd führt für solche Fälle, mit der Begründung, dass sich I-Marken jeglichem Vergleich entziehen, einen eigenen Wahrheitswert ein: » At first glance, it appears to make sense to handle equality between two inapplicablevalue marks just like equality between two actual values. Note, however, that I-marks are neither values nor placeholders for values. They mean unknowable rather than unknown. Thus, within the condition part of a relational-language statement, whenever an I-mark is 76

Sandini Bib

Nullmarken in Datenbanken

equated to an actual value, an A-mark or an I-mark, the truth-value of such a condition is always taken to be MAYBE of type INAPPLICABLE.« [Codd90 Seite 180] Unterschiede in den verschiedenen Ansätzen (eigener Wahrheitswert oder FALSE für Vergleiche mit I-Marken) führen in Selektionen nur dann zu unterschiedlichen Ergebnissen, wenn wir eine Bedingung verwenden, die die Negation enthält. Solange die Bedingungen nur AND und OR enthalten, sind diese Fragen irrelevant. In den Fällen, in denen eine Abfrage mit NOT verwendet wird und Attribute I-Marken enthalten können, muss der Benutzer sich jeweils besondere Gedanken machen, was die entsprechenden Aussagen bedeuten. So ist die Menge der Züge von Bremerhaven nach Bremen, die nicht vor 12 Uhr in Wulsdorf halten, keineswegs identisch mit der Menge der Züge von Bremerhaven nach Bremen, die frühestens um 12 Uhr in Wulsdorf halten; denn sie enthält auch die Züge, die überhaupt nicht in Wulsdorf halten.

Prädikat isInapplicable Um feststellen zu können, ob ein Attribut eine I-Marke hat, führen wir das logische Prädikat isInapplicable ein. isInapplicable(x) hat den Wert TRUE, wenn das Attribut x eine I-Marke hat, und ist FALSE, wenn ein echter Wert vorhanden ist. So bekommen wir im Folgenden die Liste aller noch nicht abgearbeiteten Bestellungen: Proj[bestell_nr, kunde, bestelldatum] ( Sel[isInapplicable(Lieferdatum)] (Bestellung) ) Bestell_nr

Kunde

Bestelldatum

153

105

12.05.2000

154

103

15.05.2000

Verbund unter Verwendung von Nullmarken Beim Verbund werden Tupel nicht verknüpft, wenn eines der Verknüpfungsattribute eine I-Marke enthält. Vergleichen Sie hierzu das folgende Beispiel: Abteilung Abt_Nr

Leiter

Umsatz

A

Hansen, Hannes

32.000,00 DM

B

Paulsen, Palle

50.000,00 DM

C

*

27.500,00 DM

D

Hansen, Hannes

E

*

F

Petersen, Pidder

41.200,00 DM 234.000,00 DM 48.600,00 DM

77

Sandini Bib

2 Einführung in das relationale Datenmodell

Der folgende Verbund ergibt die Relation aller Abteilungen mit demselben Abteilungsleiter. Das Ergebnis enthält nicht die Abteilungen C und E, obwohl in der Tabelle diese beiden Abteilungen als Abteilungsleiter denselben Eintrag (nämlich keinen!) haben. Sel[abt1 ≠ abt2] ( Proj[abt1 ::= abtNr, leiter] (Abteilung) Join[leiter] Proj[abt2 ::= abtNr, leiter] (Abteilung) ) Abt1

Leiter

Abt2

D

Hansen, Hannes

A

A

Hansen, Hannes

D

In den Aggregatfunktionen SUM, MAX, MIN, AVG werden Tupel mit einer I-Marke bei der Berechnung nicht berücksichtigt.

Prädikat isUnknown Das Auftreten einer A-Marke bezeichnen wir im Text durch UNKNOWN oder in Tabellen kürzer durch ein Fragezeichen. Entsprechend gibt es ein Prädikat isUnknown(attr), um abzufragen, ob ein Attribut einen unbekannten Wert hat. In arithmetischen Ausdrücken, in denen mindestens eine A-Marke als Argument auftritt, ist das Ergebnis eine A-Marke. Wenn wir im folgenden A für eine A-Marke setzen, gilt also 8+A=A, ebenso 0*A=A (obwohl hier mit einem gewissen Recht 0 als Ergebnis angenommen werden könnte). Vergleichsoperationen mit einer A-Marke liefern die logische Konstante UNKNOWN. Das gilt auch für Vergleiche wie etwa A m2, sonst 0.

2.6.11 Anwendung der Tabellenoperationen auf Relationen Für diesen Abschnitt bezeichnen wir die Projektion im Sinne der Relationenalgebra als ProjR und die Projektion Sinne der Tabellenenalgebra entsprechend der Definition von Abschnitt 2.6.4 als ProjT. Für eine Relation R ist ProT(R)

nicht immer eine Relation, sondern es kann eine Tabelle sein, die gewisse Tupel mehrfach enthält. 82

Sandini Bib

Tabellen und Relationen

Mit dem in Abschnitt 2.6.2 eingeführten Distinct-Operator erhalten wir die relationale Projektion ProR durch: ProR […](R) = Distinct(ProT[…](R))

Aus diesem Grund gibt es in SQL ein Schlüsselwort DISTINCT, das angibt, dass eine durchzuführende Projektion eine Relation als Ergebnis haben soll. Ohne Angabe von DISTINCT wird die entsprechende Projektion der Tabellenalgebra ausgeführt. Bei der Bildung der Vereinigungsmenge von zwei Relationen können Tupel doppelt gezählt werden, so dass hier die relationale Vereinigung von der tabellarischen Vereinigung abweicht. Für die relationale und tabellarische Variante der Vereinigung gilt: T1 ∪ T2 = Distinct (T1 + T2)

Anders als bei der Projektion ist beim UNION-Operator von SQL allerdings die relationale Variante der Standardfall. Um die tabellarische Operation zu erhalten, ist hier UNION ALL anzugeben. Für alle anderen Operationen sind die relationalen Operatoren Spezialfälle der Tabellenoperatoren. Wenn also die Operanden Tabellen sind, die keine mehrfach auftretenden Tupel haben, haben auch die Ergebnisse keine mehrfach auftretenden Tupel. Hiermit können wir jetzt auch den vermeintlichen Widerspruch aufklären, wieso Datenbanksysteme, die nach dem tabellarischen Datenmodell (z.B. Access, SQLDatenbanksysteme) arbeiten, dennoch als relational bezeichnet werden: Wir können in diesen Datenbanksystemen rein relational arbeiten, wenn wir uns an folgende Richtlinien halten: 왘 Jede Basisrelation muss einen Primärschlüssel haben. 왘 Bei Projektionen ist sicherzustellen, dass die relationale Projektion benutzt wird (in SQL durch SELECT DISTINCT). 왘 Beim UNION-Operator ist die relationale Variante zu wählen (in SQL UNION ohne das Schlüsselwort ALL).

2.6.12 Übungsaufgaben Aufgabe 2.5 Welche der folgenden Abfragen ergeben Relationen? Vorausgesetzt ist, dass die Ausgangstabellen jeweils Relationen sind, aber jeweils die für Tabellen definierten Operatoren benutzt werden. Es sind hierbei die jeweiligen Schlüssel- und Fremdschlüsseleigenschaften der Relationen entsprechend Anhang C zu beachten. a) ProjT[kunden_nr, name, straße, plz, ort] (kunde) b) ProjT[plz, ort] (kunde) c) kunde join[kunden_nr] bestellung

83

Sandini Bib

2 Einführung in das relationale Datenmodell

d) ProjT[bestell_nr] (kunde join[kunden_nr] bestellung) e) ProjT[kunden_nr] (kunde join[kunden_nr] bestellung)

2.7 Indexe in relationalen Datenbanken Während alle Informationen einer relationalen Datenbank in den Relationen enthalten sind und keine zusätzlichen Zugriffspfade existieren, die für die Semantik der Datenbank relevant sind, gibt es zur Beschleunigung einiger Operationen die sog. Indexe auf Relationen. Die Benutzung von Indexen gehört zum internen Schema einer relationalen Datenbank und ist daher nicht in den SQL-Standard aufgenommen worden. Die Indexe spielen jedoch eine große Rolle und sind in fast allen relationalen Datenbanksystemen zu finden. Ein Index ist durch die Angabe einer Tabelle und einer Menge von Attributen beschrieben, die den Index bilden. Daneben sind gegebenenfalls weitere Angaben möglich z.B. zur Sortierung oder Speicherorganisation. Wenn ein Index vorhanden ist, können Operationen, in denen die entsprechenden Attribute in einer Bedingung auftreten (Auswahl oder Verbund; aber auch für Projektion und Mengenoperationen sinnvoll) und weitere Zugriffe schneller durchgeführt werden. Neben der Beschleunigung bei gewissen Zugriffen werden allerdings manche Änderungsoperationen durch einen Index langsamer. In der Regel ist es sinnvoll, auf jeden Schlüssel und auf jeden Fremdschlüssel einen Index zu legen. Dieses sollte das Datenbank-Verwaltungssystem selbstständig erledigen. Schauen Sie bezüglich dieses Punktes in dem Handbuch Ihres Datenbanksystems nach. Im Folgenden wird der prinzipielle Aufbau eines Index auf der Relation »Artikel« auf dem Attribut »Lagerplatz« dargestellt. Zu diesem »Datenteil« des Index gehört dann noch ein B*-Baum oder ähnliches, um die Zugriffe auf die entsprechenden Sätze weiter zu beschleunigen. Hierzu wird die folgende Tabelle mit Angabe der Zugriffsadresse für die einzelnen Tupel verwendet (hier: die relative Satznummer – es kann auch andere sog. TupelIdentifikatoren geben, die z.B. die Lage in einem Block und die relative Nummer des Satzes in diesem Block beschreiben). Diese Zugriffsadresse ist nicht im Satz mit abgespeichert, kann aber vom Datenbank-Verwaltungssystem unmittelbar für den Datenzugriff verwendet werden. Ein Index muss sich nicht immer auf die relative Satznummer beziehen (wie es z.B. in XBase, Informix SE und – in modifizierter Form – in Adabas realisiert wird), sondern kann sich auf eine komplexere Satzadresse beziehen (z.B. auf sog. TupelIdentifikatoren aus Blocknummer und relativer Satznummer im Block wie in Oracle oder DB2).

84

Sandini Bib

Indexe in relationalen Datenbanken SatzNr

Artikel_ Nr

MWSt_ Satz

Bezeichnung

Listenpreis

Bestand

Mindestbestand

Verpackung

Lagerplatz

0

G001

2

Whisky

38,40

397

1

G002

2

Portwein

12,45

473

50

0,7 l

7

100

0,5 l

7

2

G003

2

Bier

5,20

1250

250

6er Pack

7

3

K001

2

Schuhe

98,50

120

25

Karton

2

4

K002

2

Hose

112,80

62

25

5

K003

2

Damenhut

65,70

12

20

Karton

2

6

K004

1

Sonnenbrille

76,00

50

20

Karton

2

7

L001

1

Ceylon-Tee

6,35

356

100

125 g

5

8

L002

1

China-Tee

8,35

42

50

125 g

5

9

L003

1

Naturreis

1,78

345

0

1 kg

4

10

L004

2

Schokolade

0,98

2101

1000

Tafel

2

11

L005

2

Butterkekse

1,72

234

250

250 g

2

2

Zwei mögliche Formeln eines Index sind in den beiden folgenden Abbildungen kurz dargestellt. Die erste Form mit fester Satzlänge wird z.B. in XBase verwendet. Die zweite Implementierung ist im Zugriff schneller und weniger speicheraufwendig – setzt allerdings voraus, dass das System in der Lage ist, Sätze variabler Länge zu verwalten. Lagerplatz

Satz-Nr

Lagerplatz

Satz-Nr

2

3

2

3,4,5,6,10,11

2

4

4

9

2

5

5

7,8

2

6

7

0,1,2

2

10

2

11

4

9

5

7

5

8

7

0

7

1

7

2

85

Sandini Bib

2 Einführung in das relationale Datenmodell

Das Anlegen eines Index darf nur Auswirkungen auf die Effizienz haben – der Benutzer muss zur Abfrageformulierung grundsätzlich dieselben Möglichkeiten unabhängig davon haben, ob ein Index vorhanden ist oder nicht. In diesem Sinne sind z.B. Systeme wie XBase oder Paradox keine Datenbanksysteme, da dort für gewisse Verknüpfungen Indexe vorausgesetzt werden.

2.7.1 Übungsaufgaben Aufgabe 2.6 Finden Sie für das von Ihnen benutzte Datenbanksystem heraus, auf welche Weise dort Indexe anzulegen sind. Aufgabe 2.7 Finden Sie für das von Ihnen benutzte Datenbanksystem heraus, für welche Integritätsregeln (z.B. Primärschlüssel, weitere Schlüssel, Fremdschlüssel) automatisch Indexe angelegt werden. Aufgabe 2.8 Legen Sie bei einer großen Datenbank zusätzliche Indexe an, und vergleichen Sie die Verarbeitungszeiten mit und ohne Index.

86

Sandini Bib

3

Datenbankentwurf

3.1 Anwendungsentwicklung, Prozess- und Datenmodell Wenn die Idee entsteht, für ein bestimmtes Arbeitsgebiet EDV-Unterstützung zu schaffen, wird ein Prozess in Gang gesetzt, an dessen Ende möglicherweise eine fertige EDV-Lösung steht: ein Computersystem mit einer für die Erledigung der gestellten Aufgabe mehr oder weniger tauglichen Software. Die Lösung einer anspruchsvolleren Aufgabe – wie etwa die Automatisierung der Auftragsbearbeitung – ist von der Stange meist nicht zu haben. Sie muss erst erstellt werden, mit erheblichem Aufwand an Zeit und Arbeit. Dabei entsteht eine Reihe von Tätigkeiten und Zwischenresultaten, die aufgrund ihrer wechselseitigen logischen und zeitlichen Abhängigkeit allgemein verschiedenen Phasen zugeordnet werden (siehe Abbildung 3.1). Problem

Systemanalyse

Anforderungsdefinition

Systementwurf

Spezifikation

Implementierung

vorläufiges Produkt

Test und Korrektur

Endprodukt

Nutzung

neue Anforderungen

Abbildung 3.1: Klassisches Phasenmodell der Softwareentwicklung

87

Sandini Bib

3 Datenbankentwurf

Die Tätigkeiten werden in der Grafik in Form von Rechtecken dargestellt. Die Zwischenresultate, die sozusagen zur nächsten Phase weitergereicht werden, erscheinen als Pfeile. Jede Phase wird mit einem definierten und dokumentierten Resultat abgeschlossen. Man nennt dieses Modell auch Software-Life-Cycle, womit ausgedrückt werden soll, dass eine Anwendungslösung im Grunde nie richtig fertig ist. Das benutzbare Resultat, in unserem Bild das »Endprodukt«, lässt neue Bedürfnisse nach Erweiterung oder Verbesserung entstehen – der Benutzer »entdeckt« neue Anforderungen, so dass der Prozess unter Umständen mit einer modifizierten, erweiterten Problemstellung von neuem beginnt. Dieses hier kurz skizzierte Modell hat heftige Diskussionen ausgelöst und etliche Korrekturen erfahren. Man hat festgestellt, dass es bei allen Bemühungen in der Praxis kaum ein Projekt gibt, das tatsächlich nach diesem linearen, immer nur vorwärts weisenden Muster abgewickelt wurde. Die Modifikationen, die am Modell vorgenommen wurden, reichen vom Hinzufügen rückwärts gerichteter Pfeile zwischen den Phasen (man kann jederzeit einen Schritt zurücktun) über »Spiralmodelle« bis hin zum »Prototyping«, wo möglichst schnell ein ablauffähiges Rumpfprogramm erstellt wird, an dem der Benutzer sehen kann, ob er seine Anforderungen richtig formuliert hat. Insofern markiert das in der Grafik vorgestellte Modell schon ein »Ideal« der Softwareproduktion. Wir beziehen uns hier wegen der Einfachheit der Darstellung weiter auf dieses Grundmodell. Das Phasenmodell, wie es in Abbildung 3.1 wiedergegeben wird, geht von einem Programm als Endprodukt aus. Ein Programm oder Programmpaket ist eine mehr oder weniger umfangreiche, aber doch fest vorgegebene Ansammlung von Operationen und Datenstrukturen, die der Anwender benutzen, aber nicht selbst gestalten kann. Dies trifft für jedes Anwendungsprogramm zu, wie umfangreich auch immer seine Funktionen sein mögen. Ergeben sich nun aus der praktischen Arbeit neue, bisher nicht berücksichtigte Informationsbedürfnisse, so muss das Programm erweitert oder umgeschrieben werden, sofern das Grundkonzept die Erfüllung der neuen Anforderungen überhaupt zulässt. Sonst ist im schlimmsten Fall eine völlige Neuauflage des ganzen Zyklus notwendig. Mit einem Datenbankkonzept wird hingegen die Organisation und Speicherung der Daten unabhängig von jeder einzelnen Anwendung realisiert. Den Kern der betrieblichen Informationsverwaltung bildet damit die Datenbank. Die Verwaltung des betrieblichen Datenbestands wird zu einer zentralen Funktion. Anwendungsprogramme und unterschiedliche Sichtweisen auf die Daten, die ablauf- und aufbauorganisatorischen Erfordernissen Rechnung tragen, beziehen sich auf die gemeinsame Datenbasis. Daneben gibt es interaktive Zugriffsmöglichkeiten auf die Daten mithilfe einer Datenbanksprache wie SQL oder datenbankunabhängigen Zugriffswerkzeugen, mit denen Benutzer ohne Kenntnis einer Sprache bequemen Zugriff auf Daten haben (sofern ihnen diese zugänglich sind). So können Informationen nach verschiedenen Kriterien abgefragt und Daten manipuliert werden, ohne dass in jedem Fall dazu Software entwickelt werden muss. Pro-

88

Sandini Bib

Anwendungsentwicklung, Prozess- und Datenmodell

gramme im herkömmlichen Sinn sind also nicht für jeden Datenzugriff notwendig, sondern nur dort, wo in einem Arbeitsgebiet jeweils bestimmte Folgen von aufeinander folgenden Operationen auszuführen sind, die sich für jeden gleichartigen Vorgang im Prinzip wiederholen. Man spricht in diesem Zusammenhang auch von »Geschäftsprozessen« und »Workflow«. Programme sind unter diesen Umständen nicht mehr identisch mit der EDV-Lösung, sondern nur ein Bestandteil von ihr. Die getrennte Betrachtung und Entwicklung von Datenstrukturen und automatisierten Verarbeitungsprozessen ist schließlich ein Hauptmerkmal der Client-ServerArchitektur, bei der Daten und Programme meist auf unterschiedlichen Rechnern implementiert werden. Der Gesamtprozess der Anwendungsentwicklung muss folgerichtig den Entwurf und die Realisierung der Datenbank als eigenständigen Zweig enthalten. Unser modifiziertes Phasenmodell stellt dies grafisch dar.

Problem

Systemanalyse

Anforderungsdefinition

Datenbankentwurf

Datenbankbeschreibung

Anwendungsentwurf

Datenbankrealisierung

Spezifikation

Datenbank

Test und Korrektur

Anwendungsimplementierung

vorläufiges Produkt

Endprodukt

Nutzung

neue Anforderungen

Abbildung 3.2: Modifiziertes Phasenmodell

89

Sandini Bib

3 Datenbankentwurf

Die erste Phase in Abbildung 3.2 ist die Systemanalyse, auch Anforderungsdefinition bzw. Requirements Definition genannt. Ihren Ausgang nimmt die Systemanalyse von den Benutzerwünschen. Ziel und Resultat ist eine exakte1 für Fachleute und Nichtfachleute gleichermaßen verständliche Formulierung der Forderungen an das zu erstellende Softwaresystem. Ist die Anforderungsdefinition erstellt, so teilt sich der Prozess. Der eine Zweig enthält den Entwurf und die Realisierung der Datenbank, der andere widmet sich den Anwendungsprogrammen. Der Datenbankentwurf resultiert in einem Datenbankschema, das direkt mittels der Datendefinitionssprache (DDL: Data Definition Language) in eine benutzbare Datenbank umgesetzt werden kann. Dieser Prozess wird in diesem Kapitel ausführlich beschrieben. Seine zunehmende Bedeutung für die Informationsverarbeitung entspringt dem Bedürfnis, über ein langfristig stabiles konzeptionelles Datenmodell als Ausgangsbasis für alle Anwendungen und Datenbanken zu verfügen. Darin sind die Daten unternehmensweit vereinheitlicht und auf eine gemeinsame begriffliche und logische Basis gestellt. Eine gesamtheitliche Sicht des Unternehmens gilt als entscheidende Voraussetzung dafür, den Nutzen der Informatik im Unternehmen zu erhöhen. Die Betrachtung und Gestaltung der Informationsverarbeitung unter diesem Gesichtspunkt ist eine anspruchsvolle, langwierige Aufgabe, deren Nutzen gleichwohl den Aufwand rechtfertigt.2 In der Phase Datenbankrealisierung werden die Datenbanktabellen erstellt, Zugriffsrechte vergeben und Benutzersichten auf Daten definiert. Das Resultat ist eine »leere« Datenbank, d.h. ein Gerüst, das für die Aufnahme von Daten vorbereitet ist. Daten sind in der Tat das Einzige, was dann für die Arbeit mit der Datenbank noch fehlt. In der Phase Anwendungsentwurf wird ein Modell des Softwaresystems entwickelt, das die in der Anforderungsdefinition festgelegten Prozesse zum Inhalt hat. Gegenstand sind hierbei komplexe Operationen auf der Datenbasis, die automatisiert werden sollen. Auch der Entwurf von Eingabe- und Editiermasken, Berichten sowie von Benutzermenüs gehört hierher. Das Modell ist so etwas wie die Architektur eines Anwendungsprogramms. Die Grundlage für den Entwurf von Prozessen sind die Daten, auf denen sie operieren sollen. Daher muss der Datenbankentwurf vor dieser Phase stattfinden. Die Datenbankbeschreibung geht in den Anwendungsentwurf ein, wie der Pfeil in Abbildung 3.2 andeutet. Während in den vorangegangenen Phasen noch keine einzige Programmzeile geschrieben wurde (höchstens als Pseudocode), geht es bei der Anwendungsimple1 Der Begriff »exakt« heißt hier »vollständig und konsistent«. Dabei bedeutet Vollständigkeit, dass alle vom Benutzer gewünschten Leistungen aufgeführt werden. Konsistenz bedeutet, dass keine Festlegung einer anderen widersprechen darf. [Somm87; S.16] 2 vgl. [Unte96]

90

Sandini Bib

Anwendungsentwicklung, Prozess- und Datenmodell

mentierung darum, aufgrund des »Bauplans« eine ablauffähige Lösung zu erstellen. Hier werden Menüs, Masken, Reports und verarbeitende Programme erstellt und zu einem Gesamtsystem zusammengefügt. Das resultierende »vorläufige Produkt« muss anschließend in der Testphase gründlich geprüft und korrigiert werden. In dieser Phase wird die Datenbank mit Testdaten gefüllt und sämtliche Prozeduren werden auf ihre Richtigkeit hin überprüft. Sind die erforderlichen Korrekturen eingebracht, erfolgt die Übergabe des »Endprodukts« verbunden mit der Installation auf der Hardware und der Einweisung der Benutzer. In der vorläufigen Endphase, der Nutzung, muss das Produkt seine Alltagstauglichkeit unter Beweis stellen. Hier zeigt sich, ob es für den Zweck, für den das ganze Projekt ins Leben gerufen wurde, tauglich ist. Es entstehen dabei neue Bedürfnisse nach Erweiterungen und Verbesserungen, aber auch nach Korrektur festgestellter Unzulänglichkeiten. Daher schließt sich der Kreis mit neuen, aus der Praxis geborenen Anforderungen, die einen neuen Phasenzyklus veranlassen können. Den Fall, dass eine fertige Lösung nach kurzem Gebrauch auf dem »Müll« landet, wollen wir freilich der Vollständigkeit halber nicht verschweigen. Wir werden im Folgenden zwei Methoden kennen lernen, die im Datenbankentwurf eine Rolle spielen: den Datenbankentwurf nach dem Entity-RelationshipModell (kurz ERM) und die Normalisierung. Diese beiden Ansätze beruhen auf unterschiedlichen Voraussetzungen. Die Grundlage der Normalisierung ist ein relationales Datenmodell. Die Normalisierung setzt also auf einer Abstraktionsebene auf, die nahe an der Implementierung im Rechner liegt. Das ERM geht von Entitäten (= Objekten) des abzubildenden Realitätsausschnittes aus. Im Prinzip ist das ERM unabhängig vom Datenmodell. Es wird jedoch heute fast ausschließlich zum Entwurf relationaler Datenbanken verwendet. Als das ERM entstand (1976), sind damit sehr wohl auch Datenbanken nach dem sog. Netzwerk-Datenmodell 3 entwickelt worden. Für objektorientierte Datenbanken – die nächste Generation – brauchen wir dagegen mehr semantische Möglichkeiten. Hier hat sich in den letzten Jahren die UML (Unified Modeling Language) als anerkannter Standard etabliert. Die UML ist sehr viel mächtiger als das ERM; die Entity-Relationship-Diagramme lassen sich jedoch fast unverändert in der UML darstellen. Daneben enthält die UML einige Konstrukte, die auch bei der Entwicklung relationaler Datenbanken relevant sind; diese werden wir in Abschnitt 3.3 kennen lernen.

3 Das »Netzwerk-Datenmodell« hat nichts mit den Computernetzwerken zu tun, sondern damit, dass die verschiedenen »Satzarten« des Datenmodells netzartig verknüpft werden konnten – im Gegensatz zum hierarchischen Datenmodell.

91

Sandini Bib

3 Datenbankentwurf

3.2 Grundbegriffe des EntityRelationship-Modells 3.2.1 Entität Eine Entität ist eine eigenständige Einheit, die im Rahmen des betrachteten Modells eindeutig identifiziert werden kann. Dieses Identifizierungsmerkmal wird als »Schlüssel« bezeichnet. Eine Entität kann z.B. Folgendes sein: 왘 ein Gegenstand

(z.B. ein bestimmtes Kfz) 왘 eine Kategorie von Gegenständen

(z.B. der Artikel 100 g Schokolade mit Lebertran, Marke Galaktika) 왘 eine Person 왘 ein Ereignis

(z.B. das Fußballspiel zwischen Werder Bremen und MSV Kayhude am 28.2.79) 왘 eine abstrakte Größe 왘 ein ausgefülltes Formular 왘 ein Dokument

Merke! 왘 Eine Entität wird durch eine Menge von Eigenschaften (Attributen) beschrie-

ben. 왘 Eine Eigenschaft hat einen Bezeichner und einen Wert. 왘 Eine Entität kann erzeugt werden. 왘 Die Eigenschaften einer Entität können geändert werden. 왘 Eine Entität kann gelöscht werden.

3.2.2 Abhängige Entität Eine Entität heißt abhängig, wenn die Existenz dieser Entität in dem betrachteten Modell von der Existenz einer anderen Entität abhängt und sie nicht durch eigene Attribute allein identifiziert werden kann. Abhängige Entitäten können erzeugt oder gelöscht werden und ihre Attribute können geändert werden. Die Entität, von der eine andere Entität abhängig ist, nennen wir Vaterentität. Beim Löschen der Vaterentität ist die abhängige Entität (automatisch) mit zu löschen. Beispiele für abhängige Entitäten sind: 왘 die Positionen einer Bestellung, die entfallen, wenn die Bestellung storniert

wird;

92

Sandini Bib

Grundbegriffe des Entity-Relationship-Modells 왘 Kinder von Arbeitnehmern (außer bei kleinen Firmen), da hier der Arbeitgeber

für die Zahlung des Kindergeldes zuständig ist. Beim Ausscheiden des Arbeitnehmers entfällt auch die Zahlung des Kindergeldes durch den Arbeitgeber. 왘 die Bankverbindung eines Kunden, der eine Einzugsermächtigung erteilt hat.

Beim Löschen des Kunden aus der Datenbank ist auch die Bankverbindung zu löschen.

3.2.3 Entitätentypen und Entitätenmengen Ein Entitätentyp ist eine abstrakte Zusammenfassung von Entitäten, die in dem betrachteten Modell durch dieselben Eigenschaften beschrieben werden können (z.B. Name, Länge in cm, Preis in Euro, ...). Jede mögliche Entität in dem Modell kann durch den angegebenen Entitätentyp beschrieben werden. Neben den Entitätentypen verwenden wir den Begriff Entitätenmenge als Übersetzung des von Chen eingeführten Begriffs entity set. Unter einer Entitätenmenge verstehen wir eine konkrete Sammlung (z.B. die Menge aller zu einem festen Zeitpunkt in einem Unternehmen angestellten Mitarbeiter). Eine Abfrage an die Datenbank bezieht sich immer auf die Entitätenmenge, z.B.: »Suche alle Kunden mit dem Wohnort Bremerhaven, die im letzten Jahr für mehr als 100 € bestellt haben.« Die Anzahl der Elemente einer Entitätenmenge ist zu jedem Zeitpunkt durch die tatsächlich vorhandenen Entitäten gegeben – diese Menge kann sich zu jedem Zeitpunkt ändern.

3.2.4 Attribut Die Eigenschaften der Entitäten in einem Entitätentyp werden durch Attribute beschrieben. Ein Attribut besteht aus einem Attribut-Bezeichner und einer Domäne für mögliche Eigenschaften von konkreten Entitäten. Da Entitäten jeweils nur einen Ausschnitt der Wirklichkeit wiedergeben – nämlich den Ausschnitt, für den wir uns in einem bestimmten Anwendungsbereich interessieren –, ist es sehr wichtig, festzulegen, durch welche Attribute wir die Entitäten beschreiben. So sind die Attribute, die eine Person als Patienten in einer Arztpraxis beschreiben, andere als die Attribute, die dieselbe Person als Mitarbeiter in einem Unternehmen beschreiben, und diese sind wiederum verschieden von den Attributen, die diese Person als Kunden einer Bank beschreiben. Daneben gibt es eine Unzahl von Attributen, für die sich glücklicherweise niemand interessiert (z.B. die exakte Anzahl der Haare).

93

Sandini Bib

3 Datenbankentwurf

3.2.5 Beziehung Mehrere Entitäten können in einer Beziehung (engl. relationship) stehen. Beziehungen können zweistellig sein oder mehr als zwei Entitäten einbeziehen. Die Entitäten in einer Beziehung spielen jeweils eine Rolle – gegebenenfalls kann dieselbe Entität (auch in einer Beziehung) mehrere Rollen spielen, wenn dies nicht ausdrücklich ausgeschlossen wird. 왘 So kann ein Vertrag als eine vierstellige Beziehung mit den Rollen

Kontrahent_1, Kontrahent_2, Dokument, Notar aufgefasst werden: [Kontrahent_1 = 'Amann, Axel', Kontrahent_2 = 'Bemann, Bernd', Dokument = 'Kaufvertrag über das Grundstück, Gemarkung Hudekamp 63/17', Notar = 'Cefrau, Cäcilie'] 왘 Eine Bestellung ist eine dreistellige Beziehung mit den Rollen Besteller, Händ-

ler und Ware.

Beziehungen können auch durch Eigenschaften näher beschrieben werden. So kann in einer Bestellung das Bestelldatum eine relevante Eigenschaft sein. Falls der Preis nicht fest mit der Ware verbunden ist, sondern frei ausgehandelt wird, ist auch der Preis eine Eigenschaft der Bestellung.

3.2.6 Beziehungstyp (Relationship Type) Ein Beziehungstyp beschreibt eine Klasse von Beziehungen, die jeweils dieselben Rollen und Eigenschaften haben. Für die Entitäten der entsprechenden Rollen wird jeweils ein Entitätentyp vorgegeben. Auch Beziehungstypen können durch Attribute ergänzt werden, die die Eigenschaften der Beziehung beschreiben.

3.2.7 Geschäftsregeln Neben der reinen Beschreibung von Daten, die einen bestimmten Unternehmensbereich widerspiegeln, enthält ein Datenmodell auch Geschäftsregeln. Das sind Vorgaben, die Einschränkungen an die möglichen Werte von Attributen und an die möglichen Beziehungen zwischen Entitätenmengen darstellen. Wichtige Geschäftsregeln sind z.B.: 왘 die Festlegung von eindeutigen Schlüsseln 왘 die Beschränkung von Beziehungen durch eine Angabe, wie viele Entitäten zu

einer anderen Entität in Beziehung stehen dürfen 왘 Einschränkungen der möglichen Wertebereiche von Attributen 왘 Abhängigkeiten zwischen Attributen wie Einkaufspreis < Verkaufspreis

94

Sandini Bib

Grundbegriffe des Entity-Relationship-Modells

Geschäftsregeln sind intentionale Bedingungen, d.h. Bedingungen, die aufgrund von Modell-Annahmen oder betrieblichen bzw. verwaltungsmäßigen Vereinbarungen zu gelten haben. Sie sind keine Bedingungen, die aufgrund zufälliger Umstände gerade gelten.

Beispiel (extensionale 1:1-Beziehung) Wenn in einem Unternehmen keine zwei Mitarbeiter dieselben Vor- und Nachnamen haben, ist damit extensional eine 1:1-Beziehung zwischen Mitarbeitern und Namen gegeben. Dies ist deswegen keine intentionale Beziehung, da nicht ausgeschlossen ist, dass gegebenenfalls später ein Mitarbeiter eingestellt wird, der denselben Namen hat wie ein schon vorhandener Mitarbeiter.

Beispiel (intentionale 1:1-Beziehung) Eine intentionale 1:1-Beziehung dagegen ist z.B. die Relation zwischen den Kraftfahrzeugen und ihren Zulassungskennzeichen, da hier eine Eindeutigkeit in beiden Richtungen (kein Fahrzeug mit zwei verschiedenen Kennzeichen/nicht dasselbe Kennzeichen für zwei verschiedene Fahrzeuge) vom System vorgegeben ist. Es kann hier »Systemfehler« geben (z.B. James Bond mit einem Aston Martin und mehreren wechselbaren Kennzeichen oder zwei verschiedene Fahrzeuge mit demselben Kennzeichen). Diese Systemfehler passieren aus organisatorischen Mängeln und/ oder aus der Absicht heraus, das System für eigene Zwecke außer Kraft zu setzen. Die Verletzung von Regeln ist kein Argument dagegen, Regeln einzuführen, sondern ein Argument dafür, bessere Maßnahmen zur Durchsetzung der Regeln einzuführen. (Dieses gilt natürlich nur für sinnvolle Regeln – Regeln, die aus dem einzigen Grund »Das haben wir immer schon so gemacht« bestehen, sollten einer Überprüfung unterzogen werden.)

Merke: 왘 Extensionale Beziehungen können nachträglich als solche festgestellt werden.

Sie bestehen zufällig oder ihre Gründe spielen für das Datenmodell keine Rolle. 왘 Intentionale Beziehungen sind nicht zufällig, sondern aus der Sache begründet.

Ihre Einhaltung muss mittels geeigneter Maßnahmen durch das DatenbankVerwaltungssystem sichergestellt werden. Für die Datenmodellierung spielen ausschließlich intentionale Beziehungen eine Rolle.

3.2.8 Schlüssel Jede Entität muss durch ihre Attribute eindeutig identifizierbar sein. Bei abhängigen Entitäten reichen Attribute, um jeweils die von einer Vaterentität abhängigen Entitäten zu unterscheiden. Dazu ist jeweils ein Schlüssel festzulegen, der aus

95

Sandini Bib

3 Datenbankentwurf

einem Attribut oder aus einer Menge von Attributen besteht. Es besteht dann die Regel, dass es keine zwei Entitäten geben kann, die in allen Attributen des Schlüssels übereinstimmen. Für abhängige Entitäten bedeutet dies, dass es keine zwei Entitäten geben kann, die von derselben Vaterentität abhängen und in allen Attributen des Schlüssels übereinstimmen.

Beispiele von Identifikationsschlüsseln: 왘 Kfz-Kennzeichen 왘 Fahrgestellnummer eines Kfz 왘 Motornummer eines Kfz 왘 Signatur eines Buches in einer Bibliothek 왘 ISBN-Nummer eines Buches 왘 EAN (Europäische Artikelnummer) 왘 Gebäudenummer und Raumnummer für einen Raum auf einem Gelände

Notwendige Eigenschaften von Schlüsselsystemen Da vorhandene Identifizierungssysteme (z.B. Name, Vorname) nicht immer die strengen Anforderungen an einen identifizierenden Schlüssel erfüllen, müssen wir häufig ein künstliches Schlüsselsystem einführen. Nach [Zehn85] hat ein künstliches Identifikationssystem folgende Forderungen zu erfüllen: 왘 Eindeutigkeit: Für jede Entität gibt es genau einen Identifikationsschlüsselwert,

der anderweitig nie vorkommt. Der Schlüssel ist unveränderlich. 왘 Laufende Zuteilbarkeit: Eine neu auftretende Entität erhält ihren Identifikations-

schlüssel sofort. 왘 Kürze, Schreibbarkeit: Ein Identifikationsschlüssel soll (relativ) kurz sein und

leicht geschrieben werden können. Dieses gilt allerdings nur für Verfahren, in denen der Schlüssel auch manuell eingegeben werden muss. Die folgende Eigenschaft steht mit den vorstehenden im Widerspruch (insbesondere mit der Unveränderlichkeit) und sollte nur Beachtung finden, sofern die obigen Eigenschaften dadurch nicht beeinträchtigt werden: 왘 Sprechender Schlüssel: Aus dem Identifikationsschlüssel sollen gewisse Eigen-

schaften der Entität ersichtlich sein.

Zur Problematik von sprechenden Schlüsseln Sprechenden Schlüsseln sieht man an, dass sie aus einem anderen Bereich stammen, nämlich einem Bereich, der ohne Unterstützung von Datenbanken konzipiert wurde. Verschiedene Informationen sind in dem Schlüssel untergebracht, um ohne DV-Unterstützung gewisse Eigenschaften schnell finden zu können. Zum Beispiel ist in Deutschland (wie auch in Frankreich und der Schweiz) auf den Kfz-Zeichen

96

Sandini Bib

Grundbegriffe des Entity-Relationship-Modells

die Zulassungsstelle erkennbar – in der Regel durch eine Buchstabenkombination oder in einem Sonderfall durch eine Buchstabenkombination (»HB«) und die Anzahl der Ziffern (bis zu drei für die Kommune Bremen, vier für die Kommune Bremerhaven). In einigen Nachbarstaaten wie Dänemark und Schweden ist diese sprechende Eigenschaft der Schlüssel vor einiger Zeit abgeschafft worden. Es entfällt dort auch die Notwendigkeit, das Kennzeichen bei Umzug oder Verkauf des PKW zu ändern. Bei Systemen, die DV-unterstützt auf einer Datenbank laufen, kann eine Entität durch die Angabe beliebiger Eigenschaften gefunden werden – diese Eigenschaften müssen nicht Bestandteil des Schlüssels sein. Falls diese Eigenschaften sich ändern, müsste der Schlüssel geändert werden. Schlüssel wie L-MUE85 für einen Lieferanten mit Namen Müller, der seit 1985 Geschäftspartner ist, sollten in einem DV-gestützten System nicht vergeben werden. In Systemen, die in erster Linie von menschlichen Lesern verarbeitet werden (wie dieses Buch), sind dagegen Schlüssel wie die hier verwendeten Kürzel für Literaturverweise, z.B. »[Zehn85]« für eine Schrift von Zehnder, die im Jahre 1985 erschienen ist, durchaus sinnvoll. Ein verwandtes Problem ist die Vergabe und Verwaltung von Schlüsseln in einer hierarchischen Organisation, in der eine zentrale Organisation mögliche Schlüsselbereiche an beteiligte Organisationen vergibt, die wiederum eigenverantwortlich diese Bereiche weiterverwalten. Dieses kann wegen der laufenden Zuteilbarkeit erforderlich werden. Beispiele hierfür sind die EAN (Europäische Artikelnummer), ISBN (internationale Standardbuchnummer) und die Internet-Adressen – die allerdings auch eine sprechende Komponente haben (wie hs-bremerhaven.de für die Hochschule Bremerhaven), um dem menschlichen Benutzer das »Speichern« der Adresse zu erleichtern. Bei der ISBN sind international Ziffern für die verschiedenen Länder vergeben worden, in jedem Land werden Nummern für die Verlage vergeben, und jeder Verlag nummeriert seine Bücher selbstständig durch.

3.2.9 ER-Diagramme In [Chen76] sind neben den Begriffen des Entity-Relationship-Modells (kurz ERM) auch Symbole für eine grafische Darstellung eingeführt worden, die später auf unterschiedliche Weise ergänzt und abgeändert wurden. In der Folge sind viele Variationen dieser Diagramme erschienen, da die ursprünglich von Chen eingeführten Diagramme für Systeme mit einer realistischen Größe nicht anwendbar sind. Wir verwenden die Variante, die in einigen Softwarewerkzeugen, z.B. dem PowerDesigner, Verwendung findet. Zum Einstieg stellen wir das konzeptionelle Datenmodell der Versand-Datenbank als ER-Diagramm dar.

97

Sandini Bib

3 Datenbankentwurf

Auftraggeber

Bestellung

Kunde

für Bankeinzug

Position

Artikel

Girokonto

MwSt_Satz

Abbildung 3.3: ER-Modell (Versandhandel)

Bedeutung: Die folgenden Bedeutungen ergeben sich aus dem Diagramm von »Girokonto« bis »MwSt_Satz« gegen den Uhrzeigersinn gelesen. 왘 Girokonto ist ein abhängiger Entitätentyp, d.h., dass ein Girokonto nur vorhan-

den sein kann, wenn ein entsprechender Kunde in der Datenbank vorhanden ist. Beim Löschen des Kunden ist das angegebene Girokonto automatisch zu löschen. 왘 Ein Kunde kann (maximal) ein Girokonto angeben (zum Bankeinzug). 왘 Eine Bestellung ist für höchstens einen Kunden bestimmt. 왘 Ein Kunde kann mehrere Bestellungen aufgeben. 왘 Eine Bestellung kann mehrere Bestellpositionen enthalten. 왘 Eine Bestellposition gehört zu genau einer Bestellung und ist von ihr abhängig,

d.h., eine Bestellposition kann nur im Rahmen einer Bestellung erzeugt werden. Wenn eine Bestellung storniert wird, wird automatisch die Bestellposition mit storniert. 왘 Eine Bestellposition enthält genau einen Artikel. (Über die Menge des Artikels

ist damit noch nichts ausgesagt.) 왘 Ein Artikel kann in mehreren Bestellpositionen auftreten. 왘 Einem Artikel ist genau ein Mehrwertsteuersatz zugeordnet. 왘 Derselbe Mehrwertsteuersatz kann für verschiedene Artikel verwendet wer-

den.

98

Sandini Bib

Grundbegriffe des Entity-Relationship-Modells

3.2.10 Kardinalitäten von zweistelligen Beziehungstypen Im Folgenden betrachten wir nur zweistellige Beziehungstypen. Grundsätzlich sind im Entity-Relationship-Modell auch Beziehungstypen mit mehr als zwei Rollen möglich. Die Behandlung von Beziehungstypen mit mehr als zwei Rollen betrachten wir weiter unten. Bei zweistelligen Beziehungstypen stellt sich die Frage, zu wie vielen Elementen der jeweils anderen Entitätenmenge ein Element in Beziehung stehen kann. Wenn Ent_1 und Ent_2 zwei Entitätenmengen sind, die in dem zweistelligen Beziehungstyp R stehen, interessieren wir uns dafür, wie viele Elemente aus Ent_2 jeweils zu einem Element aus Ent_1 in Beziehung stehen können (und umgekehrt). Als Mindestzahlen interessieren uns 0 oder 1 (obwohl es sicher auch Modelle gibt, wo die Mindestzahl 2 oder eine noch größere Zahl eine Rolle spielt). 0: optional, d.h., es kann Elemente aus Ent_1 geben, für die kein Element aus Ent_2 in der Relation R steht. 1: obligatorisch, d.h., für jedes Element aus Ent_1 muss (mindestens) ein Element aus Ent_2 in der Relation R stehen. Wie wir in Abbildung 3.4 sehen, ist diese Unterscheidung in der ursprünglichen Notation von Chen nicht möglich. Als Höchstzahl unterscheiden wir nur zwischen »höchstens 1« und »keine Einschränkung« (obwohl es auch hier sicher andere relevante Beschränkungen gibt, z.B. »höchstens 2«). 1: eindeutig, d.h., für jedes Element aus Ent_1 kann nur höchstens ein Element aus Ent_2 in der Beziehung R stehen. *

mehrdeutig, d.h., es kann Elemente aus Ent_1 geben, für die mehr als ein Element aus Ent_2 in der Relation R stehen.

In der Verknüpfung gibt es somit vier Möglichkeiten in einer Richtung (vgl. die Darstellungen in Abbildung 3.4): 0..1, 0..*, 1..1, 1..*. Umgangssprachlich dagegen werden diese Beziehungen nur als 1:1-Beziehungen, n:1-Beziehungen oder n:m-Beziehungen bezeichnet. Es werden nur die maximalen Kardinalitäten betrachtet. Dieses hat auch seine Ursache darin, dass die Unterscheidung, ob mehrere Entitäten mit einer Entität in Beziehung stehen können oder nur maximal eine, Konsequenzen auf die Speicherstruktur hat – im ersteren Fall müssen wir in irgendeiner Weise eine Konstruktion vorsehen, die es ermöglicht, mehrere Elemente zu verwalten. Im letzteren Fall können wir das Element,

99

Sandini Bib

3 Datenbankentwurf

das in Beziehung steht, direkt angeben. Dagegen ist die Frage, ob zu einer Entität notwendigerweise ein weiteres Element in Beziehung stehen muss, nicht von so weitreichender Konsequenz: Wir können die Nichtexistenz durch eine Nullmarke anzeigen.

(1)

(3)

(4)

0..1

1

c

0..*

N

mc

1..1

1

1

1..*

N

m

(2)

Legende: (1) Beschreibung des Bereichs ( * : keine obere Grenze ) – wird u.a. in der UML benutzt (2) Darstellung in ER-Diagrammen (3) Darstellung nach [Chen76] (4) Darstellung nach [Zehn85] Abbildung 3.4: Verschiedene Beschreibungen von Kardinalitätsbedingungen

Im Folgenden werden einige zweistellige Relationen beispielhaft dargestellt. Es ist zu beachten, dass die intendierten Beziehungen gegebenenfalls auch anders dargestellt werden können – es hängt jeweils vom festgelegten Kontext ab. So ist im ersten Beispiel in anderen Kulturkreisen auch eine Zuordnung von einem Mann zu mehreren Frauen, gegebenenfalls auch von einer Frau zu mehreren Männern möglich. Nach dem oben über intentionale Beziehungen Gesagten ist die Existenz von Bigamie kein Argument, dass die Ehe generell als m:n-Beziehung aufzufassen ist. Des Weiteren gilt die angegebene Bedingung im Rahmen der mitteleuropäischen Rechtsordnungen auch nur, wenn wir jeweils einen festen Zeitpunkt wählen – wenn dagegen eine historische Komponente enthalten ist, kann natürlich (juristisch einwandfrei) ein Mann zu verschiedenen Zeiten mit mehreren Frauen verheiratet sein – und vice versa

.

100

Sandini Bib

Grundbegriffe des Entity-Relationship-Modells

Ehefrau

Ehemann

Mann

Frau

Ehe

Kfz-Kennzeichen

Kfz Zulassung

Motor

Kfz Einbau

Reifen

Kfz Einbau

Bundesbürger

Einwohner

Wohnsitz

Gemeinde in BRD

Anmeldung

Wahlberechtigter Bundesbürger mind. 18 J a hre

erster Wohnsitz

Gemeinde in BRD

Anmeldung

Student

Studiengang Einschreibung

Auftraggeber

Auftrag

Kunde

Abbildung 3.5: Beispiele für zweistellige Beziehungen

Es ist auch möglich, dass bei einer zweistelligen Relation die beteiligten Entitätentypen identisch sind, wie in folgenden Beispielen: Vorgesetzter

Untersteller

Mitarbeiter

Mitarbeiter

Aggregat

Teil

Baugruppe

ist enthalten in

Teil

Abbildung 3.6: Zweistellige Beziehungen einer Entitätenmenge mit sich selbst

101

Sandini Bib

3 Datenbankentwurf

Hierfür wird in Diagrammen üblicherweise eine Entitätenmenge dargestellt und die Beziehung als Schleife von unten nach oben oder von rechts nach links. Vorgesetzter

Aggregat

Mitarbeiter

Teil Unterstellter

Baugruppe

Abbildung 3.7: Alternative Darstellung von Abbildung 3.6

Es hat sich gezeigt, dass es aus mehreren Gründen sinnvoll ist, die Kardinalität einer Beziehung jeweils an genau der gegenüberliegenden Entitätenmenge anzuschreiben und nicht, wie sie von Chen vorgeschlagen wurde und von uns oben eingeführt worden ist. Gezählt werden dann nicht die Anzahl Exemplare von Ent_2, die mit Ent_1 in Beziehung stehen, sondern die Anzahl von Beziehungen, die von einem Element aus Ent_1 zu Elementen aus Ent_2 bestehen können. Dieses führt leider zu einer gewissen Verwirrung in der Literatur, da bei einigen deutschen Autoren diese alternative Symbolik bevorzugt wird, während im internationalen Bereich und auch in vielen vorhandenen Design-Werkzeugen die oben eingeführte Notation verwendet wird (vgl. hierzu [Raas91]). Daher ist es unumgänglich, vor Verwendung von ER-Diagrammen die gewählte Nomenklatur zu erklären.

3.2.11 Domänen Auf der konzeptionellen Ebene, d.h., auf der Ebene des Entwurfs eines Datenmodells sind für die Beschreibung von Wertebereichen der Attribute Domänen auf einem abstrakten, d.h. anwendungsnahen Niveau, zu verwenden, z.B. Postleitzahl, Familienstatus oder Uhrzeit.4 Diese Vorgehensweise hat zwei Gründe: 왘 Die Entwurfsdokumentation ist klarer, wenn die Bedeutung von möglichen

Attributwerten inhaltlich beschrieben wird. 왘 Eine Festlegung auf Datentypen sollte erst erfolgen, wenn das Datenbank-Ver-

waltungssystem feststeht, da in Datenbank-Verwaltungssystemen unterschiedliche Möglichkeiten zur Verfügung stehen (z.B. Datentyp Uhrzeit, Möglichkeit der Kodierung von Mengen mit festgelegten Werten, Datentyp für logische Werte). In der Regel können sinnvollerweise nur Werte einer Domäne mit Werten derselben Domäne verglichen werden. (Es macht keinen Sinn, eine Kundennummer mit einer Postleitzahl zu vergleichen). Wenn in Ausnahmefällen etwas anderes beabsichtigt ist, ist es jeweils zu dokumentieren. 4 Zum Domänenkonzept vgl. Kap. 2.1.

102

Sandini Bib

Grundbegriffe des Entity-Relationship-Modells

3.2.12 Fallbeispiel: Versandhandel als ER-Modell Im Folgenden stellen wir die in Kapitel 2 eingeführte Versand-Datenbank als ERDiagramm vor, wie es vom PowerDesigner erstellt wird. Der Unterschied zu dem relationalen Modell ist, dass es hier keine Fremdschlüssel gibt. Die Beziehungen zwischen verschiedenen Entitätentypen werden durch Beziehungen dargestellt. Bei dieser Darstellung werden die Attribute und ihre Datentypen mit angegeben. Schlüsselattribute sind unterstrichen. Somit kann man nach diesem Modell recht zügig eine Datenbankstruktur in einem DBMS entwickeln. Wenn die Modelle umfangreich werden, ist diese ausführliche Darstellung möglicherweise zu unübersichtlich. Deshalb gehört es zu den Forderungen an Entwurfswerkzeuge, auf Wunsch Details aus- oder einblenden zu können. Bei der Definition des Entitätentyps »Girokonto« existiert kein eigener Schlüssel, sondern der Schlüssel wird von »Kunde« geerbt. Da die Beziehung eindeutig ist, wird kein eigenes (zusätzliches) Schlüsselattribut benötigt. Bestellung bestell_nr bestelldatum lieferdatum rechnungsbetrag

BESTELL_KEY DATUM DATUM MONEY

Kunde Auftraggeber

kunden_nr status name straße plz ort letzte_bestellung letzte_werbeaktion zahlung

KUNDEN_KEY KUNDEN_STATUS PERSONENNAME STRASSENNAME POSTLEITZAHL ORTSNAME DATUM DATUM ZAHLUNGSART

Position mwst_prozent bestellmenge liefermenge gesamtpreis

PROZENTSATZ CARDINAL CARDINAL MONEY

für Ba nke inzug

Girokonto konto_inhaber PERSONENNAME blz BANKLEITZAHL konto_nr KONTONUMMER

Artikel artikel_Nr bezeichnung listenpreis bestand mindestbestand verpackung lagerplatz kann_wegfallen bestellvorschlag nachbestellung nachbestellmenge

ARTIKEL_KEY STRING MONEY CARDINAL CARDINAL STRING LAGER BOOLEAN ZEITPUNKT ZEITPUNKT CARDINAL

MWSt_Satz mwst CARDINAL prozent PROZENTSATZ beschreibung STRING

Abbildung 3.8: ER-Diagramm für Fallbeispiel »Versandhandel«

103

Sandini Bib

3 Datenbankentwurf

An dieser Stelle könnten wir noch diskutieren, ob einige dieser Attribute nicht eigenständige Entitätentypen beschreiben, z.B. »Lagerplatz«. Diese Frage kann nicht allgemein entschieden werden, sondern hängt von der jeweiligen Umgebung ab. Wenn die aufzubauende Datenbank auch eine Lagerverwaltung enthalten soll, ist es sicher sinnvoll, »Lagerplatz« mit Attributen wie Kapazität, Lage und klimatischen Bedingungen als eigenständigen Entitätentyp zu definieren. Solange aber keine Attribute für »Lagerplatz« benötigt werden, reicht es aus, »Lagerplatz« als Attribut von »Artikel« zu verwenden.

3.2.13 Umsetzung eines ER-Modells in ein relationales Datenmodell Im folgenden diskutieren wir, wie aus dem ER-Diagramm ein Relationenschema abgeleitet wird. Am einfachsten ist es natürlich, die entsprechende Funktion des Design-Werkzeuges zu verwenden, das nicht nur das Modell grafisch darstellt (ggf. auch über mehrere Seiten), eine Beschreibung der Entitätstypen und Beziehungstypen mit den Attributen, Beschreibungen und Anmerkungen gibt, sondern auch eine Umwandlung in ein relationales Datenmodell erzeugt (dort physikalisches Datenmodell genannt im Gegensatz zu dem konzeptionellen [ERM] und objektorientierten [UML]).

Aus Entitäten werden Relationen Der erste Schritt ist denkbar einfach: Für jeden Entitätentyp in dem Datenmodell wird eine Relation gebildet. Die Attribute dieser Relation sind zum einen die Attribute des Entitätentyps, ggf. kommen weitere Attribute für Fremdschlüssel hinzu. Der Schlüssel wird aus den Schlüsselattributen des Entitätentyps gebildet.

Funktionale Beziehungen werden durch Fremdschlüssel realisiert Funktionale Beziehungen, d.h. 1:1- oder n:1-Beziehungen, können in praktisch jedem Datenmodell dadurch dargestellt werden, dass in irgendeiner Weise ein Verweis auf die Speicherstruktur hergestellt wird, die den rechten Entitätentyp realisiert (Zeiger auf den Vatersatz beim Netzwerk-Datenbankmodell, Verweis über Schlüssel in irgendeiner Form bei fast allen Datenmodellen). Im relationalen Datenmodell wird dieser Verweis über so genannte Fremdschlüssel realisiert (vgl. Kapitel 2.2). Bei n:1-Beziehungen nennen wir die Relation, die auf der Seite mit der Kardinalität 1..1 oder 0..1 steht, Vater-Relation, die andere SohnRelation. In die Sohn-Relation wird für jedes Schlüsselattribut der Vater-Relation ein Attribut eingebracht, das denselben Datentyp hat. Falls zwischen diesen beiden Relationen nur eine n:1-Beziehung existiert, können wir in der Regel die Bezeichner der Vater-Relation übernehmen. Die Beziehung zwischen Bestellung und Kunde kann also wie in Abbildung 3.9 aufgelöst werden.

104

Sandini Bib

Grundbegriffe des Entity-Relationship-Modells Kunde

Bestellung bestell_nr kunden bestelldatum lieferdatum rechnungsbetrag

integer

integer

date date numeric (15,2)

kunden_nr= kunden_nr

kunden_nr status name straße plz ort letzte_bestellung letzte_werbeaktion zahlung

integer char (1) char (30) char (30) char (5) char (25) date date char (1)

Abbildung 3.9: Realisierung durch Fremdschlüssel

Falls mehrere solche Beziehungen existieren wie in Abbildung 3.10, bietet es sich an, die Bezeichner der Rollen als Bezeichner für die Attribute zu übernehmen, wie in Abbildung 3.11.

Dozent

Prüfung

Prüfer

pruefungs_nr CARDINAL zeit ZEITPUNKT raum RAUM_NR

Beisitzer

dozent_Nr name raum telefon

DOZENT_KEY PERSONENNAME RAUM_NR TELEFON_NR

Abbildung 3.10: ER-Diagramm mit zwei Beziehungstypen zwischen zwei Relationen Pruefung pruefungs_Nr prüfer beisitzer zeit raum

integer

char (3)

char (3)

timestamp char (5)

Dozent dozent_Nr = prüfer dozent_Nr = beisitzer

dozent_Nr name raum telefon

char (3) char (30) char (5) char (20)

Abbildung 3.11: Relation mit zwei Fremdschlüsseln

Der Unterschied zwischen der Kardinalität 0..1 und 1 besteht nur darin, dass im ersten Fall die Attribute des Fremdschlüssels Nullmarken zulassen, im zweiten Fall nicht. Ein kleines Problem bekommen wir bei Anwendung dieser Methode bei 1:1-Beziehungen, wie z.B. in Abbildung 3.11. Es ist nicht klar, welche Relation die VaterRelation wird. Es gibt hier grundsätzlich drei Möglichkeiten: Fahrzeug CARDINAL fahrzeug_nr STRING typ anzahl_zylinder CARDINAL

Motor motor_nr hubraum anzahl_zylinder letzte_wartung

CARDINAL CARDINAL CARDINAL DATUM

Abbildung 3.12: 1:1-Beziehung

105

Sandini Bib

3 Datenbankentwurf

1) Wir erklären eine der beiden Relationen zur Vater-Relation und setzen den Fremdschlüssel entsprechend dem oben Gesagten in die Sohn-Relation ein. In dem ER-Diagramm in Abbildung 3.8 haben wir bei der Relation zwischen Girokonto und Kunde die Relation Kunde zur Vater-Relation erklärt. Dieses geschieht dort durch die Angabe »dominant role« für den Entitätentyp Kunde bei der Bearbeitung des Beziehungstyps zwischen den beiden Entitätentypen Kunde und Girokonto. 2) Wir verzichten darauf, eine der beiden Relationen zur Vater-Relation zu erklären, und setzen in jede der zwei Relationen einen Fremdschlüssel, der auf die jeweils andere Relation zeigt. Diese Lösung hat den Vorteil, dass ggf. schnellere Datenzugriffe in beiden Richtungen möglich sind, aber den gravierenden Nachteil, dass sichergestellt werden muss, dass bei Änderung eines der beiden Fremdschlüssel der jeweils andere Fremdschlüssel auch mit aktualisiert werden muss. Dieses kann ggf. durch Einführung eines Triggers erfolgen (vgl. Kapitel 7.3.3). 3) Eine weitere Möglichkeit ergibt sich daraus, dass grundsätzlich zu überlegen ist, beide Entitätentypen durch eine gemeinsame Relation zu realisieren. Diese Relation erhält die Attribute von beiden Entitätenmengen (bei Namensgleichheit ist vorher ein Attribut umzubenennen), die für den nicht obligatorischen Entitätentyp in jedem Fall Nullmarken zulassen müssen. Dies ist allerdings bei einer 0..1:0..1-Beziehung in der Regel problematisch, da für Schlüsselattribute keine Nullmarken zulässig sind. Die Beziehung zwischen Girokonto und Kunde könnte dagegen ohne Probleme durch Übernahme der Attribute von Girokonto in Kunde realisiert werden. Motor

Fahrzeug fahrzeug_nr motor_nr typ anzahl_zylinder

integer

integer

varchar(64) integer

motor_nr = motor_nr

motor_nr hubraum anzahl_zylinder letzte_wartung

integer integer integer date

Abbildung 3.13: 1:1-Beziehung, realisiert durch einen Fremdschlüssel Motor

Fahrzeug fahrzeug_nr motor_nr typ anzahl_zylinder

integer

integer

varchar(64) integer

motor_nr = motor_nr fahrzeug_nr = fahrzeug_nr

motor_nr fahrzeug_nr hubraum anzahl_zylinder letzte_wartung

integer integer integer integer date

Abbildung 3.14: 1:1-Beziehung, realisiert durch zwei Fremdschlüssel

Behandlung von abhängigen Entitäten Eine Sonderbehandlung erfahren n:1- oder 1:1-Beziehungen, bei denen die SohnRelation von der Vater-Relation abhängig ist. Da abhängige Entitäten nur im Rah-

106

Sandini Bib

Grundbegriffe des Entity-Relationship-Modells

men der Vater-Entität existieren, erben sie auch den Schlüssel der Vater-Entität. Bei einer 1:1-Beziehung ist damit die abhängige Entität auch schon hinreichend identifiziert. Bei einer 1:n-Beziehung muss dagegen die abhängige Entität einen eigenen Schlüssel haben, der im Rahmen des Vatersatzes die Entität identifiziert. Es ist aber auch möglich, dass eine Entität von mehreren Vater-Entitäten abhängig ist, deren Schlüssel dann gemeinsam den Entitätenschlüssel bilden, wie in unserem Beispiel die Entität Position, die von Bestellung und Artikel abhängig ist. Im Diagramm von Abbildung 3.8 haben wir hier zum einen die Beziehungen zwischen Kunde und Girokonto sowie zwischen Bestellung und Position und zwischen Artikel und Position. In der Umsetzung in ein relationales Modell in Abbildung 3.15 sehen wir, dass für die Relation Girokonto jetzt kunden_nr sowohl Primärschlüssel als auch Fremdschlüssel ist. In der Relation Position wird der Schlüssel zusammengesetzt aus den Fremdschlüsseln bestell_nr und artikel_nr. Bestellung bestell_nr kunden_nr bestelldatum lieferdatum rechnungsbetrag

integer

integer

date date numeric (15,2)

bestell_nr = bestell_nr

Kunde

....

kunden_nr status name straße plz ort letzte_bestellung letzte_werbeaktion zahlung

integer char (1) char (30) char (30) char (5) char (25) date date char (1)

Position artikel_Nr bestell_nr mwst_prozent bestellmenge liefermenge gesamtpreis

char (4)

integer

ecimal (3,1) integer integer numeric (15,2)

artikel_Nr = artikel_Nr

kunden_nr = kunden_nr

Girokonto kunden_nr konto_inhaber blz konto_nr

integer

char (30) numeric (8) char (10)

Artikel artikel_Nr mwst bezeichnung listenpreis bestand mindestbestand verpackung lagerplatz kann_wegfallen bestellvorschlag nachbestellung nachbestellmenge

char (4)

integer

varchar (64) numeric (15,2) integer integer varchar (64) integer smallint timestamp timestamp integer

Abbildung 3.15: Abhängige Entitäten

In Abbildung 3.16 wird eine abhängige Entität benutzt, die innerhalb der VaterEntität einen eigenen Schlüsselteil besitzt. Abbildung 3.17 zeigt das entsprechende relationale Modell.

107

Sandini Bib

3 Datenbankentwurf Mitarbeiter personal_n r na m e straße p lz ort letzte_bestellung letzte_werbeaktion za hlung

PERSONAL_KEY P ERS ONENNAME S TRAS S ENNAME P OS TLEITZAHL ORTS NAME DATUM DATUM ZAHLUNGS ART

fü r Kin d e rge ld

Kind CARDINAL kind_ n r na m e P ERS ONENNAME g e b u rtsta g DATUM

Abbildung 3.16: Abhängige Entität mit eigenem Schlüsselteil Mitarbeiter personal_nr name straße plz ort letzte-bestellung letzte_werbeaktion zahlung

PERSONAL_KEY PERSONENNAME STRASSENNAME POSTLEITZAHL ORTSNAME DATUM DATUM ZAHLUNGSART

personal_nr = personal_nr

Kind personal_nr kind_nr name geburtstag

PERSONAL_KEY CARDINAL PERSONENNAME DATUM



Abbildung 3.17: Relationales Datenmodell für Abb. 3.16

Behandlung von n:m-Beziehungen Während – wie wir eben gesehen haben – n:1- und 1:1-Beziehungen sich durch Fremdschlüssel realisieren lassen, ist die Darstellung von m:n-Beziehungen in relationalen Datenbanken nicht unmittelbar möglich. Das hängt unter anderem mit der »ersten Normalform«5 zusammen, die wir im Abschnitt 3.4 über Normalformen besprechen. 5 Wenn wir allerdings die Möglichkeiten der objektrelationalen Datenbanken, die in Kapitel 9 eingeführt werden, nutzen, können wir auf die erste Normalform verzichten. Es gibt dann auch weitere Möglichkeiten, Beziehungstypen zwischen Entitätstypen zu implementieren.

108

Sandini Bib

Grundbegriffe des Entity-Relationship-Modells

Um auf funktionale Beziehungen zu kommen, ersetzen wir die m:n-Beziehung durch die Einführung einer neuen (Entitäten-)Menge und zweier Funktionen. Diese Konstruktion ist immer möglich. Die neue Menge enthält für jedes Paar von Elementen, die in Beziehung stehen, einen Satz (bzw. Tupel im relationalen Modell). Die beiden Funktionen zeigen jeweils auf die entsprechenden Sätze (bzw. Tupel) der in Beziehung stehenden Entitätenmengen. Dieses sei an einem kleinen Beispiel dargestellt (vgl. Abbildung 3.18): Zwischen den Entitätenmengen Mitarbeiter = {Amann, Bemann, Cefrau, Demann, Efrau}

und Sprache = { Dänisch, Englisch, Finnisch, Französisch, Isländisch, Norwegisch, Schwedisch}

bestehe folgende zweistellige Beziehung: Fremdsprachenkenntnis = {[Amann, Englisch], [Amann, Spanisch], [Cefrau, Englisch], [Cefrau, Schwedisch], [Demann, Dänisch], [Efrau, Französisch], [Efrau, Dänisch], [Efrau, Isländisch]}

Mitarbeiter

Fremdsprachenkenntnis

Amann

Englisch

Amann

Spanisch

Cefrau

Englisch

Cefrau

Schwedisch

Demann

Finnisch

Efrau

Französisch

Efrau

Dänisch

Efrau

Isländisch

S pra che

Abbildung 3.18: Darstellung einer zweistelligen Beziehung durch eine Relation

Wir können die zusammengehörenden Paare als Fakten (z.B. »Herr Amann spricht Englisch«, abgekürzt »A/En«) und somit als Entitäten auffassen. Damit wird Fremdsprachenkenntnis zu einer Entitätenmenge. Der Zusammenhang zwischen Mitarbeiter und Sprache wird durch die Projektionen auf die Komponenten der Paare ausgedrückt, d.h., es werden zwei Funktionen f : Fremdsprachenkenntnis g : Fremdsprachenkenntnis

→ Mitarbeiter → Sprache

und

109

Sandini Bib

3 Datenbankentwurf

definiert mit: f([A/En]) = Amann, f([A/Sp] = Amann, ..., f([E/Is]) = Efrau g([A/En]) = Englisch, g([A/Sp] = Spanisch, ..., g([E/Is]) = Isländisch FremdsprachenKenntnis

Mitarbeiter

Sprache

Amann

A/En

Dänisch

Bemann

A/Sp

Englisch

Cefrau

C/En

Finnisch

Demann

C/Se

Französisch

Efrau

D/Fi

Isländisch

E/Fr

Norwegisch

E/Dk

Schwedisch

E/Is

Spanisch

Abbildung 3.19: Darstellung einer zweistelligen Beziehung durch zwei Funktionen

Somit wird die n:m-Beziehung Fremdsprachenkenntnis im relationalen Datenmodell realisiert durch eine Relation Fremdsprachenkenntnis mit zwei Attributen, die zum einen jeweils Fremdschlüssel auf die beteiligten Relationen Mitarbeiter und Sprache sind, zum anderen gemeinsam den Primärschlüssel bilden. Mitarbeiter personal_nr name straße plz ort gehalt

integer

char (30) char (30) char (5) char (25) numeric (15,2)

personal_nr = personal_nr

Framdsprachenkenntnis personal_nr integer sprach_id char (2)

sprach_id = sprach_id

Sprache sprach_id char (2)

Sprache varchar (30)

Abbildung 3.20: Implementierung einer n:m-Beziehung im relationalen Datenmodell

110

Sandini Bib

Elemente der UML

Bei n:1- und 1:1-Beziehungen haben wir unterschieden zwischen 0..1 und 1..1. Dieses ist relevant dafür, ob für den entsprechenden Fremdschlüssel eine Nullmarke zugelassen ist oder nicht. Bei n:m-Beziehungen müssen wir hier nicht unterscheiden, ob es sich um die Kardinalität 0..* oder 1..* handelt.

3.2.14 Übungsaufgaben Aufgabe 3.1 Untersuchen Sie, welche Kardinalitäten in folgenden Beziehungen möglich sind. Geben Sie dafür gegebenenfalls Randbedingungen vor: a) Postleitzahlen ←→ Orte (in Deutschland) b) Steuernummer ←→ Steuerpflichtiger c) Kind ←→ Vater d) Kind ←→ Mutter e) Kind ←→ Elternteil Aufgabe 3.2 Erstellen Sie für die Beziehungen in Aufgabe 3.1 ER-Diagramme. Beachten Sie dabei, dass wir in c), d) und e) in der Aufgabenstellung nicht die Entitätentypen angegeben haben (die auf beiden Seiten jeweils »Person« sind), sondern Rollen. Aufgabe 3.3 Erstellen Sie für die folgenden Angaben jeweils ein Entity-Relationship-Diagramm und bestimmen Sie die Schlüsselattribute. a) Es gibt Personen, Bücher und Verlage. Jedes Buch hat einen oder mehrere Autoren. Jedes Buch kann zu gegebener Zeit von höchstens einem Ausleiher ausgeliehen werden. Ein Ausleiher kann mehrere Bücher leihen. Ein Buch ist von einem Verlag. b) Ein Auto ist von einem Hersteller. Es hat zum Zeitpunkt der Herstellung keinen Halter, danach höchstens einen Halter. Auf einen Halter können mehrere Autos eingetragen sein.

3.3 Elemente der UML Neben den Analyse- und Designmethoden, die auf dem reinen Datenmodell (wie ERM) und auf dem klassischen Programmierparadigma der imperativen Programmierung6 beruhen, haben sich Anfang der 90er-Jahre mehrere objektorientierte 6 Die Programmiersprache besteht in erster Linie aus Anweisungen, die auf der Basis von veränderbaren Variablen arbeiten. Die wichtigsten Beispiele sind FORTRAN, ALGOL, COBOL, PL/I, Pascal, Ada, C, Modula und andere. Daneben gibt es das funktionale Programmierparadigma, das schon sehr früh durch LISP unterstützt worden ist und in neuerer Zeit durch Miranda und andere Sprachen unterstützt wird. Derzeit setzt sich das objektorientierte Programmierparadigma, das z.B. von C++, Smalltalk und Java unterstützt wird, gegen die anderen Programmierparadigmen durch.

111

Sandini Bib

3 Datenbankentwurf

Analyse- und Designmethoden herausgebildet. Hierbei werden Objekte betrachtet, die nicht nur eine Existenz haben (wie Entitäten), sondern auch ein Verhalten. Das Verhalten wird durch Operationen beschrieben, die ein Objekt ausführen kann, wenn es eine entsprechende Nachricht (Auftrag) bekommt. Damit werden auch die Daten und die Algorithmen in einem einheitlichen Schema betrachtet. Ab Mitte der 90er-Jahre wurden verschiedene Analyse- und Designmethoden zu einer einheitlichen Methode zusammengefasst, die 1997 als Unified Modeling Language (UML) bei der Object Management Group (OMG) zur Standardisierung eingereicht und von dieser akzeptiert wurde (vgl. hierzu [Oest98] oder http:// www.oose.de/uml). In der UML gibt es mehrere Diagrammtypen: Anwendungsfalldiagramme, Klassendiagramme, Verhaltensdiagramme und Implementierungsdiagramme. Uns interessieren im Folgenden die Klassendiagramme. Aus folgenden Gründen ist die UML auch für die Zwecke des Entwurfs relationaler Datenbanken interessant: 왘 Die UML hat sich in sehr kurzer Zeit als anerkannter Standard etabliert. 왘 ER-Diagramme können auf relativ einfache Weise in Klassendiagramme über-

führt werden. 왘 Es gibt Konzepte, die nicht im ERM enthalten sind, die aber dennoch eine große

Rolle bei der Entwicklung relationaler Datenbanken spielen, nämlich die Konzepte Vererbung, Aggregation und Komposition. Wir werden daher im Folgenden zum einen diejenigen Konzepte der UML einführen, mit denen wir ER-Diagramme als Klassendiagramme darstellen können. Zum anderen werden wir die Konzepte Vererbung, Aggregation und Komposition einführen und zeigen, wie wir Modelle, die diese Konzepte benutzen, in relationale Datenbankschemata überführen können. Zu Beginn stellen wir die Notation der ERM und der UML gegenüber. Es ist allerdings zu beachten, dass die UML eine mächtigere Semantik hat und daher die entsprechenden Begriffe nicht äquivalent sind, sondern sich in diesem Zusammenhang nur entsprechen. So unterscheidet sich ein Objekt von einer Entität dadurch, dass es neben seiner Existenz auch ein eigenes Verhalten hat. Andererseits kann ein ERM in ein UML-Modell überführt werden – in diesem Fall wird aus einer Entität durch das Hinzufügen von Verhalten ein Objekt. Begriff der ERM

Begriff der UML

Entität

Objekt Exemplar (instance)

Entitätentyp

Klasse

Entitätenmenge

(extent)

Tabelle 3.1: Vergleich von ERM- und UML-Notation

112

Sandini Bib

Elemente der UML

Begriff der ERM

Begriff der UML

Beziehung

Assoziation

Beziehungstyp

Assoziation

Attribut

Attribut

Tabelle 3.1: Vergleich von ERM- und UML-Notation (Forts.)

3.3.1 ER-Diagramme und UML-Klassendiagramme Entitätentypen werden in der UML zu Klassen. Sie werden wie im ERM in einem Kästchen dargestellt. Dieses Kästchen kann – wie in den oben eingeführten ERDiagrammen auch die Attribute der Klasse enthalten. Danach können die Operationen der Klasse eingetragen werden – jeweils durch einen waagerechten Strich getrennt. Es sind weitere Angaben möglich – hier verweisen wir auf die entsprechende Literatur. Es stellt sich hier die Frage, wie es mit der Identifizierbarkeit von Objekten aussieht. Für Entitätenmengen haben wir verlangt, dass es eine Kombination von Attributen gibt, die jede Entität eindeutig identifizieren. In der Objektorientierung ist der Blickpunkt etwas geändert worden. Auch hier benötigen wir ein eindeutiges Identifizierungsmerkmal – allerdings ist dieses Merkmal fest mit dem Objekt verbunden und kann nie geändert werden und auch nach dem Löschen eines Objekts darf dessen Schlüssel nicht ein weiteres Mal verwendet werden. Diese Objektidentifizierer sollen darüber hinaus nicht nur innerhalb einer Klasse, sondern innerhalb eines Datenmodells einheitlich sein.7 Sie werden üblicherweise automatisch vergeben und sind nach außen nicht sichtbar. Daneben ist es natürlich nicht verboten, dass es Attributkombinationen gibt, die die Schlüsseleigenschaft haben. Die Eigenschaft eines Attributes oder einer Attributkombination, innerhalb einer Entitätenmenge immer eindeutig zu sein, stellen wir als sog. Zusicherung in geschweiften Klammern mit dem Schlüsselwort »unique« dar. Bei zusammengesetzten Schlüsseln muss diese Zusicherung immer die Form {unique(attr1,attr2,... )} haben. Bei Schlüsseln, die aus einem Attribut bestehen (der häufigere Fall), schreiben wir die Zusicherung {unique} hinter das entsprechende Attribut. Bei der Umsetzung in ein Relationenschema müssen wir dann entweder eine eindeutige Attributkombination als Primärschlüssel auszeichnen oder einen künstlichen Schlüssel einfügen, der beispielsweise ein automatisch hochzuzählender numerischer Wert ist. Beziehungstypen im ERM werden in der UML zu Assoziationen. Wenn eine Assoziation zwei Rollen hat, wird sie durch eine Linie zwischen den beiden beteiligten 7 Dies ist auch schon deshalb sinnvoll, da durch das weiter unten eingeführte Vererbungsprinzip ein Objekt gleichzeitig Element mehrerer Klassen sein kann.

113

Sandini Bib

3 Datenbankentwurf

Klassen bezeichnet. Die Kardinalität der Assoziation drückt ähnlich wie im ERM die Anzahl der Exemplare einer Klasse aus, die an der Beziehung beteiligt sind. Es treten unter anderem folgende Bezeichnungen auf: 1 für »genau 1«, * für »keiner, einer oder mehrere«, 0..1 für keiner oder einer, 1..* für »mindestens einer«. Es sind weitere Kombinationen möglich wie 2 für »genau zwei«, 4,6,10 für »vier, sechs oder zehn«, 12..20 für »zwischen 12 und 20«, 5..* für »mindestens 5« oder 0..5 für »höchstens fünf«. So wird das ER-Diagramm von Abbildung 3.8 zu dem Klassendiagramm in Abbildung 3.21. Kunde

Bestellung bestell_nr bestelldatum lieferdatum rechnungsbetrag

Bestell_key Datum Datum Money

0..*

1..1

kunden_nr 1..1 status Auftraggeber name stra e plz ort letzte_bestellung letzte_werbeaktion zahlung

Kunden_key Kunden_status Personenname Stra enname Postleitzahl Ortsname Datum Datum Zahlungsart

1..* 1..1

Position mwst_prozent bestellmenge liefermenge gesamtpreis

Prozentsatz CARDINAL CARDINAL Money

1..1 f r Bankeinzug

Girokonto

0..*

konto_inhaber Personenname blz Bankleitzahl konto_nr Kontonummer 1..1

Artikel artikel_Nr bezeichnung listenpreis bestand mindestbestand verpackung lagerplatz kann_wegfallen bestellvorschlag nachbestellung nachbestellmenge

Artikel_key String Money CARDINAL CARDINAL String Lager Boolean Zeitpunkt Zeitpunkt CARDINAL

MWSt_Satz 0..*

1..1

CARDINAL mwst prozent Prozentsatz beschreibung String

Abbildung 3.21: Klassendiagramm für Versandhandel

3.3.2 Aggregation und Komposition in UML In dem Diagramm in Abbildung 3.21 haben wir die abhängigen Entitäten Position und Girokonto jeweils als Komponenten (dargestellt durch eine ausgefüllte Raute). Daneben gibt es Aggregate (dargestellt durch eine offene Raute).

114

Sandini Bib

Elemente der UML

Durch die Aggregation wird ausgedrückt, dass Objekte einer Klasse in Objekten einer anderen Klasse in gewisser Weise enthalten oder ihnen logisch zugeordnet sind. So ist ein Motor ein Aggregat eines Kraftfahrzeugs; andere Aggregate des Kraftfahrzeugs sind zum Beispiel die Räder, das Getriebe und die Bremsanlage. In unserem Beispiel ist die Bestellposition als Aggregat dem Artikel untergeordnet. Ein Aggregat kann auch gleichzeitig »mehrere Eltern« haben. (vgl. [Balz00]) Kfz

Gebäude

Motor

Raum

Abbildung 3.22: Aggregation und Komposition

Die Komposition ist ein Spezialfall der Aggregation mit der zusätzlichen Eigenschaft, dass die Komponenten nur im Zusammenhang mit genau einem Vaterobjekt existieren können. Konkrete Beispiele für die Komposition sind Gebäude mit ihren Teilen wie Zimmern, Dach, Eingängen, Fensterlöchern, Kabelschächten. Ein abstraktes Beispiel sind Bestellungen mit ihren Bestellpositionen. Ob es sich im konkreten Fall um eine Komposition oder um eine Aggregation handelt, hängt also von der Frage ab, ob ein Teilobjekt unabhängig von dem Vaterobjekt existieren kann. Betrachten wir zum Beispiel einen modular aufgebauten Lehrgang, der aus Kurseinheiten besteht. Wenn Kurseinheiten auch unabhängig von dem Lehrgang bestehen können, handelt es sich um eine Aggregation; wenn Kurseinheiten immer genau einem Lehrgang zugeordnet sind, handelt es sich um eine Komposition. Beispiele, die Aggregation und Komposition benutzen, sind in den Abbildungen 3.21 und 3.25 dargestellt. In Abbildung 3.21 stellen wir eine Bestellung als Komposition der Positionen dar. Ebenso kann ein Girokonto als Komponente des Kunden aufgefasst werden (ist dem Kunden untergeordnet; wird nur im Zusammenhang mit einem Kunden angelegt; wird gelöscht, wenn der Kunde gelöscht wird). In Abbildung 3.25 stellen wir ein Fahrzeug dar, das verschiedene Aggregate enthält. Ein Objekt in einer Komposition gehört immer genau einem Vaterobjekt an – ein Objekt einer Aggregation kann zu keinem, einem oder mehreren Vaterobjekten gehören. So kann ein Motor in einem Fahrzeug eingebaut sein oder auf Lager liegen (Kardinalität 0..1); eine Kurseinheit kann zu einem Lehrgang gehören oder zu mehreren Lehrgängen (Kardinalität 1..*); ein Mitarbeiter kann an keinem, einem oder mehreren Projekten beteiligt sein (Kardinalität *).

115

Sandini Bib

3 Datenbankentwurf

Die Entsprechungen von Aggregation und Komposition im ER-Modell sind Beziehungstypen – eine Komponente stellt dabei jeweils eine abhängige Entität dar. Somit spielt bei der Komposition die Existenzabhängigkeit eine Rolle bei der Frage des Verhaltens beim Löschen eines Vatersatzes (Löschweitergabe, vgl. Kapitel 2.2.2).

3.3.3 Das Vererbungskonzept Ein wichtiges Konzept aus der Objektorientierung ist das Konzept der Vererbung. Der Begriff stammt aus der Biologie und dort speziell aus der Klassifizierung von Lebewesen. So ist jedes Säugetier ein Wirbeltier und »erbt« alle Eigenschaften, die allen Wirbeltieren gemein sind, z.B. wird die Stabilität des Körpers in erster Linie durch ein im Körper gelegenes System von Knochen oder Knorpeln gewährleistet; es hat einen geschlossenen Blutkreislauf, durch den die Körperzellen mit Nährstoffen und Sauerstoff versorgt werden, es hat einen Kopf mit einem Mund, durch den die Nahrung zugeführt wird, und zwei Linsenaugen. Des Weiteren ist jedes Raubtier ein Säugetier und erbt alle Eigenschaften der Säugetiere wie die Existenz von vier Extremitäten8, der Nachwuchs wird lebend geboren und in den ersten Tagen des Lebens durch Milchdrüsen des Muttertieres versorgt. Jeder Löwe ist ein Raubtier und erbt damit alle Eigenschaften von Raubtieren. Für die Objektorientierung bedeutet das Vererbungsprinzip zum einen, dass es Unterklassen gibt, die weitere Attribute haben. Zum anderen wird das Verhalten der Oberklassen auf die Unterklassen vererbt – es kann aber auch überschrieben werden. Damit ist jedes Objekt einer Unterklasse auch gleichzeitig ein Objekt der entsprechenden Oberklasse (jedes Säugetier ist ein Wirbeltier), es hat aber in der Regel weitere Attribute, die es in der Oberklasse nicht gibt. So gibt es für Säugetiere Attribute wie Länge der Vorderextremitäten oder Volumen der Lunge, die nicht für alle Wirbeltiere sinnvoll sind, z.B. nicht für Fische. Üblicherweise können Klassen Objekte enthalten, die nicht in irgendeiner Unterklasse liegen. Daneben gibt es abstrakte Klassen. Das sind Klassen, die selbst keine eigenständigen Objekte enthalten können, sondern alle ihre Objekte sind Objekte irgendeiner Unterklasse. Dieser Begriff spielt in der Informatik eine größere Rolle als in der Modellierung der realen Welt. Die Struktur einer Klasse legt fest, wie die Objekte dieser Klasse repräsentiert werden. Wenn wir zum Beispiel eine Klasse »geometrische Figuren« haben, die Kreise, Rechtecke und Dreiecke enthält, gibt es für jede der Unterklassen Kreis, achsenparalleles Rechteck und Dreieck eine eigenständige Repräsentation9 – aber keine allgemeine Repräsentation für die Klasse der 8 Wale sind auch Säugetiere, haben aber keine vier Extremitäten – dies zeigt die Grenzen dieses Modells in der Anwendung auf die Biologie. In der Objektorientierung ist es dagegen nicht zulässig, dass Strukturen einer Oberklasse in einer Unterklasse verschwinden. Das Verhalten kann dagegen in einer Unterklasse neu definiert werden. 9 Z.B. Mittelpunkt und Radius für einen Kreis, linker unterer Punkt und Ausdehnung in x-Richtung und Ausdehnung in y-Richtung für ein achsenparalleles Rechteck, drei Punkte für ein Dreieck.

116

Sandini Bib

Elemente der UML

geometrischen Figuren. Bei abstrakten Klassen schreiben wir den Namen der Klasse kursiv oder das Wort »abstrakt« in geschweifte Klammern hinter den Namen der Klasse. Wenn die Unterklassen disjunkt sind, können wir in der Oberklasse ein Attribut angeben, das festlegt, zu welcher Oberklasse das Objekt jeweils gehört. Dieses Attribut wird Diskriminator genannt.

Beispiel Versandhandel, mit Vererbung In unserem Datenmodell Versandhandel können wir jetzt die Kunden mit Bankeinzug als Unterklasse der Klasse der Kunden darstellen. Diese haben alle Attribute von Kunden und zusätzlich die Attribute, die ihr Girokonto beschreiben. Um zu zeigen, dass eine Oberklasse üblicherweise mehr als eine Unterklasse hat, haben wir die Kunden, die mit Kreditkarte zahlen, als weitere Unterklasse dargestellt. Die Klasse der Kunden ist nicht abstrakt, da es Kunden gibt, die weder mit Kreditkarte zahlen, noch am Bankeinzugsverfahren teilnehmen. In Abbildung 3.23 stellen wir den Teil des Diagramms, der die Kundendaten enthält, als Klassendiagramm mit Vererbung dar. Kunde + + + + + + + + +

kunden_nr status name straße plz ort letzte_bestellung letzte_werbeaktion zahlung

Kunden_key Kunden_status Personenname Straßenname Postleitzahl Ortsname Datum Datum Zahlungsart

zahlung

Kunde mit Kreditkarte + hersusgeber + karten_nr + gültig_bis

Personenname Bankleitzahl Kontonummer

Kunde mit Girokonto + konto_inhaber Personenname Bankleitzahl + blz Kontonummer + konto_nr

Abbildung 3.23: Klassendiagramm für Versandhandel, Version 2

Für die Umsetzung einer Vererbungshierarchie in ein Relationenschema gibt es vom Grundsatz her drei Möglichkeiten, eine davon in zwei Varianten:

117

Sandini Bib

3 Datenbankentwurf 왘 Jede Klasse wird zu einer eigenständigen Relation

Für jede Klasse wird eine Relation gebildet, die die im Diagramm angegebenen Attribute enthält, d.h. für die Oberklasse die gemeinsamen Attribute und für die Unterklassen die jeweils zusätzlichen Attribute. Wenn es in der Vaterklasse eine eindeutige Attributkombination gibt, wird diese zum Schlüssel der Oberrelation. Dieser Schlüssel wird gleichzeitig zum Schlüssel der Unterrelationen und Fremdschlüssel, um die zusätzlichen Daten der Unterklassen mit den jeweiligen Daten der Oberklasse zu verbinden. Falls die Oberklasse abstrakt ist und nur für die Unterklassen eindeutige Schlüssel definiert sind, werden in einem ersten Schritt die Schlüssel auf einen gemeinsamen Datentyp gebracht, zum Beispiel Zeichenketten mit der größten Schlüssellänge der einzelnen Unterrelationen. Der Primärschlüssel der Oberrelation wird dann aus einer Kombination aus dem Diskriminator und diesem Schlüssel gebildet.10 In diesem Falle kann es sinnvoll (wenn auch redundant) sein, den Diskriminator auch in den Primärschlüssel der Unterrelationen mit einzubeziehen.11 Diese Konstruktion ist sowohl bei abstrakten Oberklassen als auch bei normalen Oberklassen möglich. Einziger Nachteil: Die Daten, die zu einem Objekt gehören, sind jeweils auf zwei Relationen verteilt und müssen immer zur Laufzeit miteinander verknüpft werden. 왘 Jede nicht abstrakte Klasse wird zu einer Relation, disjunkte Variante

Hier werden die Attribute der Oberklasse in die Unterklassen hineingezogen. Somit wird für jede Klasse, die eigene Objekte hat, eine Relation eingeführt, die die gesamten Daten der Objekte enthält. Die Oberklasse enthält dann nur die Objekte, die in keiner der Unterklassen enthalten sind. Schlüssel müssen hier nur für die jeweiligen Relationen eindeutig sein – sie müssen nicht eindeutig im Bereich der Oberklasse sein. Der Vorteil dieser Lösung besteht darin, dass die Daten, die zu einem Objekt gehören, zusammenhängend in einer Relation gespeichert sind. Ein Nachteil ist allerdings gegeben, wenn es Assoziationen zur Oberklasse gibt. Diese müssen nämlich gegebenenfalls für jede der Unterklassen getrennt verwaltet werden. 왘 Jede nicht abstrakte Klasse wird zu einer Relation, redundante Variante

Hier werden die Attribute der Oberklasse in die Unterklassen hineingezogen. Somit wird für jede Klasse, die eigene Objekte hat, eine Relation eingeführt, die die gesamten Daten der Objekte enthält. Die Oberklasse enthält alle Objekte dieser Klasse, also redundanterweise auch die Objekte, die zusätzlich in einer der Unterklassen enthalten sind. 10 Der Schlüssel allein reicht üblicherweise nicht aus, da nicht sichergestellt werden kann, dass nicht in verschiedenen Unterklassen zufälligerweise identische Schlüssel auftreten 11 Der Grund liegt darin, dass in SQL und in anderen Systemen ein Fremdschlüssel von der Struktur her mit dem Primärschlüssel der Vaterrelation identisch sein muss.

118

Sandini Bib

Elemente der UML

Schlüssel müssen hier eindeutig im Bereich der Oberklasse sein. Die Vorteile dieser Lösung sind folgende: Die Daten, die zu einem Objekt gehören, sind zusammenhängend in einer Relation gespeichert. Es gibt keine Probleme mit Beziehungen zur Oberklasse, da alle Objekte, auf die sie sich beziehen, in der Oberklasse enthalten sind. Es ist allerdings eine Redundanz gegeben, die in der Datenbank sicher verwaltet werden muss (z.B. durch Trigger, vgl. Kapitel 7.3.3). 왘 Alle Daten werden in der Oberklasse gespeichert

Hier werden alle Attribute aller Unterklassen in die Oberklasse gezogen – alle Objekte werden in der Oberklasse gespeichert, wobei jeweils die Attribute, die nicht zu der entsprechenden Unterklasse gehören, mit einer Nullmarke zu versehen sind. Diese Lösung ist nur akzeptabel, wenn die Anzahl der eigenständigen Attribute der Unterklassen nicht zu groß ist. Die Umsetzung von Abbildung 3.23 in ein Relationenschema nach dem Grundsatz, dass jede Klasse zu einer eigenständigen Relation wird, ergibt das Schema in Abbildung 3.24. Kunde kunden_nr status name straße plz ort letzte_bestellung letzte_werbeaktion zahlung

Kunden_key Kunden_status Personenname Straßenname Postleitzahl Ortsname Datum Datum Zahlungsart

kunden_nr =kunden_nr

Kunde mit Kreditkarte kunden_nr herausgeber karten_nr gültig_bis

Kunden_key Personenname Bankleitzahl Kontonummer

kunden_nr = kunden_nr

Kunde mit Girokonto kunden_nr konto_inhaber blz konto_nr

Kunden_key

Personenname Bankleitzahl Kontonummer

Abbildung 3.24: Relationenmodell für Klassen mit Vererbung

Beispiel Fahrzeugwartung Im Folgenden wird ein weiteres kleines Fallbeispiel eingeführt. Es geht um die Wartung und Inspektion von Fahrzeugen und Fahrzeugaggregaten in einem Verkehrsbetrieb. Das Modell ist durch folgende Aussagen beschrieben:

119

Sandini Bib

3 Datenbankentwurf 왘 Es gibt Fahrzeuge, Motoren, Bremsanlagen, Getriebe (und weitere Aggregate,

die hier nicht betrachtet werden). 왘 Jedes Fahrzeug kann ein Aggregat von einer Klasse enthalten. Ein Aggregat

kann auch fehlen, dann ist das Fahrzeug in der Werkstatt und nicht betriebsbereit. 왘 Jedes Fahrzeug und jedes Aggregat kann zu einer Variante gehören (z.B. Die-

selmotor, Automatikgetriebe). 왘 Es gibt eine Liste von vorgeschriebenen Wartungen und Inspektionen, die zeit-

lich und/oder nach Laufleistung seit der letzten Wartung/Inspektion festgelegt sind. Diese Wartungen bzw. Inspektionen sind von der Klasse und der Variante abhängig. 왘 Die durchgeführten Wartungen und Inspektionen sind zu speichern. 0..*

1

Gerät {abstract}

Wartung_Inspektion datum laufleistung bemerkung

variante

0..* Gerät.geräteart = W&I-Vorgabe.für_gerät Gerät.variante = W&I-Vorgabe.für_variante

1 Geräteart W&I-Vorgabe

0..1 0..1 ist_eingebaut_in

Fahrzeug {geräteart = 'F' } Betankung(km_stand, liter) Einsatz(fahrer, ...) ...

Aggregat {geräteart 'F'} anfangsdatum laufleistung_bei_einbau kmstand_bei_einbau

bezeichnung für_gerät für_variante max_zeit max_km

{incomplete} Geräteart

Motor {geräteart = 'M'} motor_nr {unique} leistung hubraum anz_Zylinder anord_Zylinder anz_Ventile anz_Kerzen ...

Abbildung 3.25: Fahrzeugwartung

120

Getriebe {geräteart = 'G'} getriebe_nr {unique} anz_gänge ...

Bremse {geräteart = 'B'} brems_nr {unique} bremskraftverstärker ...

Sandini Bib

Elemente der UML

Die Attribute und Operationen sind aus Abbildung 3.19 zu entnehmen. Bei dieser Umsetzung wird die fahrzeug_nr, motor_nr, getriebe_nr und bremsen_nr allgemein als geräte_nr bezeichnet und gemeinsam mit dem Diskriminator geräteart zum Primärschlüssel für alle Geräteklassen. Für die Klassen Wartung_ Inspektion und W&I_Vorgabe wird jeweils ein Schlüssel vom System generiert. Somit ergibt sich folgendes Schema: Gerät(geräteart, geräte_nr, variante) Fahrzeug(geräteart, geräte_nr, typ, erstzulassung, anz_räder, km_stand) FK: geräteart, geräte_nr -> Gerät Aggregat(geräteart, geräte_nr, typ, anfangsdatum, laufleistung_bei_einbau, km_leistung_bei_einbau) FK: geräteart, geräte_nr -> Gerät Motor(geräteart, geräte_nr, leistung, hubraum, anz_zylinder, anz_ventile, anz_kerzen) FK: geräteart, geräte_nr -> Gerät Getriebe(geräteart, geräte_nr, anz_gänge) FK: geräteart, geräte_nr -> Gerät Bremsanlage(geräteart, geräte_nr, bremskraftverstärker) FK: geräteart, geräte_nr -> Gerät W&I_Vorgabe(w&i_vorgabe_nr, bezeichnung, für_gerät, für_variante, max_zeit, max_km) Wartung_Inspektion(wartung_inspektion_nr, w&i_Vorgabe_Nr, geräteart, geräte_nr, datum, laufleistung, bemerkung) FK: geräteart, geräte_nr -> Gerät FK: W&I_Vorgabe_Nr -> W&I_Vorgabe

3.3.4 Übungsaufgaben Aufgabe 3.4 In einer Bibliothek gibt es »Buchtitel« und »Buchexemplare«. Für einen Buchtitel können mehrere Exemplare vorhanden sein, jedoch immer mindestens eins. Ausleiher leihen Buchexemplare. Ausleiher können Buchtitel vormerken lassen. Ausleiher und Autoren sind Personen. Personen sind Studenten oder Professoren. Jede Vorlesung wird von einem Professor gehalten. Ein Professor hält mehrere Vorlesungen. Ein Student besucht mehrere Vorlesungen. Eine Vorlesung wird von mehreren Studenten besucht, aber erst nach Semesterbeginn steht fest, von wem. Ein Professor empfiehlt für eine bestimmte Vorlesung ein Buch. Aufgabe 3.5 (Segeltörn) Eine Yachtagentur will die Törns (Touren) ihrer Segelyachten mit einer Datenbank verwalten. Dabei geht es darum, die Mitfahrer ebenso zu erfassen wie die im Lauf der Tour angelaufenen Häfen. Es gelten folgende Regeln:

121

Sandini Bib

3 Datenbankentwurf 왘 Eine Crew setzt sich aus mehreren Mitfahrern zusammen. Mitfahrer müssen an

keiner Crew teilnehmen, können aber auch an mehreren Crews beteiligt sein. 왘 Eine Crew bezieht sich immer auf eine Tour. Während einer Tour kann aber die

Crew wechseln. 왘 Für jede Tour gibt es einen Kapitän. Ein Kapitän kann natürlich an mehreren

Touren teilnehmen. 왘 Kapitäne und Mitfahrer sind Personen. 왘 Eine Tour wird immer von einer Yacht gefahren. Meistens übersteht eine Yacht

die erste Fahrt. Dann kann sie an weiteren Touren teilnehmen. 왘 Während einer Tour läuft eine Yacht mehrere Häfen an.

Modellieren Sie grafisch die Entitätentypen und Beziehungstypen. Legen Sie die Schlüsselattribute und die wichtigsten anderen Attribute fest.

3.4 Normalformen in relationalen Datenbanken Wie wir in Kapitel 2 dargestellt haben, werden in relationalen Datenbanken alle Daten und auch alle Beziehungen in Relationen gespeichert. Sinnvollerweise werden für einen bestimmten Anwendungsbereich die erforderlichen Daten in mehrere Relationen aufgeteilt. Die Verknüpfung erfolgt über die gespeicherten Werte – so wird also beispielsweise in einer Bestellung die Kundennummer gespeichert, um daraus die Verknüpfung zu dem Kundensatz herzustellen. Es ist aber auch möglich, für jede Bestellung alle Kundendaten in einer Relation mit zu speichern. Dieses Vorgehen hat einige Nachteile, so unter anderem: 왘 Wenn für einen Kunden mehrere Bestellungen vorliegen, so müssen die Daten

mehrfach erfasst und gespeichert werden. Dabei ist darauf zu achten, dass die Kundendaten für denselben Kunden auch in verschiedenen Sätzen übereinstimmen. 왘 Wenn sich irgendwelche Kundendaten (z.B. die Telefonnummer) ändern, muss

diese Änderung in allen Bestelldaten für diesen Kunden vorgenommen werden. 왘 Wenn jeweils die Bestelldaten nur bis zur Abwicklung des Auftrags gespeichert

werden, werden nach Abwicklung des Auftrages auch die Kundendaten gelöscht. Es ist einleuchtend, dass solche Anomalien in einer gut organisierten Datenbank nicht auftreten. Sehr verkürzt gesagt verlangen wir, dass das Unternehmensdatenmodell so organisiert wird, dass keine redundanten Speicherungen auftreten. Doch was heißt »redundante Speicherungen«? Ist es überhaupt möglich, jegliche Redundanz in der Speicherung zu vermeiden?

122

Sandini Bib

Normalformen in relationalen Datenbanken

Eigentlich geht es darum, dass die Einhaltung gewisser Regeln, denen die Daten gehorchen müssen (z.B. dass für einen Kunden, der durch eine Kundennummer repräsentiert wird, jeweils dieselben Kundendaten gespeichert werden und nicht etwa in verschiedenen Aufträgen verschiedene Anschriften), möglichst ohne Zutun des Benutzers sichergestellt wird. Wie wir in Kapitel 1.3 festgestellt haben, gibt es eine Reihe von unterschiedlichen Regeln, denen eine Datenbank genügen muss. Im Grunde genommen können wir die Einhaltung aller dieser Regeln durch geeignete »Trigger« (vgl. Kapitel 7.3.3) gewährleisten. Es gibt jedoch eine Reihe von Geschäftsregeln, deren Einhaltung allein durch die Aufteilung der Daten auf die verschiedenen Relationen und die Festlegung von geeigneten Schlüsseln in diesen Relationen sichergestellt werden können. Die zugrunde liegenden Abhängigkeiten sind so genannte »funktionale Abhängigkeiten«. Diese Fragen sind schon zu Beginn der 70er-Jahre sehr intensiv untersucht worden. Es sind dabei spezielle Normalformen eingeführt worden, denen Relationen genügen sollen. Dazu gehört auch die Methode der Normalisierung, d.h. der systematischen Umwandlung eines Systems von Relationen, die Normalformen verletzen, in ein System von Relationen, die die Normalformen erfüllen.

3.4.1 Funktionale Abhängigkeiten Um den Begriff der Normalformen einzuführen, müssen wir uns vorher mit dem Begriff der funktionalen Abhängigkeit befassen. Der Begriff der Funktion ist Ihnen sicher aus der Schule bekannt. Üblicherweise verbindet man damit in irgend einer Weise eine Rechenvorschrift (wie quadrieren, Wurzel ziehen, Winkelfunktionen sin, cos, tan und Ähnliches). Der Funktionenbegriff ist aber tatsächlich allgemeiner: es kommt nicht darauf an, dass es eine Rechenvorschrift gibt, sondern nur, dass es möglich ist, zu einem Argument auf eindeutige Weise ein Resultat zu bekommen. So ist die Anzahl der Stimmen, die in der letzten Wahl in einem Wahlbezirk für eine bestimmte Partei abgegeben worden ist, als Funktion aufzufassen: Wenn wir den Wahlbezirk und die Partei wissen, können wir die Anzahl der Stimmen feststellen: wir müssen nur in der entsprechenden Datenbank mit den amtlich festgestellten Ergebnissen den entsprechenden Eintrag suchen.12 In diesem Sinne können wir natürlich das Suchen in einer Datenbank als »Rechenvorschrift« auffassen. Zwei weitere Eigenschaften unterscheiden unseren Begriff »funktional« vom üblichen Funktionenbegriff.

12 Eigentlich handelt es sich hierbei – und in den meisten anderen Anwendungen im Datenbankbereich – um eine partielle Funktion, das heißt, nicht für alle möglichen Kombinationen von Argumenten gibt es einen Eintrag – z.B. für eine Partei, die nicht kandidiert hat.

123

Sandini Bib

3 Datenbankentwurf 왘 Die abhängige Größe kann zu unterschiedlichen Zeiten unterschiedliche Werte

haben. So kann die funktionale Beziehung zwischen Mitarbeiter und Gehalt zu unterschiedlichen Zeiten ein unterschiedliches Gehalt liefern. 왘 Es muss nicht zu jedem Argument ein Ergebnis existieren. So liefert die Bezie-

hung zwischen Kfz-Kennzeichen und Fahrzeugtyp nicht zu jedem möglichen Kfz-Kennzeichen einen Fahrzeugtyp, sondern nur zu den ausgegebenen KfzKennzeichen. Nach der allgemeinen Vorrede kommen wir jetzt zur formalen Definition des Begriffs funktionale Abhängigkeit, der – wie oben gesagt – die Voraussetzung für die Untersuchung von Normalformen ist. Wir betrachten jetzt eine Relation, in der a und b Attribute seien. Das Attribut b ist von dem Attribut a funktional abhängig, wenn gilt: Für jeden bestimmten Wert von a gibt es – zu einem gegebenen Zeitpunkt – nur einen Wert von b. Vereinfacht ausgedrückt: »Wenn der Wert von a feststeht, steht auch der Wert von b fest. Auch wenn wir b (noch) nicht kennen, wissen wir, das es nur einen Wert b gibt.« Oder über die logische Umkehrung definiert: Es kann zu keinem Zeitpunkt in der Datenbank zwei Tupel geben, die denselben Wert für das Attribut a haben, aber verschiedene Werte für b. Hierfür schreiben wir 13 {a} → {b}

Wir sagen auch »a determiniert b funktional« oder »a ist eine Determinante für b«.

Beispiele Der Name eines Studierenden hängt funktional von der Matrikelnummer ab. {Matrikel_Nr} → {Name}

Ein Auftrag ist immer (höchstens) einem Kunden zugeordnet.14 {Auftrag_Nr} → {Kunden_Nr}

Funktionale Abhängigkeiten können auch zwischen Mengen von Attributen bestehen. So hängt – in einer entsprechenden Tabelle in einer Prüfungsdatenbank – das Prüfungsergebnis in Form der Note ab von der Matrikelnummer des Studieren13 Wie wir gleich sehen werden, können statt einzelner Attribute auch Mengen von Attributen genommen werden. Wegen einer einheitlichen Sprechweise fassen wir diese Attribute somit als Mengen auf, die jeweils genau ein Attribut enthalten. 14 Falls der wenig erfreuliche Fall auftritt, dass der Kunde vom Auftrag zurücktreten muss, haben wir einen Auftrag, dem kein Kunde zugeordnet ist. In Abhängigkeit vom Geschäftszweig des Unternehmens werden wir den Auftrag stornieren, falls die bisher erbrachten Leistungen für den Auftrag gering sind, oder wir werden für den Auftraggeber eine Nullmarke einsetzen und einen neuen Kunden suchen.

124

Sandini Bib

Normalformen in relationalen Datenbanken

den, der Nummer der Lehrveranstaltung und dem Datum der Prüfung (da es mehrere Prüfungsangebote gibt und die Wiederholung einer Prüfung unter bestimmten Bedingungen zulässig ist). Dieses ergibt folgende funktionale Abhängigkeit {Matrikel_Nr, LV_Nr, Datum} → {Note}

Wenn A und B Mengen von Attributen einer Relation sind, bedeutet A → B: Wenn Tupel t1 und t2 in allen Attributen von A übereinstimmen, dann müssen sie auch in allen Attributen von B übereinstimmen. Weiter oben haben wir von Geschäftsregeln gesprochen, die einen intentionalen Charakter haben. Dieses gilt auch für funktionale Abhängigkeiten, die auf intentionalen Beziehungen beruhen, nicht auf extensionalen. So ist zum Beispiel in einer Studenten-Relation der Studiengang nicht abhängig vom Namen und Vornamen eines Studierenden, auch wenn rein zufällig keine zwei Studierenden mit gleichem Vor- und Nachnamen existieren – es ist ja nicht ausgeschlossen, dass irgendwann zwei Studierende mit gleichem Vor- und Nachnamen auftreten. Einige weitere kleine Beispiele für funktionale Abhängigkeiten sind im Folgenden gegeben: In einer Relation Student (matrikel_nr, name, vorname, studiengang, fachbereich, studienbeginn,...)

sei folgender Sachverhalt gegeben: Zwei Studierende, die denselben Studiengang studieren, gehören damit auch automatisch demselben Fachbereich an. Mit anderen Worten: Der Fachbereich ergibt sich aus dem Studiengang. Dieses ist eine funktionale Abhängigkeit: {Studiengang} → {Fachbereich}

Eine interessante Frage in diesem Zusammenhang ist zum Beispiel, ob es zwischen den Orten und den Postleitzahlen in Deutschland in irgendeiner Weise funktionale Abhängigkeiten gibt. Es können hier zwei Fragen gestellt werden: Gilt {Ort} → {PLZ} ? Gilt {PLZ} → {Ort} ? Um die erste Frage zu beantworten, müssen wir einen Experten befragen: »Kann es einen Ort geben, der mehrere Postleitzahlen hat?« Diese Frage ist mit »Ja« zu beantworten, wie viele Beispiele belegen (z.B. Bremerhaven mit den Postleitzahlen 27568, 27570 und anderen). Um die zweite Frage zu beantworten, müssen wir ebenfalls einen Experten fragen: »Kann es eine Postleitzahl geben, die für mehrere Orte gilt?« Hier muss der Experte gegebenenfalls schon etwas länger suchen – aber auch diese Frage ist mit »Ja« zu beantworten.15

125

Sandini Bib

3 Datenbankentwurf

In beiden Fällen haben wir hier herausgefunden, dass die oben untersuchten funktionalen Abhängigkeiten nicht gelten. Im Folgenden zeigen wir, dass die Möglichkeit, dass auf der linken Seite mehrere Attribute stehen können, auch tatsächlich gebraucht wird. So ist bei einem Sommerhausvermittler in Dänemark (Häuser werden an einen Kunden grundsätzlich für eine oder mehrere Kalenderwochen von Sonnabend bis Sonnabend vermietet) eine funktionale Abhängigkeit {kalenderwoche, mietobjekt} → {kunden_nr}

gegeben. Es gibt aber weder eine funktionale Abhängigkeit {mietobjekt} → {kunden_nr},

(da dasselbe Mietobjekt – zu unterschiedlichen Zeiten – an verschiedene Kunden vermietet werden kann) noch eine funktionale Abhängigkeit {kalenderwoche} → {kunden_nr},

(da in einer Kalenderwoche verschiedene Mietobjekte vermietet werden können). Auf der rechten Seite einer funktionalen Abhängigkeit können auch mehrere Attribute stehen, wie in: {kunden_nr} → {name, vorname, straße, plz, ort}

Allerdings können wir uns hier auf einelementige rechte Seiten beschränken, da eine funktionale Abhängigkeit grundsätzlich äquivalent ist zu einer Menge von funktionalen Abhängigkeiten mit jeweils den einelementigen Untermengen der rechten Seite. Das heißt, dass z.B. die funktionale Abhängigkeit T → {a, b, c}

genau dann gilt, wenn die funktionalen Abhängigkeiten T → {a}, T → {b}, T → {c}

gelten.

3.4.2 Schlüssel Ein Spezialfall der funktionalen Abhängigkeit liegt vor, wenn es für jeden Wert einer Attributkombination jeweils nur ein Tupel in der Relation geben kann. So gibt es in der Studenten-Relation eine funktionale Abhängigkeit: {matrikel_nr} → {name,vorname,studiengang,fachbereich,studienbeginn}

15 Zu belegen etwa durch die Gemeinden Kayhude im Kreis Segeberg und Bargfeld-Stegen im Kreis Stormarn, die beide die Postleitzahl 23863 haben. Es handelt sich hierbei nicht um Ortsteile derselben Gemeinde.

126

Sandini Bib

Normalformen in relationalen Datenbanken

Wir können jetzt den oben in Kapitel 2.2 und 3.2.8 eingeführten Begriff des Schlüssels für Entitätenmengen entsprechend für Relationen über funktionale Abhängigkeiten definieren. Das ist insofern wichtig, da in der Analyse der Normalformen sowohl der Begriff des Schlüssels als auch der Begriff der funktionalen Abhängigkeiten auftritt. Sei X die Menge der Attribute einer Relation R. Eine Menge A ⊆ X von Attributen ist ein Schlüsselkandidat für R, wenn gilt: 1) A → X 2) Keine Untermenge von A erfüllt 1. Eine Relation kann mehrere Schlüssel haben, vgl. das Beispiel in Tabelle 3.2, wo wir neben einer hochschulweiten Matrikelnummer die Studierenden in den einzelnen Jahrgängen mit laufenden Nummern versehen. Hier sind sowohl {matrikel_nr} als auch {Studiengang, Jahrgang, lfd_nr} Schlüssel. Matrikel_Nr

Name

Studiengang

Jahrgang

lfd_Nr

01313-06

Aalbeck

Inf/WI

2001

2

01710-06

Mayer

Inf/WI

2000

2

01517-06

Mayer

Inf/WI

2001

4

01214-06

Peters

Inf/WI

2002

5

01422-06

Zyweck

Inf/WI

2001

5

Tabelle 3.2: Relation mit mehreren Schlüsselkandidaten

Einer der Schlüssel (ggf. der einzig mögliche Schüssel) kann als Primärschlüssel bezeichnet werden. Folgende Sachverhalte können durch funktionale Abhängigkeiten beschrieben werden: 1) Die Relation stellt einen Entitätentyp dar. Die Schlüssel des Entitätentyps bilden den Primärschlüssel S der Relation. Wir haben eine funktionale Abhängigkeit S → X , wobei X die Menge aller Attribute der Relation ist. 2) Die Relation beschreibt einen Beziehungstyp; dann hängen die Attribute der Relation von den Schlüsselattributen der beteiligten Entitäten ab (z.B. hängt menge in der Relation Position von {liefer_nr, artikel_nr} ab). 3) Die Relation beschreibt einen Beziehungstyp zwischen Entitäten, die gewisse gegenseitige Ausschlusskriterien enthalten. Z.B. gibt es in der Relation »Stundenplan« die Bedingung, dass zu einem Zeitpunkt ein Raum nur für eine Veranstaltung reserviert sein darf. Im Fall (1) ist der Schlüssel ein sog. Identifikationsschlüssel, der in anderen Relationen vom Typ (2) die Entität vertreten kann. Ein Attribut in einer BeziehungsRelation, das sich auf das Schlüsselattribut in einer Entitäten-Relation bezieht, ist der in Kapitel 2.2.2 eingeführte Fremdschlüssel.

127

Sandini Bib

3 Datenbankentwurf

Im Fall (3) könnte man die Tatsache, dass z.B. die Kombination der Attribute {wochentag, raum, stundenblock} eindeutig sein muss, als Schlüssel modellieren. Es

empfiehlt sich allerdings nicht, so eine Kombination als Primärschlüssel festzulegen, da dieser bei jeder Raumverlegung seinen Wert verliert. Sinnvoller ist es dann schon, ein (unveränderliches) künstliches Attribut als Primärschlüssel einzuführen. Relationen mit mehreren Schlüsselkandidaten, die jeweils aus mehreren Attributen bestehen, die sich teilweise überlappen, können Probleme aufwerfen, die sich nicht mit den geschilderten Normalformen lösen lassen. Der interessierte Leser sei z.B. an [Date00] und [Date92] verwiesen. Im nächsten Abschnitt zeigen wir eine Relation, in der es mehrere gegenseitige Ausschlussbedingungen gibt. Für solche Relationen können die im Folgenden dargestellten Begriffe sehr viel komplexer sein, als es aufgrund der angegebenen Beispiele erscheint. Andererseits treten solche komplexen Beispiele in der Praxis eher selten auf.

3.4.3 Normalformen, vereinfachte Version Für die Darstellung von unternehmensrelevanten Daten durch Relationen gibt es im Prinzip beliebig komplexe und geschachtelte Möglichkeiten. Ein Datenmodell ist aber nur dann vernünftig handhabbar, wenn es gewissen Kriterien genügt: Es muss den drei im Folgenden angegebenen Normalformen genügen. Es gibt darüber hinaus weitere Normalformen, die aber in diesem Rahmen nicht behandelt werden. Nach einem sauberen Entwurf gemäß dem Entity-Relationship-Modell aus Kapitel 3.2 sind die erzeugten Relationen häufig schon in der dritten Normalform. Da andererseits die Attribute im Entwurf nach dem ER-Modell nicht systematisch untersucht werden, kann es hier noch unerwünschte funktionale Abhängigkeiten geben, die durch die Normalisierung beseitigt werden. Wir erläutern zuerst die drei Normalformen und führen anschließend an einem Beispiel eine Normalisierung vollständig durch. 1) Normalform (1NF) Eine Relation ist in der ersten Normalform, wenn die Werte der Attribute elementar sind. Damit sind als Attribute z.B. Mengen, Folgen und Arrays ausgeschlossen. Einige Beispiele dafür werden am Ende dieses Abschnitts dargestellt. Als elementar gelten aber auch komplexe (d.h. aus Komponenten zusammengesetzte) Datentypen wie Datum oder Uhrzeit, sofern in der Regel jeweils der gesamte Wert relevant ist und nicht die Komponenten wie Tag, Monat, Jahr oder Stunden und Minuten. Über diese Frage entbrennt in der Literatur immer wieder ein heftiger Streit – ist zum Beispiel ein Datum eine elementare Größe oder nicht? Wir legen hier als Kriterium für »elementar« an, dass unter dem Gesichtspunkt des Datenbanksystems die

128

Sandini Bib

Normalformen in relationalen Datenbanken

Größe jeweils als Ganzes zu sehen ist und dass keine einzelnen Komponenten getrennt verarbeitet werden können. Dem widerspricht nicht, dass über spezielle Funktionen auf diese Daten zugegriffen wird, z.B. durch »Gruppiere die Verkäufe nach Monaten«. Nun wird üblicherweise ein Datum als Aggregat von Tag, Monat und Jahr aufgefasst. Dies ist aber nur eine kulturell bedingte Auffassung, die außerdem noch in anderen Kulturkreisen (Arabien, China, Maya, ...) anders festgelegt wird. Und was unterscheidet die obige Anweisung von »Gruppiere die Verkäufe nach Wochen«? Die Kalenderwoche ist sicherlich nicht Bestandteil des Datums, sondern kann durch eine (abgeleitete) Funktion (vgl. Kapitel 7.3.2) beschrieben werden. In der Praxis werden derzeit auch komplexe Objekte wie Bilddaten, Zeichnungen, Tonfolgen in relationalen Datenbanksystemen als elementar gespeichert. Dies wird damit begründet, dass diese Daten vom Datenbank-Verwaltungssystem nur verwaltet werden, Such- und Zugriffskriterien aber in anderen Attributen liegen. Es können daher auch keine Abfragen formuliert werden, die sich auf Inhalte dieser Attribute beziehen: So kann in einer Immobiliendatenbank, in der für jedes Objekt ein Foto enthalten ist, die Frage »Suche alle Objekte, die rote Dachziegel haben« nur beantwortet werden, wenn für die Farbe der Dachziegel ein spezielles Attribut enthalten ist – aus dem Foto kann die Datenbank diese Information (derzeit noch) nicht herausziehen. Erweiterungen von Datenbanken sind derzeit in der Entwicklung. Solche Systeme wird man dann allerdings eher zu den objektorientierten oder objektrelationalen Datenbanken rechnen. Nicht elementar ist ein Attribut einer Bücher-Relation, das für ein Buch mehrere Autoren enthält, wenn hinterher Abfragen der Form »Suche alle Bücher, deren Autoren in Schleswig-Holstein geboren wurden« oder »Zähle für jeden Autor die Anzahl der Werke« erfolgen. Wenn dagegen diese Autoren nur als bibliografische Information, nicht aber als Verarbeitungskriterium benutzt werden, kann dieses Attribut als elementar aufgefasst werden. Ohne so eine dialektische Festlegung des Begriffs »elementar« kämen wir unseres Erachtens nicht weiter, da sonst mit Recht jede Zeichenkette als nicht elementar anzusehen wäre, da sie aus einzelnen Zeichen besteht. Das würde sogar jede Zahl betreffen, die ja aus Ziffern besteht. Die 1NF ist eine Grundforderung für relationale Datenbanken. Relationale Datenbanksysteme können nur Relationen speichern und verarbeiten, die in der ersten Normalform sind. Insbesondere sind dort Mehrfachfelder durch Verknüpfung mehrerer Relationen zu erzeugen. In objektorientierten und in objektrelationalen Datenbanken ist diese Beschränkung aufgehoben – es gibt dort weitere Konstruktoren, die die Modellierung von Mengen, Folgen, Arrays und Strukturen erlauben (vgl. Kapitel 9). Nicht elementar ist des Weiteren ein Array, das in zwölf Komponenten die Verkäufe eines Jahres festhält, oder ein Attribut, das für eine Buslinie die Folge aller Haltepunkte enthält. In diesen Fällen ist auch davon abzuraten, solche komplexen Datenstrukturen über spezielle Attribute in die Relation zu »schmuggeln« (z.B.

129

Sandini Bib

3 Datenbankentwurf

verkauf_01, verkauf_02, ... , verkauf_12 oder in Kenntnis, dass eine Buslinie höchstens 25 Stationen haben kann, stop_01, ..., stop_25). Dieses ist zwar prinzipiell

möglich – Programmierer, die gewohnt sind, solche Sachverhalte über Arrays auszudrücken, halten sicher solche Darstellungen auch für »natürlich«. Dennoch ist zu sagen, dass so eine Darstellung in der konkreten Anwendung zu großen Problemen führt. Eine Abfrage der Form »Welche Buslinien halten am Hauptbahnhof?« wäre zu formulieren als: »Für welche Buslinie ist stop_01 = ‘Hauptbahnhof’ oder stop_02 = ‘Hauptbahnhof’ oder ... stop_25 = ‘Hauptbahnhof ’?« (alle 25 stop_nn ausschreiben!). Die Abfrage »Gibt es eine Umsteigemöglichkeit von Linie 1 zu Linie 2?« führt sogar zu einer Abfrage mit 25 * 25 = 625 Termen: »Linie_1.stop_01 = Linie_2.stop_01 oder Linie_1.stop_01 = Linie_2.stop_02 ... Linie_1.stop_25 = Linie_2.stop_24 oder Linie_1.stop_25 = Linie_2.stop_25«. Eine Normalisierung führt hier etwa zu folgendem Relationenschema: Linie (linien_nr, gesellschaft, ...) Station (linien_nr, stop, km_von_start, ...)

Die Abfrage nach den Umsteigemöglichkeiten von Linie 1 auf Linie 2 ist in der Relationenalgebra (vgl. Kapitel 2.4) durch »Suche alle Paare von Tupeln [t1,t2] von Stationen mit t1.Linien_nr = 1 und t2.Linien_nr = 2 und t1.stop = t2.stop« lösbar – wenn diese Abfrage mindestens ein Ergebnis enthält, gibt es eine Umsteigemöglichkeit.

Hinweis Die weiteren Normalformen setzen grundsätzlich die erste Normalform voraus, ohne dass das im Folgenden jeweils explizit gesagt wird.

Einige Eigenschaften von funktionalen Abhängigkeiten Wie wir oben gesehen haben, müssen wir bei der Festlegung von funktionalen Abhängigkeiten auf der linken Seite grundsätzlich auch Mengen mit mehr als einem Attribut zulassen. Auf der rechten Seite dagegen können wir uns grundsätzlich auf einelementige Mengen beschränken, denn aus der Definition der funktionalen Abhängigkeit folgt unmittelbar folgende Aussage: Eine funktionale Abhängigkeit A → B gilt genau dann, wenn für alle Attribute b ∈ B A → {b} gilt. Im Zusammenhang mit Schlüsseln müssen wir folgende Aussagen beachten (wobei die erste Aussage ein Spezialfall der zweiten Aussage ist): Wenn S ein Schlüssel ist, dann gilt S → B für jede beliebige Attributmenge B Wenn S' eine Obermenge eines Schlüssels ist, dann gilt S' → B für jede beliebige Attributmenge B

130

Sandini Bib

Normalformen in relationalen Datenbanken

Das bedeutet nichts anderes, als dass wir aus der Kenntnis der Schlüsselattribute die übrigen Attribute einer Relation feststellen können. So gilt für studentische Daten {matrikel_nr} → {name, strasse, plz, ort}

Wenn wir die Matrikelnummer kennen, können wir die übrigen Daten aus der Datenbank ableiten. Das gilt natürlich auch dann noch, wenn wir neben der Matrikelnummer zusätzliche Angaben wie z.B. den Studiengang kennen: {matrikel_nr, studiengang} → {name, strasse, plz, ort}

Wir betrachten jetzt eine Relation, die wir auf Normalformen untersuchen wollen, und gehen von folgenden Festlegungen aus: 왘 X ist die Menge aller Attribute. 왘 T und A sind beliebige Mengen von Attributen.

Triviale funktionale Abhängigkeiten Wenn A eine Teilmenge von T ist, dann gilt immer die funktionale Abhängigkeit T → A. Solche funktionalen Abhängigkeiten nennen wir trivial. Für die Untersuchung von Normalformen spielen naturgemäß die trivialen funktionalen Abhängigkeiten keine Rolle. Wir bringen jetzt vereinfachte Definitionen für die zweite und dritte Normalform. Wir können zeigen, dass diese Definitionen mit den später eingeführten exakten Definitionen nur dann nicht übereinstimmen, wenn die Relation mehrere verschiedene Schlüsselkandidaten mit mindestens einem gemeinsamen Attribut hat. Solche Relationen treten aber in der Praxis relativ selten auf, so dass für den Anfang die vereinfachten Definitionen ausreichen. Die exakten Definitionen bringen wir später und zeigen auch, weshalb sie eine weitere Bedingung enthalten müssen. 2) Normalform (2NF) (vereinfacht) Eine Relation ist in der zweiten Normalform, wenn es keine nicht triviale funktionale Abhängigkeit T → A gibt, wobei T eine echte Untermenge eines Schlüssels ist. »T ist eine echte Untermenge eines Schlüssels« heißt, dass der entsprechende Schlüssel mindestens ein Element enthält, das nicht in T enthalten ist. Somit wird die 2NF häufig in der Form »Alle Attribute16 sind vom Schlüssel voll abhängig« ausgedrückt. Die Betonung liegt hier auf »voll«, d.h., es gibt kein Attribut, das schon von einem Teil des Schlüssels funktional abhängt. Eine Verletzung der zweiten Normalform ist nur möglich, wenn der Schlüssel mehr als ein Attribut enthält. 16 Genauer müssten wir sagen: »Alle Attribute, die nicht im Schlüssel liegen, sind vom Schlüssel voll abhängig.«

131

Sandini Bib

3 Datenbankentwurf

3) Normalform (3NF) (vereinfacht) Eine Relation ist in der dritten Normalform, wenn für jede nicht triviale funktionale Abhängigkeit T → A T Obermenge eines Schlüssels ist. Ein Verstoß gegen die funktionale 3NF ist also gegeben, wenn wir eine nicht triviale funktionale Abhängigkeit T → A finden können, wobei T nicht alle Schlüsselattribute enthält. T kann auch Nichtschlüsselattribute enthalten. Darin geht die dritte Normalform über die zweite hinaus. Die Bedingung »T nicht Obermenge eines Schlüssels« schließt auch aus, dass T selbst ein Schlüssel ist. Die Bedingung der 3NF wird häufig in der Form »Es gibt keine transitiven funktionalen Abhängigkeiten« ausgedrückt. Damit ist gemeint, dass sich für den Schlüssel S die funktionale Abhängigkeit S → A nach dem »Transitivitätsgesetz« aus S → T und T → A ableiten lässt. Es ist leicht zu zeigen, dass eine Relation in 3NF auch in 2NF ist, da eine Verletzung der 2NF auch eine Verletzung der 3NF ist: Wegen der Bedingung 2 (Minimalität) für Schlüssel kann eine echte Untermenge eines Schlüssels keine Obermenge eines (anderen) Schlüssels sein.

Weser-Versand – seit 1827 immer für Sie bereit Postfach 12 34 56 # 27568 Bremerhaven # Tel. +49/471/482323 # Fax. +49/ 471/482328 Peter Stein Moordamm 34

RECHNUNG Seite 1

Datum 29.04.2000

23863 Kayhude

Kunden-Nr 101

Rechnungs-Nr 151 Mehrwertsteuer 0=keine, 1=halbe, 2=volle ↓

Menge

Packung

Art-Nr

Artikel

Lager

Einzelpreis

Gesamtpreis

4

0,5 l

G002

Portwein

7

12,45

49,80

2

3

6er

G003

Bier

7

5,20

15,60

2

K002

Hose

2

112,80

338,40

2

Karton

K003

Damenhut

2

65,70

65,70

2

125 g

L002

China-Tee

5

8,35

83,50

1

3 1 10

Netto

Artikel-Anzahl = 21

MWSt

Summe

Ohne MwSt halbe MwSt volle MwSt

83,50

5,84

89,34

469,50

75,12

544,62

553,00

80,96

633,96

Abbildung 3.26: Rechnung als Ausgangsbasis für eine Datenanalyse

132

Sandini Bib

Normalformen in relationalen Datenbanken

3.4.4 Beispiel für eine Normalisierung Der Begriff »Normalform« beinhaltet des Weiteren, dass jede Relation in eine Menge von Relationen zerlegt werden kann, die (in einer noch näher zu spezifizierenden Weise) äquivalent zu der Ursprungsrelation ist. Im Folgenden wird ein Beispiel für die Normalisierung einer Datenbank angegeben. In einem fiktiven Unternehmen der Branche Versandhandel sollen die Lieferscheine und Rechnungen entsprechend Abbildung 3.26 über eine Datenbank verwaltet werden. Wir können hier zwei mögliche Entwurfstechniken benutzen: den Entwurf nach dem ER-Modell sowie die Überführung in die dritte Normalform nach Codd. Dieses Beispiel ist angelehnt an das im Anhang C beschriebene Fallbeispiel, aber es enthält nur einen Ausschnitt und weicht an einigen Stellen von dem dort angegebenen Schema ab. Der Grund liegt darin, dass wir aus einer Analyse der Rechnungen nur einen Teil der Datenstrukturen erhalten, die für die Auftragsverwaltung notwendig sind. Wir gehen davon aus, dass eine Rechnung immer auf einer Bestellung beruht und sprechen daher von Bestelldaten statt von Rechnungsdaten.

Sammlung der Daten, unnormalisiert Eine Zusammenfassung aller Daten ergibt die Tabelle 3.3. Dieses ist keine Relation, da die erste Normalform verletzt ist: Zu jeder Bestellung kann es mehrere Positionen geben. Formal könnten wir das etwa wie folgt beschreiben, wobei die Daten in den geschweiften Klammern jeweils wiederholt werden können. Versand (bestell-Nr, bestell-datum, kunden-nr, kunden-name, kunden-straße, kunden-plz, kunden-ort, {artikel-nr, artikel-packung, artikel-bezeichung, artikel-lager, artikel-preis, artikel-mwst, menge} )

Innerhalb einer Lieferung ist artikel_nr jeweils eindeutig, weshalb das Attribut in der geschweiften Klammer unterstrichen worden ist. Bestell

Kunden

Nr

Nr

Datum

151 02.05.2000 101

Name

Artikel Straße

PLZ

Ort

Nr

Stein, Peter Moordamm 34 23863 Kayhude G002 G003

Menge Packung Bezeichnung Lager Preis 0,5 l

6er Pack Bier

K002

152 02.05.2000 103

Randers, Nis

Am Seeufer 12 23845 Oering

Portwein

Hose

MwSt

7

12,45

2

4

7

5,20

2

3

2 112,80

2

3

K003

Karton

Damenhut

2

65,70

2

1

L002

125 g

China-Tee

5

8,35

1

5

K001

Karton

Schuhe

2

98,50

s2

10

K003

Karton

Damenhut

2

65,70

2

2

K004

Karton

Sonnenbrille

2

76,00

1

12

Tabelle 3.3: Daten nicht in erster Normalform

133

Sandini Bib

3 Datenbankentwurf

Relationen in 1. Normalform Wir überführen diese nicht normalisierte Datensammlung17 in die erste Normalform, indem wir die Wiederholungsgruppen herausziehen. Somit erhalten wir die folgenden zwei Relationen. Die herausgezogene Relation benötigt zur vollen Identifizierbarkeit der Tupel neben den Attributen der Wiederholungsgruppe die Schlüsselattribute {bestell-nr} der Haupttabelle. Diese bilden zusammen mit dem Schlüssel {artikel-nr} der abhängigen Gruppen den Schlüssel {bestell-nr, artikel-nr}. Bestelldaten (bestell-nr, bestell-datum, kunden-nr, kunden-name, kunden-straße, kunden-plz, kunden-ort) Positionsdaten (bestell-nr, artikel-nr, artikel-packung, artikel-bezeichung, artikel-lager, artikel-preis, artikel-mwst, menge) BestellNr

BestellDatum

KundenNr

KundenName

KundenStraße

KundenPLZ

KundenOrt

151

02.05.2000

101

Stein, Peter

Moordamm 34

23863

Kayhude

152

02.05.2000

103

Randers, Nis

Am Seeufer 12

23845

Oering

Tabelle 3.4: Bestelldaten BestellNr

ArtikelNr

ArtikelPackung

ArtikelBezeichnung

ArtikelLager

151

G002

0,5 l

Portwein

7

151

G003

6er Pack

Bier

151

K002

151

K003

151

L002

125 g

China-Tee

5

8,35

1

5

152

K001

Karton

Schuhe

2

98,50

2

10

152

K003

Karton

Damenhut

2

65,70

2

2

152

K004

Karton

Sonnenbrille

2

76,00

1

12

Karton

ArtikelPreis

ArtikelMwSt

Menge

12,45

2

4

7

5,20

2

3

Hose

2

112,80

2

3

Damenhut

2

65,70

2

1

Tabelle 3.5: Positionsdaten

Im Übrigen bekommen wir die Ausgangsdaten von Tabelle 3.3 in einer abgewandelten – aber relationalen – Form als Verbindung (vgl. Tabelle 3.6). Bestelldaten Join[bestell_nr] Positionsdaten

17 Diese Datensammlung wird auch als NF2-Relation bezeichnet (für NF2 = NFNF = Non

First Normal Form). Das NF2-Datenmodell ist ab etwa 1985 als mögliche Erweiterung des relationalen Datenmodells eingehend untersucht worden. Vgl. z.B. [HeSa95; S. 110ff]

134

Sandini Bib

Normalformen in relationalen Datenbanken Bestell

Kunden

Nr

Nr

Datum

Name

Artikel Straße

PLZ

Ort

Nr

Menge Packung Bezeichnung Lager Preis

MwSt

151 02.05.2000 101 Stein, Peter

Moordamm 34 23863 Kayhude G002 0,5 l

Portwein

7

12,45

2

151 02.05.2000 101 Stein, Peter

Moordamm 34 23863 Kayhude G003 6er Pack

Bier

7

5,20

2

4 3

151 02.05.2000 101 Stein, Peter

Moordamm 34 23863 Kayhude K002

Hose

2

112,80

2

3

151 02.05.2000 101 Stein, Peter

Moordamm 34 23863 Kayhude K003 Karton

Damenhut

2

65,70

2

1

151 02.05.2000 101 Stein, Peter

Moordamm 34 23863 Kayhude L002

China-Tee

5

8,35

1

5 10

125 g

152 02.05.2000 103 Randers, Nis Am Seeufer 12

23845 Oering

K001 Karton

Schuhe

2

98,50

2

152 02.05.2000 103 Randers, Nis Am Seeufer 12

23845 Oering

K003 Karton

Damenhut

2

65,70

2

2

152 02.05.2000 103 Randers, Nis Am Seeufer 12

23845 Oering

K004 Karton

Sonnenbrille

2

76,00

1

12

Tabelle 3.6: Ursprungsdaten als Relation

Bestimmung der funktionalen Abhängigkeiten Es werden folgende funktionale Abhängigkeiten gefunden: Bestelldaten: {bestell-nr} → {bestell_datum, kunden-nr} {kunden-nr} → {kunden-name, kunden-straße, kunden-plz, kunden-ort } Positionsdaten: {artikel-nr} → {artikel-packung, artikel-bezeichung, artikel-lager, artikel-preis, artikel-mwst} {bestell-nr, artikel-nr} → { menge }

In der Relation Positionsdaten ist der Schlüssel durch {bestell-nr, artikel-nr} gegeben. Die Artikelattribute hängen aber schon von einer Teilmenge davon ab, nämlich von {artikel-nr}. Somit ist die Relation nicht in der zweiten Normalform. Zur Normalisierung ziehen wir artikel-nr sowie alle davon abhängigen Attribute zu einer eigenen Relation mit dem Schlüssel {artikel-nr} zusammen und entfernen die von {artikel-nr} abhängigen Attribute aus der ursprünglichen Relation. Wir erhalten dann die beiden Relationen Artikel und Position. ArtikelNr

ArtikelPackung

ArtikelBezeichnung

ArtikelLager

G002

0,5 l

Portwein

7

12,45

2

G003

6er Pack

Bier

7

5,20

2

Hose

2

112,80

2

K003

Karton

Damenhut

2

65,70

2

L002

125 g

China-Tee

5

8,35

1

K001

Karton

Schuhe

2

98,50

2

K004

Karton

Sonnenbrille

2

76,00

1

K002

ArtikelPreis

ArtikelMwSt

Tabelle 3.7: Relation »Artikel« in der zweiten Normalform

135

Sandini Bib

3 Datenbankentwurf

Bestell-Nr

Artikel-Nr

Menge

151

G002

4

151

G003

3

151

K002

3

151

K003

1

151

L002

5

152

K001

10

152

K003

2

152

K004

12

Tabelle 3.8: Relation »Position« in der zweiten Normalform

Diese neuen Relationen sind Projektionen der Relation Positionsdaten. Hierbei wird auch deutlich, dass bei der Projektion mehrfach auftretende Tupel auf eines reduziert werden (Vgl. Kapitel 2.4.2). Der zweimal bestellte Artikel »Damenhut« taucht in der Relation Artikel nur einmal auf. Umgekehrt können wir die ursprüngliche Relation als Verbund der Relationen Artikel und Position wiedergewinnen: Artikel = Proj [artikel-nr, artikel-packung, artikel-bezeichnung, artikel-lager, artikel-preis, artikel-mwst] Positionsdaten Position = Proj [bestell-nr, artikel-nr, menge] Positionsdaten Positionsdaten = Artikel Join[artikel-nr] Position

Die Relation Position ist in der zweiten Normalform: Eine Verletzung dieser Normalform könnte nur eine Abhängigkeit des Attributs menge von {bestell-nr} oder von {artikel-nr} sein. Das Erstere ist nicht der Fall, da in derselben Bestellung verschiedene Artikel in unterschiedlicher Menge auftreten können; das Zweitere nicht, da ein Artikel in unterschiedlichen Bestellungen in unterschiedlicher Menge auftreten kann. Diese beiden Relationen sind auch in der dritten Normalform, da wir keine weiteren funktionalen Abhängigkeiten haben. Wir haben eben ganz locker gesagt »da wir keine weiteren funktionalen Abhängigkeiten haben«. Dies ist eine Aussage, aber keine Analyse. Ist nicht vielleicht doch der Mehrwertsteuersatz von der Artikelbezeichnung abhängig? Es spricht sogar einiges dafür, dass Artikel mit derselben Bezeichnung auch denselben Mehrwertsteuersatz haben. Es geht hier aber nicht darum, ob vieles dafür spricht, sondern ob diese funktionale Abhängigkeit aufgrund irgendeiner Geschäftsregel notwendig ist. Wenn es keine Geschäftsregel gibt, die das erforderlich macht, gibt es hier auch keine funktionale Abhängigkeit. Dies erfordert aber – besonders bei größeren Datenmodellen eine recht umfangreiche Analyse.

136

Sandini Bib

Normalformen in relationalen Datenbanken

Wir sehen hier auch eine Schwierigkeit der Normalisierung bzw. der Normalformen: Es ist nicht schwierig, aufgrund gegebener funktionaler Abhängigkeiten festzustellen, ob eine Relation in zweiter oder dritter Normalform ist, es ist aber ggf. schwierig, eine Liste von notwendigen funktionalen Abhängigkeiten aufzustellen. Die Relation Bestelldaten ist nicht in der dritten Normalform, da eine Reihe von Attributen von dem Nichtschlüsselattribut kunden-nr abhängt. Eine Zusammenfassung der von kunden-nr abhängigen Attribute mit kunden-nr als Schlüssel und das Herausziehen dieser Attribute ergibt die im Folgenden zwei dargestellten Relationen. Diese sind in der dritten Normalform, da keine weiteren nicht trivialen funktionalen Abhängigkeiten existieren. KundenNr

KundenName

KundenStraße

KundenPLZ

KundenOrt

101

Stein, Peter

Moordamm 34

23863

Kayhude

103

Randers, Nis

Am Seeufer 12

23845

Oering

Tabelle 3.9: Relation »Kunde« in der dritten Normalform

BestellNr

BestellDatum

KundenNr

151

02.05.2000

101

152

02.05.2000

103

Tabelle 3.10: Relation »Bestellung« in der dritten Normalform

Es gilt hier: Kunde = Proj(kunden-nr, kunden-name, kunden-straße, kunden-plz, kunden-ort] Bestelldaten Bestellung = Proj(bestell-nr, bestell_datum, kunden-nr] Bestelldaten Bestelldaten = Kunde Join[kunden-nr] Bestellung

In den Abbildungen 3.26 bis 3.29 zeigen wir grafisch die Abhängigkeiten und ihre Beseitigung aus dem Modell, indem die Gesamtrelation in mehrere Relationen aufgeteilt wird. Die Verknüpfungen zwischen zwei Relationen erfolgen jeweils über einen Verweis eines Fremdschlüssels auf den Primärschlüssel einer anderen Relation. Nach dem letzten Schritt bleiben nur Abhängigkeiten von den jeweiligen Schlüsseln und Fremdschlüsseln übrig.

137

Sandini Bib

3 Datenbankentwurf

Versand Bestell_nr liefer_datum kunden_nr kunden_name kunden_straße kunden_plz kunden_ort

...

artikel_nr artikel_nr artikel_nr artikel_bezeichnung artikel_bezeichnung artikel_bezeichnung artikel_lager artikel_lager artikel_lager artikel_preis artikel_preis artikel_preis artikel_mwst artikel_mwst artikel_mwst menge menge menge

Abbildung 3.27: Daten in nicht normalisierter Darstellung Bestellung

Position

bestell_nr

bestell_nr

liefer_datum

artikel_nr

kunden_nr

artikel_bezeichnung

kunden_name

artikel_lager

kunden_straße

artikel_preis

kunden_plz

artikel_mwst

kunden_ort

menge

Abbildung 3.28: Relationen in der ersten Normalform Position

Bestellung bestell_nr

bestell_nr

liefer_datum

artikel_nr

kunden_nr

menge

kunden_name kunden_straße kunden_plz kunden_ort

Artikel artikel_nr artikel_bezeichnung artikel_lager artikel_preis artikel_mwst

Abbildung 3.29: Relationen in der zweiten Normalform

138

Sandini Bib

Normalformen in relationalen Datenbanken Position

Bestellung bestell_nr

bestell_nr

liefer_datum

artikel_nr

kunden_nr

menge

Kunde

Artikel

kunden_nr

artikel_nr

kunden_name

artikel_bezeichnung

kunden_straße

artikel_lager

kunden_plz

artikel_preis

kunden_ort

artikel_mwst

Abbildung 3.30: Relationen in der dritte. Normalform

Wie wir in der Darstellung der 3NF sehen, sind alle Abhängigkeiten auf Abhängigkeiten von Schlüsseln bzw. auf Verknüpfungen über Fremdschlüssel reduziert. Für Relationen (in erster Normalform – sonst sind es ja keine Relationen) können wir jetzt formulieren, wann eine Relation R mit vorgegebenen funktionalen Abhängigkeiten äquivalent zu einer Menge von anderen Relationen R1, ..., Rn ist. Dieses ist der Fall, wenn 1) Jede der Relationen Ri ist eine Projektion von R. 2) R ist der natürliche Verbund der Relationen Ri. 3) Für jede zulässige Tupelmenge von R sind die entsprechenden Projektionen zulässige Tupelmengen für Ri. 4) Für alle zulässigen Tupelmengen für Ri ist der natürliche Verbund eine zulässige Tupelmenge für R.

3.4.5 Normalformen, exakte Version Wenn wir das Beispiel der Normalisierung analysieren, stellen wir fest, dass wir bei der Überführung in die zweite und dritte Normalform jeweils die abhängigen Attribute aus der Relation herausziehen, um zusammen mit den Determinanten eine neue Relation aufzubauen. Dieses Herausziehen der abhängigen Attribute ist aber im Sinne der äquivalenten Umformung nur zulässig, wenn dabei kein Schlüssel der Ausgangsrelation zerstört wird. Das heißt, wenn in den abhängigen Attributen kein Schlüsselattribut enthalten ist. Attribute von Schlüsselkandidaten nennen wir auch Primattribute. Ein Attribut a ist ein Primattribut, wenn a Element eines Schlüssels ist. Statt »a ist ein Primattribut« sagen wir auch »a ist prim«.

139

Sandini Bib

3 Datenbankentwurf

2. Normalform (2NF) Eine Relation ist in der zweiten Normalform, wenn es keine nicht triviale funktionale Abhängigkeit T → A gibt, wobei T eine echte Untermenge eines Schlüssels ist und A kein Primattribut enthält.

3. Normalform (3NF) Eine Relation ist in der dritten Normalform, wenn für jede nicht triviale funktionale Abhängigkeit T → A T Obermenge eines Schlüssels ist oder A (mindestens) ein Primattribut enthält. Wenn wir wiederum den Prozess der Normalisierung durchgehen, stellen wir fest, dass jede Relation in eine äquivalente Menge von Relationen in dritter Normalform überführt werden kann, da auf der rechten Seite der funktionalen Abhängigkeit ja keine Primattribute mehr auftreten dürfen.

3.4.6 Übungsaufgaben Aufgabe 3.6 Betrachten Sie die Datensammlung in Tabelle 3.11. a) Welche Normalformen sind verletzt? b) Erzeugen Sie ein äquivalentes System in normalisierter Form. ISBN-Nr

Autoren

Titel

Jahr

Seiten

0-201-14192-2

Date, Ch.

The Relational Model for Database Management: Version 2

1990

538

3-89319-117-8

Finkenzeller, H.

Systematischer Einsatz von SQLOracle

1989

494

Understanding the new SQL

1993

536

Kracke, U. Unterstein, M. 1-55860-245-3

Melton, J. Simon, A.

Tabelle 3.11: Datensammlung »Buchtitel«

Aufgabe 3.7 Betrachten Sie die in Tabelle 3.12 dargestellte Relation. a) Welche Normalformen sind verletzt? b) Erzeugen Sie ein äquivalentes System in normalisierter Form.

140

Sandini Bib

Normalformen in relationalen Datenbanken

Matrikel-Nr

Student

Kurs-Nr

Kurs-Titel

Note

30321

Meyer, J.

706S6

Datenbanksysteme

1,0

30321

Meyer, J.

715S4

Software-Engineering

1,7

30346

Ahrens, H.

715S4

Software-Engineering

3,0

30346

Ahrens, H.

706S6

Datenbanksysteme

2,0

30346

Ahrens, H.

713S5

relationale u. funktionale Programmierung

1,7

30378

Knudsen, K.

706S6

Datenbanksysteme

2,0

Tabelle 3.12: Relation »Kursbelegung«

3.4.7 Die Boyce-Codd-Normalform (BCNF) Wenn wir bei der Formulierung die störende Zusatzbedingung mit dem Primattribut weglassen, erhalten wir die Boyce-Codd-Normalform, die also eine Verschärfung der dritten Normalform darstellt.

Boyce-Codd-Normalform (BCNF) Eine Relation ist in der Boyce-Codd-Normalform, wenn für jede nicht triviale funktionale Abhängigkeit T → A T Obermenge eines Schlüssels ist. Die BCNF ist eigentlich die einfachste Normalform: Es gibt nur funktionale Abhängigkeiten, die aufgrund der Schlüsseleigenschaften zu gelten haben. Es ist aber bei vorgegebener Menge von funktionalen Abhängigkeiten nicht möglich, für jede Relation eine Menge von Projektionen anzugeben, so dass die Relation sich als Verbund dieser Relationen darstellen lässt und genau die Werte für die Projektionen möglich sind, die als Verbund zulässige Werte für die Ausgangsrelation ergeben.

Beispiel für eine Relation in 3NF mit gegenseitigen Ausschlusskriterien So sei folgende Relation in der Hochschule im Rahmen des Vorlesungsplans gegeben (vgl. Tabelle 3.13): Stundenplan (tag, block, dozent, lehrveranstaltung, raum) Tag

Block

Dozent

Lehrveranstaltung

Raum

Montag

1

Otten

Datenbanksysteme

PC-Labor

Montag

2

Otten

Datenbanksysteme

PC-Labor

Montag

1

Hinz

Chemie

Chemie-Hörsaal

Montag

2

Hinz

Chemie

Chemie-Hörsaal

Dienstag

1

Otten

Java

PC-Labor

Tabelle 3.13: Relation »Stundenplan«

141

Sandini Bib

3 Datenbankentwurf

Hierbei sei Block die festgelegte Doppelstunde, in der nach vorgegebenem Raster Lehrveranstaltungen stattfinden können.18 Wir erhalten folgende funktionale Abhängigkeiten: 왘 {tag, block, raum} → {lehrveranstaltung},

Zu einem festen Zeitpunkt kann in einem Raum nur eine Veranstaltung stattfinden. 왘 {tag, block, raum} → {dozent},

Zu einem festen Zeitpunkt kann ein Raum nur für einen Dozenten reserviert sein. 왘 {tag, block, dozent} → {raum},

Zu einem festen Zeitpunkt kann ein Dozent nur in einem Raum eine Veranstaltung durchführen. 왘 {tag, block, dozent} → {lehrveranstaltung},

Zu einem festen Zeitpunkt kann ein Dozent nicht mehr als eine Lehrveranstaltung durchführen. 왘 {lehrveranstaltung} → {raum},

Einer Lehrveranstaltung ist ein fester Raum zugeordnet. Es gibt drei Schlüssel für diese Relation: {tag, block, dozent}, {tag, block, raum} und {tag, block, lehrveranstaltung}. Diese Relation ist in dritter Normalform, da alle Attribute prim sind und es daher keine funktionale Abhängigkeit gibt, an der ein Nichtprimattribut beteiligt ist. Dennoch gibt es einige Probleme beim Einfügen von neuen Tupeln und beim Ändern von Tupeln, da die ganzen gegenseitigen Ausschlusskriterien beachtet werden müssen. Die Relation ist aber nicht in Boyce-Codd-Normalform, da die Determinante der funktionalen Abhängigkeit {lehrveranstaltung} → {raum} keine Obermenge eines Schlüssels ist. Eine Zerlegung nach der Boyce-Codd-Normalform ergibt die beiden Relationen (vgl. Tabellen 3.14 und 3.15): Stundenplan_1 (tag, block, dozent, lehrveranstaltung) LV_Raum (lehrveranstaltung, raum)

18 Der Tag ist hier in ein Raster von 6 Blöcken zu 90 Minuten mit dazwischenliegenden Pausen eingeteilt. Die verschiedenen Blöcke überschneiden sich nicht. Ohne die dogmatische Festlegung auf diese festen Blöcke haben wir dieselben Probleme bei der Verwaltung des Stundenplanes – wir könnten die gegenseitigen Ausschlusskriterien dann aber nicht durch funktionale Abhängigkeiten beschreiben, was wir für dieses Beispiel brauchen.

142

Sandini Bib

Normalformen in relationalen Datenbanken

Tag

Block

Dozent

Lehrveranstaltung

Montag

1

Otten

Datenbanksysteme

Montag

2

Otten

Datenbanksysteme

Montag

1

Hinz

Chemie

Montag

2

Hinz

Chemie

Dienstag

1

Otten

Java

Tabelle 3.14: Relation »Stundenplan_1«

Lehrveranstaltung

Raum

Datenbanksysteme

PC-Labor

Chemie

Chemie-Hörsaal

Java

PC-Labor

Tabelle 3.15: Relation »Stundenplan_2«

Diese Relationen sind jeweils in BCNF. Sie sind Projektionen der Ursprungsrelation und die Ursprungsrelation lässt sich als natürlicher Verbund wiederherstellen. Es geht jedoch u.a. die funktionale Abhängigkeit {tag, block, raum} → {lehrveranstaltung},

verloren, da die Menge dieser Attribute nicht mehr in einer Relation vorhanden ist. In Stundenplan_1 kann somit folgendes Tupel eingefügt werden: Tag

Block

Dozent

Lehrveranstaltung

Montag

1

Kunz

Java

Das ist nach den verbleibenden funktionalen Abhängigkeiten in Stundenplan_1 zulässig. Der natürliche Verbund der beiden Relationen würde jedoch die in Tabelle 3.16 dargestellte unzulässige Belegung von Stundenplan ergeben, in der jetzt das PC-Labor montags im ersten Block doppelt belegt ist. Tag

Block

Dozent

Lehrveranstaltung

Raum

Montag

1

Otten

Datenbanksysteme

PC-Labor

Montag

2

Otten

Datenbanksysteme

PC-Labor

Montag

1

Hinz

Chemie

Chemie-Hörsaal

Montag

2

Hinz

Chemie

Chemie-Hörsaal

Dienstag

1

Otten

Java

PC-Labor

Montag

1

Kunz

Java

PC-Labor

Tabelle 3.16: Relation »Stundenplan« mit inkonsistenten Eintragungen

143

Sandini Bib

3 Datenbankentwurf

Das eigentliche Problem sind nicht die Normalformen an sich, sondern die Arten der funktionalen Abhängigkeiten: 왘 Die wichtigste Klasse der funktionalen Abhängigkeiten ergibt sich daraus, dass

Entitäten mit ihren Attributen durch eine eigenständige Relation implementiert werden. Wir erhalten damit die Abhängigkeiten vom Primärschlüssel (z.B. Relation der Kunden mit der Kundennummer als Primärschlüssel). 왘 Des Weiteren ergeben sich funktionale Abhängigkeiten dadurch, dass n:m-

Beziehungstypen durch Relationen implementiert werden: In diesen Relationen sind Attribute von der Vereinigung der Primärschlüssel der beteiligten Entitätentypen abhängig (z.B. die Relation, die sich aus dem Beziehungstyp »Bestellposition« ergibt). 왘 Daneben kann es funktionale Abhängigkeiten geben, weil in einer Relation die

Attribute eines weiteren Entitätentyps mit enthalten sind (vgl. in Tabelle 3.4 die Bestellrelation, die neben der Kundennummer weitere Kundenattribute enthält). 왘 Abhängigkeiten, die durch gegenseitige Ausschlusskriterien entstehen, können

nicht durch Normalisierung gelöst werden. Die Einhaltung solcher Abhängigkeiten kann dagegen durch Trigger gelöst werden (vgl. Kapitel 7.3.3). Die damit zusammenhängenden Probleme des Datenbankentwurfs lassen sich am besten durch einen sauberen Entwurf im Entity-Relationship-Modell lösen, in dem die Normalisierung in einem zweiten Schritt zur Vollständigkeitskontrolle eingeführt wird.

3.5 Qualitätskriterien für den Datenbankentwurf Immer wieder kommt es in praktischen Projekten vor, dass beim Datenbankentwurf, um Zeit zu sparen, nicht alle Möglichkeiten der Konsistenzkontrolle ausgenutzt werden. Es wird beispielsweise häufig auf die Festlegung von Schlüsseln oder Fremdschlüsseln verzichtet, von den Möglichkeiten der Einschränkungen von Wertebereichen für Attribute wird selten Gebrauch gemacht. Der »Zeitgewinn« erweist sich schnell als nur vordergründig, denn die Kontrolle der Datenkonsistenz wird so in die Anwendungsprogrammierung verlegt oder dem Benutzer überlassen. Wir möchten dafür plädieren, sich dem Datenbankentwurf mit allergrößter Sorgfalt zu widmen, denn: Eine Datenbank »lebt« viele Jahre, länger als jedes Anwendungsprogramm. Sie kann langfristig eine stabile Quelle für Informationen aller Art sein, aber auch Quelle von Ärger, wenn man nur mit »Tricks« an die benötigten Daten kommt oder sich auf sie nicht verlassen kann. Man kann in jedem Fall davon ausgehen, dass ein sauberer Datenbankentwurf den Umgang mit der Datenbank bei Abfragen und sonstigen Datenmanipulationen ebenso wie bei der Anwendungsentwicklung erleichtert.

144

Sandini Bib

Qualitätskriterien für den Datenbankentwurf

Die folgenden Kriterien sollen Anhaltspunkte für einen »guten« Datenbankentwurf geben. Ein wichtiges Qualitätsmerkmal ist bereits die Unterscheidung in verschiedene Datenmodelle, die verschiedene Abstraktionsstufen darstellen. Es ist auf jeder Stufe angebracht, beim Modellieren der Zusammenhänge so genau wie möglich zu verfahren und sich nicht zu früh mit Einschränkungen des DBMS zu arrangieren, die die Umsetzung von Konsistenzbedingungen teilweise gar nicht zulassen. Immerhin könnte die nächste Version solche Mängel beheben oder man entscheidet sich doch noch für ein anderes Produkt. Die Regeln, die wir hier niedergelegt haben, sind als Empfehlungen zu verstehen und nicht alle gleichermaßen zwingend. Ein Datenbankentwurf, der nicht jeder Relation einen Schlüssel zuordnet, ist sicher als schlecht zu bezeichnen. Die Bezeichnung von Attributen kann hingegen aus verschiedenen Gründen von unseren Vorschlägen abweichen. Schließlich mag es in der einen oder anderen Firma noch weitergehende und vielleicht restriktivere Vorschriften für den Datenbankentwurf geben.

3.5.1 Konzeptuelles Modell 1) Das konzeptuelle Modell ist als Entity-Relationship-Modell oder Klassenmodell nach UML dokumentiert. 2) Für alle Beziehungen sind minimale und maximale Kardinalität in beiden Richtungen angegeben. 3) Falls zwischen zwei Entitätentypen bzw. Klassen A und B mehr als eine Beziehung existiert, werden alle Beziehungen zwischen A und B mit Namen qualifiziert. 4) Der Name einer Beziehung ist nicht identisch mit einer der Rollenbezeichnungen. 5) Werden Rollen zu einer Beziehung angegeben, sind diese in beiden Richtungen spezifiziert.

3.5.2 Logisches Datenmodell als Relationenschema 1) Domänen sind als eigenständige Datenbankobjekte dokumentiert. 2) Jedem Attribut ist die Domäne zugeordnet, die seine Wertemenge am genauesten beschreibt. 3) Alle Schlüssel sind dokumentiert (als PRIMARY KEY oder UNIQUE). 4) Alle Fremdschlüssel sind angegeben. Das Verhalten beim Ändern und Löschen von Vatertupeln ist mit Begründung festgelegt. 5) Alle Konsistenzbedingungen, die nicht mit Schlüsseln, Fremdschlüsseln oder Domänen zusammenfallen, sind dokumentiert. 6) Auch Konsistenzbedingungen, die mehr als eine Relation betreffen, sind dokumentiert.

145

Sandini Bib

3 Datenbankentwurf

3.5.3 Physikalisches Schema für die Zieldatenbank 1) Domänen werden als eigenständige Datenbankobjekte eingeführt, falls das DBMS dies unterstützt. 2) Jedem Attribut ist die Domäne zugewiesen, die seine Wertemenge am genauesten beschreibt. Wenn das DBMS keine Domänen unterstützt, werden Wertemengen z.B. durch CHECK-Klauseln oder andere Möglichkeiten der Werteinschränkung definiert. 3) Alle Konsistenzbedingungen (Constraints) werden durch entsprechende Konstrukte der Datendefinitionssprache umgesetzt. 4) Alle Schlüssel werden mithilfe der Datendefinitionssprache realisiert. 5) Alle Fremdschlüssel werden mithilfe der Datendefinitionssprache realisiert. Dabei werden die Verhaltensregeln beim Ändern und Löschen des Vatersatzes berücksichtigt. 6) Für alle Fremdschlüssel wird das Verhalten beim Löschen und Ändern der Vatertupel festgelegt. 7) Alle Konsistenzbedingungen, die nicht mit Schlüsseln oder Domänen zusammenfallen, werden umgesetzt, soweit das DBMS dies erlaubt. 8) Auch Konsistenzbedingungen, die mehr als eine Relation betreffen, werden umgesetzt, soweit das DBMS dies erlaubt. 9) Alle Konsistenzbedingungen (Constraints) haben Namen (falls das DBMS das unterstützt). 10)Nicht umsetzbare Konsistenzbedingungen (z.B. Assertions) werden in den Befehlen zur Datendefinition als Kommentare dokumentiert.

3.5.4 Normalformen 1) Alle Relationen sind in dritter Normalform. Abweichungen davon sind zu begründen. 2) Enthält das Datenmodell unauflösbare Redundanzen, sind diese und ein Verfahren zur möglichst automatisierten Konsistenzsicherung dokumentiert.

3.5.5 Namenskonventionen 1) Namen für Relationen folgen einer einheitlichen Regel. Sie bezeichnen die darin zu speichernde Objektart stets im Singular oder stets im Plural. Wir empfehlen, grundsätzlich den Singular zu verwenden. 2) Der Einsatz von Unterstrichen _ und Sonderzeichen in Bezeichnern folgt einer einheitlichen Regel. Wird beispielsweise ein Attribut als kunden_nr bezeichnet, heißt es ebenfalls artikel_nr und nicht artikelnummer oder artikelnr.

146

Sandini Bib

Weitere Aufgaben bei der Einführung einer Datenbank

3) Bezeichner für Attribute sollten möglichst aussagefähig sein bezüglich der inhaltlichen Bedeutung. 4) Gleichbedeutende Attribute in verschiedenen Relationen haben möglichst denselben Bezeichner. 5) Constraints erhalten aussagefähige Namen. Die Art der Konsistenzbedingung kann durch Präfixe wie PKEY_, FKEY_, CHK oder Ähnliches gekennzeichnet werden.

3.6 Weitere Aufgaben bei der Einführung einer Datenbank 3.6.1 Bestimmung eines Mengengerüsts für die Datenbank Nach dem Entwurf und vor der Implementierung muss festgestellt werden, welches Datenvolumen vorliegt. Dies ist zum einen wichtig, um abzuschätzen, ob ein vorgesehenes Datenbank-Verwaltungssystem überhaupt in der Lage ist, das Datenvolumen zu verwalten. Zum anderen müssen natürlich ein entsprechend große Datenträger zur Verfügung gestellt werden. Als Faustformel können wir von Folgendem ausgehen: Größe_einer_Relation = Anzahl_der_Tupel * (Größe_eines_Tupels + 1,2 * Summe(Länge_der_indizierten_Felder) + Platz_für_zukünftige_Erweiterungen.

Zu den indizierten Feldern sind – auch wenn der Benutzer nicht explizit einen Index anlegen muss – auch die Attribute der Schlüssel und der Fremdschlüssel zu rechnen. Die konkrete Größe hängt allerdings von Implementierungsdetails des konkreten Datenbanksystems ab, z.B. ob die einzelnen Sätze mit einer festen Satzlänge gespeichert werden, ob Leerzeichen komprimiert werden oder ob bei einer Speicherung in aufsteigender Reihenfolge des Primärschlüssels (clustered) Platz für spätere Einfügungen freigelassen wird. Hierbei ist besondere Sorgfalt auf die Berechnung der größeren Tabellen zu legen, während kleinere Tabellen sehr grob geschätzt werden können. Es kommt im Wesentlichen auf die Summe an. Entwurfs-Werkzeuge wie z.B. PowerDesigner nehmen die Berechnung automatisch vor, wenn bei den Entitätentypen oder Tabellen jeweils die Anzahl der erwarteten Einträge angegeben wird.

147

Sandini Bib

3 Datenbankentwurf

3.6.2 Datenübernahme Üblicherweise sind für eine vorgesehene Anwendung schon Daten, gegebenenfalls in einem anderen Format, vorhanden. Diese Daten sind häufig unter anderen Gesichtspunkten geordnet. Hier sind Programme oder Werkzeuge bereitzustellen, die diese Daten übernehmen. Bei der Umstellung eines vorhandenen Verfahrens muss ein Konzept für den Parallelbetrieb entwickelt werden. Es können beide Verfahren mit echten Daten gefahren werden – was aber eine hohe Redundanz bei der Dateneingabe erfordert. Eine andere Möglichkeit besteht darin, ein Batch-Programm zu entwickeln, mit dem die Daten aus dem alten Verfahren in das neue übernommen werden. Dieses ist gegebenenfalls einige Male zu testen, um dann zu einem Zeitpunkt X endgültig das neue Verfahren einführen zu können. Dabei tritt das Problem auf, dass die Daten in der Parallelphase möglicherweise doppelt eingegeben werden müssen. Dabei können zeitweise inkonsistente Zustände zwischen den Daten nach dem alten Verfahren und den Daten nach dem neuen Verfahren auftreten. Spätestens bei der Übernahme des neuen Verfahrens müssen die Daten nach dem neuen Verfahren in einem konsistenten Zustand sein. Außerdem muss ein Konzept für die Schulung des Personals auf das neue Verfahren entwickelt werden. Bei völlig neuer Entwicklung ist gegebenenfalls in der Anfangsphase ein größeres Datenvolumen zu erfassen. Dies kann durch zusätzliches Personal durchgeführt werden oder es ist eine fremde Firma zu beauftragen.

3.6.3 Datenschutzkonzept Der Datenschutz ist ein Thema, das im Rahmen dieser Einführung nur kurz angesprochen werden kann. Es sind hier drei Bereiche zu beachten: 왘 Genügen der Aufbau der Datenbank und die organisatorischen Sicherungs-

maßnahmen den Anforderungen des Bundesdatenschutzgesetzes bzw. des jeweiligen Landesdatenschutzgesetzes? Sind Beteiligungsrechte zu beachten, und ist die Speicherung zu melden? 왘 Ist sichergestellt, dass vertrauliche Firmendaten nicht von Unbefugten eingese-

hen oder kopiert werden können? 왘 Ist sichergestellt, dass die Daten nicht durch Unbefugte manipuliert (verändert

oder zerstört) werden können?

3.6.4 Datensicherungskonzept Hier geht es in erster Linie um Maßnahmen, die sicherstellen sollen, dass bei nicht vorhersehbaren Ereignissen wie Überspannungsschäden, Feuerschäden, Wasser-

148

Sandini Bib

Weitere Aufgaben bei der Einführung einer Datenbank

schäden, Diebstahl, Zerstörung, technischen Defekten oder Systemfehlern die notwendigen Daten wiederhergestellt werden können. Hier spielen zwei Verfahren eine größere Rolle: 왘 Totalsicherungen in bestimmten Abständen auf externe Datenträger (z.B. Strea-

mer-Tape, beschreibbare CD-ROM) oder über DFÜ auf einen entfernten Rechner. 왘 Sicherungen der Datenänderungen nach jeder Änderungstransaktion. Dies

sollte vom Datenbank-Verwaltungssystem unterstützt werden; es ist somit ein Auswahlkriterium für das verwendete Datenbank-Verwaltungssystem. Es muss grundsätzlich möglich sein, nach Zerstörung der aktiven Datenbank (z.B. physikalische Zerstörung der Platte oder Betriebssystemfehler) die Datenbank anhand der Sicherungen, Teilsicherungen und Protokolle wieder in den Zustand vor der Zerstörung zu versetzen.

3.6.5 Verteilung der Daten und Verteilung der Verarbeitung Hier ist zu überlegen, ob die Daten auf mehrere Knoten zu verteilen sind. Wichtige Strukturdaten, deren Änderungshäufigkeit gering ist (z.B. Bankleitzahlen), sollten auf mehreren Knoten redundant gehalten werden. Wichtig ist ein Konzept zur automatischen Aktualisierung von Daten auf mehreren Knoten. Neben der Verteilung der Daten kann auch die Verarbeitung verteilt werden: Es muss ein Konzept für ein Client-Server-System entwickelt werden.

3.6.6 Historienführung In einer Datenbank werden in der Regel Geschäftsprozesse abgebildet, die zu einem bestimmten Punkt abgeschlossen sind. So folgt auf einen Auftrag die Erledigung des Auftrages. Spätestens mit der vollständigen Bezahlung der Rechnung nach der Erledigung des Auftrages sind diese Daten als operative Daten nicht mehr notwendig. Diese Daten können nach der operativen Phase als Grundlage für ein Unternehmensinformationssystem19 dienen. Hier ist zu bedenken, dass die Anforderungen an diese Daten andere sind als an die operativen Daten. Bei den operativen Daten ist die ständige Verfügbarkeit des jeweils aktuellen Stands notwendig. Die Ergebnisse müssen jeweils in sehr kurzer Zeit verfügbar sein (z.B. für Nachfragen bei Aufträgen oder für die Produktionssteuerung). In einem Unternehmensinformationssystem dagegen ist die Antwortzeit nicht so ein begrenzender Faktor – dafür sind hier sehr viel größere und komplexere Informationsmengen zu verarbeiten. 19 In den 70er-Jahren war viel von Management Information Systems die Rede. Da die Versprechungen größer waren als die erbrachten Leistungen, hat man seit langer Zeit nichts mehr davon gehört. Heute werden spezielle Systeme unter dem Begriff Data Warehouse angeboten.

149

Sandini Bib

3 Datenbankentwurf

Für den Datenbankentwurf stellen sich folgende Fragen: 왘 Wie lange bleiben Sätze in der aktuellen Datenbank? 왘 Zu welchen Zeitintervallen und wohin werden diese Sätze entsorgt? (Streamer-

Tape, beschreibbare CD oder Löschung, da Papier-Archiv vorhanden) 왘 Wie werden Historiensätze geführt (d.h. Informationen über vergangene

Zustände, z.B. vergangene Buchungen)? 왘 Welche Daten sind als betriebliche Kennziffern wichtig und wie können diese Daten aggregiert werden?

3.6.7 Auswahl eines Datenbank-Verwaltungssystems Häufig ist in der betrieblichen Umgebung ein Datenbank-Verwaltungssystem schon eingeführt. Es ist dann zu prüfen, ob dieses System die Anforderungen erfüllt. Eine Einführung eines neuen Systems für weitere Anwendungen muss schon sehr gut begründet werden. Bei der Auswahl sind die Aspekte aus den Abschnitten 3.6.1, 3.6.3, 3.6.4 und 3.6.5 zu berücksichtigen. Neben der Auswahl der Datenbankmaschine, d.h. des Datenbank-Verwaltungssystems auf dem Backend ist das Programmentwicklungssystem auszuwählen. Genormte Schnittstellen wie z.B. ODBC von Microsoft oder JDBC erlauben den gleichzeitigen Einsatz unterschiedlicher Frontend-Systeme verschiedener Hersteller unabhängig vom eingesetzten Datenbank-Verwaltungssystem.

150

Sandini Bib

4

Datendefinition in SQL

SQL hat sich als Standardabfragesprache für relationale Datenbanken etabliert. SQL steht ursprünglich für »Structured Query Language«. Die ersten Versuche dazu wurden in den IBM-Labors vorgenommen und daraus ist die Vorläufersprache SEQUEL entstanden. SQL stellt die Schnittstelle zwischen der relationalen Datenbank und dem Anwendungsprogramm dar. Die Sprache ist in erster Linie nicht für Endanwender gedacht, sondern für Systementwickler. Mit SQL lassen sich alle Operationen der Relationenalgebra realisieren, die in Kapitel 3 eingeführt worden sind.

4.1 SQL und SQL-Standard 4.1.1 Ein kleiner Überblick über die Historie von SQL 1974

D. Chamberlain et. al. definieren SEQUEL.

1977

Revision: SEQUEL/2; IBM-Prototyp System R.

1977

Oracle beginnt mit der Implementierung von SEQUEL auf Mainframes.

1979

Oracle liefert ein erstes relationales Datenbanksystem mit SQL aus.

1981

IBM liefert SQL/DS aus.

1983

IBM stellt DB2 vor.

1985

Ingres stellt auf SQL um. Informix stellt auf SQL um.

1986

Sybase wird ausgeliefert.

1986

X/OPEN entscheidet sich für SQL.

1987

Der Standard ISO 9075 Database Language SQL (SQL-86) wird veröffentlicht.

1988

dBASE IV erhält SQL als Abfrage-Sprache. Adabas erhält SQL.

1989

ISO 9075 Database Language SQL with Integrity Enhancement (SQL-89) wird veröffentlicht. SESAM und UDS erhalten SQL.

151

Sandini Bib

4 Datendefinition in SQL

1992

ISO 9075 Database Language SQL (SQL2 oder SQL-92) wird veröffentlicht.

1993

RDA-Standard (Remote Data Access) der Database Access Group (z.B. Microsoft ODBC) wird veröffentlicht.

1996

SQL/PSM (Persistent Stored Modules); Datenbankprozeduren werden normiert (vgl. Kapitel 7.3).

1999

SQL:1999 wird veröffentlicht und löst damit SQL-92 ab.

2003

Eine abermals überarbeitete und teilweise neu strukturierte Version SQL:2003 löst SQL:1999 ab. Zum Zeitpunkt der Drucklegung dieses Buchs befindet sich die neue Norm aber noch im Entwurfsstadium und wird von Pessimisten (oder Realisten) als SQL:200n bezeichnet.

Zwischen dem SQL-Standard und den in kommerziell verfügbaren Datenbanksystemen angebotenen SQL-Implementierungen gibt es Differenzen in beiden Richtungen. Teilweise übersteigt der verfügbare Sprachumfang die Forderungen der Norm, teilweise werden Forderungen der SQL-Norm nicht erfüllt. Es ist aber grundsätzlich zu erkennen, dass die Hersteller sich mehr und mehr um die Einhaltung des SQL-Standards bemühen. Die Standardisierung von SQL ist aus folgenden Gründen wichtig: 왘 Verschiedene RDBMs können nebeneinander im Betrieb existieren. Die Anwen-

dungsentwicklung und Datenbankadministration sollten möglichst wenig voneinander abweichen. 왘 Anwendungen sollen portabel sein, damit man beispielsweise auf ein leis-

tungsfähigeres DBMS umsteigen kann oder damit die Anwendungsentwicklung in einer anderen Umgebung erfolgen kann als der produktive Einsatz. 왘 Herstellerunabhängigkeit ist gefordert. 왘 Die Verfügbarkeit von »Front-Endsystemen«, also Programmen, die hersteller-

unabhängig auf Datenbanken zugreifen können, nimmt zu. 왘 In Client-Server-Umgebungen kommuniziert die Anwendersoftware über

Schnittstellen mit dem DBMS. 왘 Bei der Anwendungsentwicklung mit CASE-Tools erfolgt die Festlegung von

Daten- und Programmstrukturen über weite Strecken unabhängig vom eingesetzten DBMS.

4.1.2 Elemente von SQL Die Sprachelemente von SQL lassen sich in zwei Kategorien unterteilen, die allerdings im Standard nicht festgeschrieben sind:

152

Sandini Bib

SQL und SQL-Standard

DDL (Data Definition Language) Hierzu gehören: 왘 Anweisungen zur Anlage und Verwaltung von Schemata (Zusammenfassung von Tabellen, Datensichten etc.), für die ein bestimmter Benutzer zuständig ist 왘 Anweisungen zur Definition von Domänen 왘 Anweisungen zur Definition von Relationen einschließlich der dazugehörigen Konsistenzbedingungen 왘 Anweisungen zur Anlage von Datensichten (Views) 왘 Die Verwaltung von Benutzern und deren Datenzugriffsrechten

DML (Data Manipulation Language) Die DML enthält Anweisungen zur: 왘 Eingabe von Daten in eine vorhandene Tabelle 왘 Änderung von Daten in einer Tabelle 왘 Löschung von Daten in einer Tabelle 왘 Abfrage von Daten, die auch mehrere Tabellen umfassen können und Anweisungen zur: 왘 Definition und Steuerung von Transaktionen Weiterhin gehören zum Sprachumfang kommerziell verfügbarer relationaler Datenbanksysteme Anweisungen, die die interne Organisation der Datenbanken steuern. Sie sind syntaktisch meist an SQL-Anweisungen angelehnt, unterliegen aber nicht der Norm, da diese sich nicht auf das interne Schema einer Datenbank bezieht. Dazu gehören: 왘 Anweisungen zur Definition von Indexen 왘 Erweiterungen der CREATE TABLE-Anweisung im Hinblick auf Varianten der Ablage auf dem Speichermedium (beispielsweise in »Clustern«)1

SQL ist nicht-prozedural Die gewünschten Daten werden unter SQL durch Prädikate (logische Bedingungen) charakterisiert. Entscheidend für das Auffinden der Daten, die man ansehen oder verändern will, ist ihre Beschreibung über Attributwerte – wie kompliziert diese auch immer sein mag. Ein Beispiel: Zeige von allen Kunden, deren Wohnort Kayhude ist und die zugleich Stammkunden sind, Kunden_nr, Name und Ort an. Der »Weg« zu den Daten in Form von Suchalgorithmen etc. wird bei SQL nicht angegeben. Deshalb ist der Befehl zu obigem Beispiel relativ nahe an der umgangssprachlichen Formulierung: 1 Das beispielsweise bei ORACLE vorhandene Cluster-Konzept sieht die Speicherung von Tupeln verschiedener Tabellen, die häufig miteinander verbunden werden, physikalisch benachbart auf den Plattensektoren vor, um damit die Anzahl der Zugriffe zu reduzieren.

153

Sandini Bib

4 Datendefinition in SQL

SELECTkunden_nr, name, ort FROM kunde WHERE ort = 'Kayhude' AND status = 'S';

Auch höchst komplexe Abfragen können so gestellt und beantwortet werden, z.B.: »Zeige alle Kunden, die zwischen dem 1.3.2003 und dem 31.3.2003 einen Umsatz von mehr als 100 Euro gemacht haben, wobei sie aber keinen Tee gekauft haben dürfen und im Vorjahr auch schon einmal etwas bestellt haben müssen.«2 SQL verarbeitet grundsätzlich Mengen von Tupeln. Eine Abfrage wie die obige hat eine Tabelle mit keiner, einer oder beliebig vielen Zeilen als Ergebnis.3 Dies unterscheidet SQL von imperativen Programmiersprachen, die satzweise arbeiten, d.h. mit einer Anweisung immer nur einen Datensatz zugleich lesen, schreiben, löschen oder vergleichen können. SQL orientiert sich an der Relationenalgebra. Es muss aber deutlich festgehalten werden, dass SQL nicht mit Relationen, sondern mit Tabellen arbeitet. Relationen sind nurmehr ein Spezialfall von Tabellen. Wir haben in Kapitel 3 gezeigt, dass die Relationenalgebra mit wenigen Modifikationen auf Tabellen anwendbar ist.4 Es ist in SQL auch jederzeit möglich, eine Datenabfrage so zu formulieren, dass das Ergebnis eine Relation ist, also keine mehrfach vorkommenden identischen Tupel enthält. Seit 1999 verarbeitet SQL außer Tabellen auch Strukturen, die als objektrelational bezeichnet werden und für die einige Einschränkungen, wie wir sie in Kapitel 3 formuliert haben, nicht gelten. Mehr dazu findet sich in Kapitel 9. Wir beziehen uns im Wesentlichen auf SQL im Sinne des Standards SQL:200n auf dem Stand von August 2002 (Draft Version). Da zum Zeitpunkt der Manuskripterstellung kein DBMS verfügbar ist, das den Standard vollkommen erfüllt, wird gegebenenfalls auf Abweichungen und Besonderheiten bei existierenden DBMS (Sybase, ORACLE, etc.) hingewiesen.

4.2 Schemadefinition Ein SQL-Schema enthält Datenbankobjekte eines einzelnen Benutzers5 innerhalb einer Datenbank. Dazu gehören unter anderem von ihm erzeugte Basistabellen, 2 Wir empfehlen dieses Beispiel hier nicht als Übung. 3 Zur Unterscheidung der Begriffe Tupel, Zeile, Attribut, Spalte, Relation und Tabelle vgl. Abschnitt 2.1. 4 Näheres findet sich in Kapitel 2.6. 5 Unter einem Benutzer verstehen wir einen in der Datenbank namentlich eingetragenen, mit bestimmten Zugriffsrechten ausgestatteten Anwender der Datenbank. Benutzer und Person sind nicht unbedingt identisch. Einer Person können je nach Anwendungszusammenhang verschiedene Benutzernamen zugeordnet sein, beispielsweise einer für die Rolle als Datenbankadministrator und ein anderer für die normale Nutzung der Datenbank. Umgekehrt kann es manchmal organisatorisch sinnvoll sein, einen Benutzernamen (z.B. GAST) einzurichten, unter dem sich verschiedene Personen anmelden können, um allgemein zugängliche Informationen abzufragen (Auskunftsysteme).

154

Sandini Bib

DDL: Datendefinition mit SQL

Datensichten und Integritätsbedingungen.6 Jedes Datenbankobjekt gehört zu genau einem Schema, und jedes Schema gehört genau einem Benutzer. Ein Benutzer kann aber Eigentümer mehrerer Schemata sein. Datenbankobjekte müssen innerhalb eines Schemas eindeutige Namen haben. Das bedeutet, dass in einer Datenbank mehrere Schemata gleichzeitig existieren können und dass gleichnamige Datenbankobjekte in verschiedenen Schemata auftreten können. Die Anweisung zur Anlage eines Schemas lautet in etwas vereinfachter Form: CREATE SCHEMA schema AUTHORIZATION benutzer

Es folgen dann die Definitionsanweisungen zur Erzeugung beliebig vieler Datenbankobjekte innerhalb des neuen Schemas, das sind beispielsweise CREATE DOMAIN, CREATE TABLE, CREATE VIEW in beliebiger Anzahl und Reihenfolge. Diese Anweisungen werden in den folgenden Abschnitten beschrieben. Zur Schemadefinition muss gesagt werden, dass zurzeit die meisten Datenbanksysteme diese Anweisung nicht zur Verfügung stellen. Oft wird gar nicht logisch zwischen Datenbank und Schema unterschieden, und die Anlage einer Datenbank erfolgt nicht über eine SQL-Anweisung, sondern über spezielle Hilfsprogramme, mit denen dann auch gleich noch Details der internen Ebene wie Name und Größe der Plattendatei festgelegt werden.

4.3 DDL: Datendefinition mit SQL Eine zentrale Forderung an eine relationale Datendefinitionssprache ist die Unterstützung von Integritätsbedingungen. SQL unterstützt Schlüssel (Primär- und Kandidatenschlüssel), Fremdschlüssel und so genannte »Geschäftsregeln« – das sind Integritätsregeln, die sich durch logische Bezüge von Daten auf andere Daten ergeben. Für die Zuverlässigkeit der Daten ist beispielsweise die Eineindeutigkeit aller Primär- und Kandidatenschlüsselwerte unverzichtbar – wie sollen wir sonst einen bestimmten Kunden identifizieren? Wir stellen die entsprechenden Sprachelemente in diesem Kapitel vor. Seit 1992 wird eine rudimentäre Form von benutzerdefinierten Datentypen (»Domänen«7) unterstützt. SQL:2003 enthält auch objektorientierte Elemente, die die so genannten »objektrelationalen Datenbanken« charakterisieren sollen. Dazu gehört die Möglichkeit, »echte« benutzerdefinierte Datentypen inklusive Zugriffsmethoden und Vergleichsoperatoren zu erzeugen. Wir kommen auf diese Erweiterungen in Kapitel 9 zurück. Allgemein gilt, dass die Erzeugung neuer Datenbankobjekte mit dem Schlüsselwort CREATE eingeleitet wird. Anweisungen zur Entfernung von Datenobjekten beginnen mit dem Schlüsselwort DROP8. 6 Der Begriff »Datenbankobjekt« darf nicht mit dem Objektbegriff der objektorientierten Datenbankmodelle verwechselt werden (vgl. Kapitel 9). 7 Sie erfüllen aber nur einenTeil des im Abschnitt 2.1.2 eingeführten Domänenkonzeptes. 8 Wird in 4.3.7 kurz behandelt.

155

Sandini Bib

4 Datendefinition in SQL

4.3.1 Datentypen und Domänen Eine Domäne ist vom theoretischen Konzept her die Menge zulässiger Werte, die ein Attribut in einer Relation annehmen kann, verbunden mit einer Menge an Operationen, die innerhalb der Wertemenge oder in Verbindung mit anderen Wertemengen ausgeführt werden kann.9 CREATE DOMAIN gehört zum Datendefinitionsteil von SQL. Die Syntax lautet in der

Grundform:10 CREATE DOMAIN domänenname [AS] datentyp [default] [bedingung]

Die Domänendefinition wird im Datenwörterbuch abgelegt. Jede Domäne muss einen eindeutigen Namen erhalten. Die Bedingung, die den Wertebereich einschränkt, wird durch eine CHECK-Klausel definiert, in der eine Suchbedingung wie in der WHERE-Klausel der SELECT-Anweisung angegeben wird. Dabei kann beispielsweise auch festgelegt werden, ob Nullmarken zulässig sind. Wir sind allerdings der Auffassung, dass diese Festlegung gar nicht der Domäne selbst zukommt, wenn diese eine Wertemenge beschreibt. NULL ist kein Wert und kann daher auch nicht Element einer Wertemenge sein. Nullmarken zuzulassen ist eine Frage der Attributdefinition. Dabei können für Attribute, die sich auf dieselbe Domäne beziehen, auch unterschiedliche Festlegungen getroffen werden. Eine Kundennummer als Primärschlüssel darf keine Nullmarke enthalten, dasselbe ist für Fremdschlüssel aber in bestimmten Fällen durchaus denkbar. Aus einem ähnlichen Grund gehört auch die Default-Klausel eigentlich nicht in die Domänendefinition, sondern in die Spaltendefinition einer Tabelle mit CREATE TABLE. Verschiedene Spalten können derselben Domäne angehören, aber unterschiedliche Vorgabewerte haben. Der SQL-Standard trifft unseres Erachtens den Sinn der Sache hier nicht. Domänen sind hier letztlich nicht mehr als eine Abtrennung von Elementen der Spaltendefinition (CHECK), auf die von mehreren Spalten aus Bezug genommen werden kann.11 Das Problem der erlaubten und verbotenen Operationen ist nicht Bestandteil der CREATE DOMAIN-Anweisung, sondern wird im Standard unter dem Titel »Abstrakte Datentypen« behandelt. Wir erläutern dieses Konzept in Kapitel 9.

9 Vergleiche Abschnitt 2.1.2. 10 Die formale Syntaxbeschreibung ist im Anhang A beschrieben. 11 Melton, Mitglied des Standardisierungskomitees, sagt dazu: »'We were once fans of SQL's domain capabilities. However, they have proved to be less useful than originally hoped, and future editions of the SQL standard may actually delete the facility entirely.« [Melt02 S. 98]

156

Sandini Bib

DDL: Datendefinition mit SQL

Beispiele für Domänendefinitionen: 12 CREATE DOMAIN Kunden_key AS INTEGER CHECK (VALUE > 100); CREATE DOMAIN Kunden_status AS CHAR(1) CHECK (VALUE IN ('W', 'G', 'S')); -'W': Werbemaßname - noch nicht als Kunde aufgetreten -'G': Gelegenheitskunde -'S': Stammkunde CREATE DOMAIN Zahlungsart AS CHAR(1) CHECK (VALUE IN ('R', 'B', 'N', 'V', 'K')) DEFAULT 'N'; -'R': Rechnung -'B': Bankeinzug -'N': Nachnahme -'V': Vorkasse -'K': Kreditkarte

Auf diese Festlegung kann bei der Tabellendefinition zurückgegriffen werden. Für eine Spalte, die ihre Werte aus einer definierten Domäne bezieht, ersetzt die Nennung der Domäne dann die Typangabe. Beispiel: CREATE TABLE kunden_nr status zahlung ... );

kunde ( Kunden_Key NOT NULL Kunden_Status, Zahlungsart,

Sybase Adaptive Server Anywhere realisiert Domänen entsprechend dem Standard. Statt des Schlüsselworts VALUE, das beim Standard für den Zugriff auf den Wert anzuwenden ist, muss man dort einen beliebigen Bezeichner mit vorangestelltem @ einsetzen. Wir verwenden im Folgenden in Anlehnung an den Standard jeweils den Bezeichner @VALUE.

12 Im SQL-Standard ist nicht geregelt, ob SQL-Anweisungen durch ein Satzzeichen abgeschlossen werden müssen. In den verschiedenen interaktiven SQL-Systemen (ISQL) hat sich das Semikolon als abschließendes oder als trennendes Satzzeichen etabliert. Wir werden im Folgenden SQL-Anweisungen jeweils durch ein Semikolon abschließen. Die Zeichen -- bedeuten, dass der Rest der Zeile ein Kommentar ist.

157

Sandini Bib

4 Datendefinition in SQL

-- Domaindefinition in Sybase SQL CREATE DOMAIN Kunden_status AS CHAR(1) CHECK (@VALUE IN ('W', 'G', 'S'));

Die Anweisung CREATE DISTINCT TYPE erreicht, dass Attribute nur dann direkt vergleichbar sind, wenn sie demselben DISTINCT TYPE angehören. Beispielsweise ist ein Vergleich von Kundennummern mit Bestellnummern dann nicht ohne weiteres möglich. Dies macht ja auch in der Regel keinen Sinn und ist meistens das Ergebnis einer Verwechslung von Attribut-Bezeichnern. Die Definition eines DISTINCT TYPE schließt aber wiederum keine Einschränkung eines Wertebereichs ein. Beispiel: CREATE DISTINCT TYPE typ_kunden_nr AS INTEGER

Falls doch ausnahmsweise so ein Vergleich vorgenommen werden soll, ist das durch explizite Konvertierung auf den Ursprungstyp zu formulieren, was mit der CAST-Anweisung geschehen kann. Beispiel: CAST(kunden_nr AS INTEGER)

DB2 implementiert dieses Konzept.

4.3.2 Datentypen in SQL Es gibt die im Folgenden angegebenen Datentypen in SQL. Die Skalierungsgrößen in der Klammer hinter dem Datentyp können in der Regel weggelassen werden. Es werden dann Standardwerte eingesetzt, die bei numerischen Datentypen implementationsabhängig sind, bei Zeichen- und Bitketten jeweils 1, bei TIME 0 (d.h. keine Unterteilung der Sekunde) und bei TIMESTAMP 6 (d.h. Genauigkeit auf Mikrosekunden).

Exakt numerisch INTEGER

üblicherweise vier Byte

SMALLINT

üblicherweise zwei Byte

BIGINT

mindestens so groß wie INTEGER

NUMERIC(p,q)

Dezimalzahlen mit genau p Stellen, davon q hinter dem Dezimalpunkt

DECIMAL(p,q)

Dezimalzahlen mit mindestens p Stellen, davon q hinter dem Dezimalpunkt

158

Sandini Bib

DDL: Datendefinition mit SQL

Angenähert numerisch REAL

Gleitpunktzahlen, einfache Genauigkeit

DOUBLE PRECISION

Gleitpunktzahlen, doppelte Genauigkeit

FLOAT(p)

Gleitpunktzahlen, mindestens p Stellen Genauigkeit

Zeichenketten CHARACTER(n)

Zeichenketten mit genau n Zeichen

CHARACTER VARYING(n)

Zeichenketten mit höchstens n Zeichen

VARCHAR

Synonym zu CHARACTER VARYING

NATIONAL CHARACTER(n)

Zeichenketten mit genau n Zeichen mit nationalen Besonderheiten wie z.B. Zeichensatz, Sortierreihenfolge

NATIONAL CHARACTER VARYING(n)

Zeichenketten mit höchstens n Zeichen mit nationalen Besonderheiten

CHARACTER LARGE OBJECT (n)

Große Textobjekte. Die maximal mögliche Länge ist implementationsabhängig. Zur Spezifikation großer Längen können die Abkürzungen K (Kilo), M (Mega), G (Giga) verwendet werden.

CLOB

Synonym zu CHARACTER LARGE OBJECT

Jede Zeichenkette hat eine bestimmte Länge, wobei diese Länge nicht immer die Anzahl der Bytes sein muss. Bei nationalen Zeichensätzen tritt eine Reihe von Problemen auf, zum Beispiel: 왘 Im Deutschen bilden ä, ö, ü jeweils einen Buchstaben, der aber bei der Sortie-

rung in Namensverzeichnissen jeweils wie ae, oe, ue zu behandeln ist. 왘 Im Spanischen gelten ch und ll (wie auch ñ) jeweils als ein Zeichen, das nach c, l

(bzw. n) einzusortieren ist.

Bitketten Bitketten dienen in erster Linie als Behälter für Objekte, die nicht vom DBMS interpretiert werden (wie Bilddaten, Zeichnungselemente, Font-Daten). Die Typen BIT und BIT VARYING sind aus dem Standard entfernt worden. Es gibt nurmehr einen Typ für große Bitmuster wie beispielsweise Bilder, Töne, Zeichnungen, deren Bedeutung dem DBMS nicht bekannt ist, die es also als »unstrukturierte Daten« behandelt.

159

Sandini Bib

4 Datendefinition in SQL

BINARY LARGE OBJECT (n)

Binäre Daten mit einer maximalen Länge entsprechend n Zeichen

BLOB(n)

Synonym zu BINARY LARGE OBJECT

Datum und Uhrzeit: DATE

Kalenderdaten vom Jahr 1 bis zum Jahr 9999

TIME(p)

Uhrzeit in Stunden, Minuten, Sekunden, wobei die Sekunden noch p Stellen nach dem Komma haben

TIMESTAMP(p)

Datum und Uhrzeit

TIME(p) WITH TIME ZONE

Die Angabe einer Zeitzone ist die Abweichung von der UCT (Zeitzone von London, früher »GMT« genannt). Wegen der Sommerzeit kann sie zwischen -11:59 und +13:00 liegen. MEZ ist UCT +1:00, MESZ = UCT + 2:00.

TIMESTAMP(p) WITH TIME ZONE

Datum und Uhrzeit mit Zeitzone

INTERVAL YEAR

Datumsdifferenz in Jahren

INTERVAL YEAR TO MONTH

Datumsdifferenz in Jahren und Monaten

INTERVAL DAY

Zeitdifferenz in Tagen

INTERVAL DAY TO HOUR

Zeitdifferenz in Tagen und Stunden

INTERVAL DAY TO MINUTE

Zeitdifferenz in Tagen, Stunden, Minuten

INTERVAL MINUTE TO SECONDS (6)

Zeitdifferenz in Minuten und Mikrosekunden

Logischer Datentyp In der Praxis sind boolesche Variablen unverzichtbar. Jedes Prädikat (WHEREKlausel) ist schließlich ein boolescher Wert. In Programmiersprachen werden boolesche Ausdrücke benutzt, um Verzweigungen zu bearbeiten (IF ... THEN ... ELSE). Einige, aber längst nicht alle Datenbanksysteme bieten einen solchen Typ für logische Daten bereits an. Umso erstaunlicher ist es, dass es bis 1999 gedauert hat, bis der Datentyp BOOLEAN in SQL Einzug gehalten hat. BOOLEAN

160

Wahrheitswerte TRUE und FALSE sowie UNKNOWN

Sandini Bib

DDL: Datendefinition mit SQL

Leider fehlt bei den Datenbanksystemen häufig der boolesche Datentyp. In diesem Fall kann man sich notdürftig mit CHAR oder INTEGER behelfen, wobei beispielsweise 0 als FALSE und 1 als TRUE interpretiert wird. Diese Interpretation sollte dann dokumentiert und durchgehend eingehalten werden. Wir können auf diese Weise auch eine Domäne mit dem Befehl CREATE DOMAIN boolean definieren. Die booleschen Operationen sind damit aber in keiner Weise verfügbar.

4.3.3 Operationen mit Datentypen Mit den Datentypen sind bestimmte erlaubte und sinnvolle Operationen und Funktionen verbunden. Wir stellen dies hier nur beispielhaft dar und verzichten auf eine vollständige Aufzählung.

Operationen mit Zahlen Für numerische Datentypen sind dies zunächst einmal die arithmetischen Operatoren: +

Addition

-

Subtraktion

*

Multiplikation

/

Division

Weitere mathematische Operationen wie Potenzierung können mit speziellen Funktionen ermöglicht werden oder sind selbst zu definieren (vgl. Kapitel 7.2). Bei arithmetischen Operationen gelten die üblichen Hierarchieregeln 왘 Punktrechnung geht vor Strichrechnung. 왘 Bei gleicher Hierarchiestufe wird von links nach rechts gerechnet. 왘 Um davon abzuweichen, sind Klammern zu setzen.

Operationen mit Zeichenketten Eine ganze Ansammlung von Operatoren und Funktionen für Zeichenketten steht ebenfalls zur Verfügung. Dazu gehören Funktionen zur Ermittlung der Länge einer Zeichenkette, zur Extraktion bestimmter Teile, zum Entfernen von Leerzeichen am Anfang und Ende, zur Konvertierung in Großbuchstaben etc. Wir kommen auf diese Funktionen in Kapitel 5 zurück. Der Operator für die Zeichenverkettung ist:13 || 13 Zwei senkrechte Striche, im ASCII-Code durch den Wert 124 wiedergegeben.

161

Sandini Bib

4 Datendefinition in SQL

Durch Verkettung von Zeichenketten können zwei oder mehr Spalten virtuell wie eine ausgegeben werden. Beispielsweise können wir Vornamen und Nachnamen (unterstellt, diese wären in verschiedenen Spalten enthalten) für ein Adressetikett so zusammenfügen: vorname ||' '|| nachname

Operationen mit Datums- und Zeitdaten Eine Anzahl von Operationen, die sich mit Datums- und Zeitwerten befassen, ist im Standard definiert. Dazu gehören Differenzen zwischen Datums- und Zeitwerten mit dem Ergebnis eines Intervalls (Tage, Stunden etc.). Auf der anderen Seite können durch Addition oder Subtraktion von Intervallwerten zu Werten vom Typ TIMESTAMP neue Werte vom Typ TIMESTAMP gewonnen werden.

Operationen mit booleschen Werten Für Wahrheitswerte gibt es die üblichen Operatoren AND, OR und NOT. Zum Vergleich von Wahrheitswerten benutzt man nicht das Gleichheitszeichen, sondern den Operator IS. Das Ergebnis des Vergleichs ist wieder ein boolescher Wert, der aber nur die Werte TRUE oder FALSE annehmen kann. Wenn wir bei der Artikeltabelle das Attribut kann_wegfallen mit dem Datentyp BOOLEAN definieren, könnte eine Abfrage beispielsweise die Bedingung enthalten: WHERE kann_wegfallen IS TRUE

oder auch nur: WHERE kann_wegfallen

In beiden Fällen steht hinter WHERE ein Wahrheitswert. Im ersten Fall kann nur TRUE oder FALSE herauskommen, der zweite Ausdruck kann die Werte TRUE, FALSE oder UNKNOWN annehmen, falls für die Spalte kann_wegfallen Nullmarken erlaubt sind.

Operationen zur Typkonvertierung Die CAST-Funktion konvertiert skalare Datentypen, sofern der infrage stehende Wert überhaupt in einen anderen Datentyp konvertiert werden kann. Die allgemeine Syntax ist: CAST (Skalarer Ausdruck AS [datentyp | domäne])

Beispielsweise kann mit CAST ('333' AS INTEGER)

die Zeichenfolge ‘333’ in die Zahl 333 umgewandelt werden. Die Zeichenfolge muss natürlich der Konvention für die Darstellung von Zahlen genügen (vgl. Abschnitt 4.3.4).

162

Sandini Bib

DDL: Datendefinition mit SQL

Diese Operation kann auch für Datums- und Uhrzeitwerte angewandt werden; z.B. ergibt CAST ('1997-04-01' AS DATE)

das Datum DATE'1997-04-01' (also den 1. April 1997).

Vergleiche von Daten Die folgende Tabelle listet die Operatoren für Vergleiche auf. =

gleich

ungleich. In einigen DBMS wird stattdessen der Operator != verwendet.

>

größer als

>=

größer/gleich


10; ARTIKEL_NR MWST BESTAND ========== ==== =========== G001 2 397 G002 2 473 G003 2 1250 K001 2 120 K002 2 62 K003 2 12 K004 1 50 L001 1 356 L002 1 42 L003 1 345 L004 2 2101 L005 2 234

Liste die Artikel mit mwst ungleich 1 oder bestand > 10. Das NOT bezieht sich nur auf die Bedingung, vor der es steht: SELECT artikel_nr, mwstsatz, bestand FROM artikel WHERE NOT mwstsatz = 1 OR bestand > 10; ARTIKEL_NR MWST BESTAND ========== ==== =========== G001 2 397 G002 2 473 G003 2 1250 K001 2 120

197

Sandini Bib

5 Datenmanipulation in SQL

K002 K003 K004 L001 L002 L003 L004 L005

2 2 1 1 1 1 2 2

62 12 50 356 42 345 2101 234

Zeige die Artikel, für die nicht gilt: mwst = 1 oder bestand > 10. Das bedeutet, dass weder mwst = 1 noch bestand > 10 gilt. Das NOT bezieht sich bei der folgenden Anweisung auf beide Bedingungen, da diese durch die Klammer zusammengefasst werden. Die Ergebnismenge ist leer; es gibt keine Tupel, für die die Gesamtbedingung erfüllt ist. SELECT artikel_nr, mwst, bestand FROM ARTIKEL WHERE NOT (mwst = 1 OR bestand > 10); ARTIKEL_NR MWST BESTAND ========== ==== =========== % **Warning: No records selected

Aufgabe 5.10 Bei welchen Positionen sind Artikel mit den Nummern 'G001', 'G002' oder 'G003' geliefert worden? Aufgabe 5.11 Bei welchen dieser Positionen ist die Liefermenge größer als 2? Aufgabe 5.12 Bei welchen Positionen sind keine Artikel mit den oben genannten Nummern geliefert worden? Aufgabe 5.13 Welche Positionen sind noch nicht ausgeliefert worden? Aufgabe 5.14 Welche Kunden sind keine Stammkunden und nicht aus Husum?

5.2.5 SELECT mit BETWEEN, IN, LIKE, SIMILAR Die im Folgenden dargestellten Operatoren erlauben Vergleiche, bei denen Wertebereiche anstelle von Einzelwerten den Maßstab bilden.

198

Sandini Bib

SELECT-Anweisung mit einer Tabelle

BETWEEN Um Wertebereiche mit definierter Unter- und Obergrenze als Selektionskriterium anzuwenden, steht der Operator BETWEEN zur Verfügung. Bedingungen mit BETWEEN werden so formuliert: ausdruck BETWEEN vergleichswert1 AND vergleichswert2

Die Wirkung ist dieselbe wie bei zwei Bedingungen, die mit AND verbunden sind, nämlich ausdruck >= vergleichswert1 AND ausdruck = '2000-04-01' bestelldatum ', kname, ' am ', bdatum, ' ', bmenge, ' Stück'); END LOOP leseschleife; MESSAGE 'FERTIG !'; CLOSE kliste END;

Daneben können die UPDATE- und die DELETE-Anweisung benutzt werden, indem in der WHERE-Klausel CURRENT OF cname angegeben wird. Die entsprechende Datenänderung bezieht sich dann auf das aktuelle Tupel des Cursors. In dem folgenden Beispiel wird jedem Artikel ein neues Attribut num zugewiesen, das den Rang nach der Preishöhe enthält, d.h. der teuerste Artikel bekommt die Nummer 1, der nächste die Nummer 2 etc. Bei Artikeln mit gleichem Preis ist nach der Artikelnummer zu sortieren. -------------------------------------------------------------- PROCEDURE Neu_Num -------------------------------------------------------------- Es sollen alle Artikel nach dem Preis absteigend sortiert -- und in der Reihenfolge nummeriert werden -- bei gleichem Preis ist nach der Artikelnummer zu sortieren -- Dazu ist zuvor eine neue Spalte einzuführen ALTER TABLE artikel ADD num INTEGER; CREATE PROCEDURE neu_num () BEGIN DECLARE lfd_nr INTEGER;

290

Sandini Bib

Strategien zur Konsistenzsicherung

DECLARE preis DECIMAL(15,2); DECLARE art_nr CHAR(4); DECLARE nicht_vorhanden EXCEPTION FOR SQLSTATE VALUE '02000'; DECLARE aliste CURSOR FOR SELECT listenpreis, artikel_nr FROM artikel ORDER BY listenpreis DESC, artikel_nr ASC FOR UPDATE; -- Satzweise Verarbeitung der Abfrage SET lfd_Nr = 0; OPEN aliste; leseschleife: LOOP FETCH NEXT aliste INTO preis, art_nr; IF SQLSTATE=nicht_vorhanden THEN LEAVE leseschleife END IF; SET lfd_nr = lfd_nr + 1; UPDATE artikel SET num = lfd_nr WHERE CURRENT OF aliste; END LOOP leseschleife; MESSAGE STRING ('Es wurden ', lfd_nr, ' Artikel nummeriert.'); CLOSE aliste END;

7.4 Strategien zur Konsistenzsicherung Wir haben in den vergangenen Kapiteln verschiedene Methoden und Gesichtspunkte des Datenbankentwurfs kennen gelernt: vom konzeptionellen Entwurf über den Entwurf eines relationalen Schemas bis hin zur Implementierung unter SQL. In diesem Kapitel haben wir verschiedene Möglichkeiten kennen gelernt, wie wir die Konsistenz einer Datenbank sicherstellen können. Zum Abschluss werden wir in diesem Abschnitt die verschiedenen Techniken der Konsistenzsicherung zusammenfassen (vgl. hierzu auch [Lipe92]). Die Aufgaben der Konsistenzsicherung sind im Wesentlichen dadurch bestimmt, dass 왘 die Datenbank die abzubildende Realität korrekt wiedergibt, 왘 dabei vorgegebene Geschäftsregeln eingehalten werden und 왘 verhindert wird, dass Nutzer Datenbanktransaktionen auslösen, die nicht

zulässig sind.

291

Sandini Bib

7 Konsistenz und Mehrbenutzerbetrieb

Die erste Forderung kann durch ein Datenbanksystem nur in sehr eingeschränktem Maße unterstützt werden. Wenn ein Herr Schulze als »Schultze« gespeichert wird, kann das nicht vom Datenbanksystem bemerkt werden. Wenn dagegen eine Rechnung über 0,00 Euro geschrieben wird oder eine negative Anzahl von Artikeln auf dem Lieferschein erscheint, kann das vom Datenbanksystem erkannt werden (Rückgaben sollten als Rückgaben und nicht als negative Lieferungen behandelt werden). Die beiden weiteren Bedingungen können in heute verfügbaren Datenbanksystemen weitgehend unterstützt werden. Geschäftsregeln sind Festlegungen, wie bestimmte Geschäftsvorgänge zu behandeln sind. Dazu gehören zum Beispiel: 왘 Festlegung von Domänen für bestimmte Attribute 왘 Festlegung von Bedingungen, die für einzelne Tupel zu gelten haben 왘 Festlegung von Eindeutigkeitsbedingungen 왘 Festlegung von existenziellen Abhängigkeiten von Werten in derselben Rela-

tion oder in einer anderen Relation 왘 Festlegung von allgemeinen Beziehungen, in die auch Summen, Durchschnitts-

werte, Maxima oder Minima verschiedener Tabellen eingehen

7.4.1 Statische Geschäftsregeln Die hier angegebenen Geschäftsregeln sind in dem Sinne statisch, als dass sie festlegen, welche Bedingungen die Werte in der Datenbank jeweils erfüllen müssen. Es gibt hierbei keine Abhängigkeiten zu vergangenen Zuständen.

Domänen Zu den Geschäftsregeln zählen wir auch die Festlegung von Domänen für die Attribute. In unserem Beispiel haben wir für den Kundenstatus eine Domäne, die aus genau drei Werten {Stammkunde, Gelegenheitskunde, Werbemaßnahme} besteht. In SQL müssen wir solche Attribute durch einen der in Kapitel 4.3.2 eingeführten Datentypen kodieren13. Die Einschränkung auf die zulässigen Werte ist durch eine CHECK-Klausel sicherzustellen. Als sinnvolle Lösungen kommen u.a. die folgenden Möglichkeiten infrage:

13 In Pascal und anderen höheren Programmiersprachen gibt es dagegen Datentypen, in denen alle möglichen Werte aufgezählt werden, ohne dass wir uns um die Implementierung hierfür kümmern müssen, z.B.: TYPE kundenstatus = (werbemassnahme, gelegenheitskunde, stammkunde)

292

Sandini Bib

Strategien zur Konsistenzsicherung

-- Variante 114 CREATE DOMAIN kunden_status SMALLINT CHECK (VALUE BETWEEN 0 AND 2); -- 0: Werbemaßnahme, -- 1: Gelegenheitskunde -- 2: Stammkunde -- Variante 2 CREATE DOMAIN kunden_status CHAR(1) CHECK (VALUE IN ('W', 'G', 'S'); -- 'W': Werbemaßnahme, -- 'G': Gelegenheitskunde -- 'S': Stammkunde -- Variante 3 CREATE DOMAIN kunden_status CHAR(17) CHECK (VALUE IN ( 'Werbemaßnahme','Gelegenheitskunde','Stammkunde'));

Eine weitere Möglichkeit ist die Benutzung einer zusätzlichen Tabelle, die die Kategorien als Volltext enthält, wie in folgendem Beispiel dargestellt: -- Variante 4, mit Nachschlagetabelle CREATE TABLE kunden_status ( status_key SMALLINT NOT NULL, status_text CHAR(30) NOT NULL, PRIMARY KEY (status_key) ); CREATE TABLE kunde ( kunden_nr kunden_key NOT NULL, ... status SMALLINT NOT NULL, REFERENCES kunden_status ON UPDATE CASCADE ON DELETE RESTRICT, ... );

Diese Variante hat darüber hinaus weitere Vorteile: 왘 Wir kommen an die Volltexte heran, ohne dass wir dafür Funktionen (wie in Kapitel 7.3.2 an Beispielen dargestellt) erstellen müssen. 왘 Wir können ohne Änderung der Datenbankdefinition die möglichen Werte ändern. Das kann jeder, der die entsprechenden Änderungsrechte an der Tabelle kunden_status hat. 14 Die Umsetzung vom Kürzel in eine lesbare Form können wir durch Implementierung einer entsprechenden Funktion erreichen (vgl. Kapitel 7.3.2), die auch in SELECT-Anweisungen benutzt werden kann.

293

Sandini Bib

7 Konsistenz und Mehrbenutzerbetrieb

Häufig wird eine Domäne für natürliche Zahlen benötigt: Wenn es um die Anzahl realer Objekte geht, sind negative Zahlen nicht zulässig. Hier können wir eine entsprechende Domäne in folgender Weise definieren: CREATE DOMAIN cardinal INTEGER CHECK (VALUE >= 0);

Bedingungen für einzelne Tupel Als Beispiel hierfür betrachten wir die Bedingung, dass für eine Bestellung die Anzahl der auszuliefernden Artikel nicht größer sein kann als die Anzahl der bestellten Artikel. Sie kann bei Lieferengpässen gegebenenfalls kleiner sein. 왘 Dieses können wir durch eine CHECK-Klausel sicherstellen:15

CHECK (liefermenge = Einkaufspreis*1.2 OR sonderkondition = 1) );

Ein Spezialfall hiervon sind Festlegungen, dass für Attribute jeweils Werte eingetragen sein müssen, dass sie also keine Nullmarken enthalten dürfen. Sie sind durch die NOT NULL-Klausel anzugeben. Es können jedoch auch komplexere Bedingungen gelten, z.B. dass nur unter bestimmten Zusatzbedingungen ein Wert erforderlich ist. Dies ist dann explizit in einer CHECK-Klausel unter Verwendung des Prädikats IS NULL anzugeben, wie im folgenden Beispiel, wo für die Vertragsart 'Express' eine Telefaxnummer vorhanden sein muss:

15 Beachten Sie, dass die Bedingung der CHECK-Klausel nicht TRUE ergeben muss, sondern auch UNKNOWN zulässig ist (vgl. Kapitel 4.3.5, CHECK-Klausel). In diesem Beispiel ist es also keine Verletzung der CHECK-Klausel, wenn liefermenge eine Nullmarke enthält. Die in der Literatur zum Teil anzutreffende Formulierung CHECK (liefermenge IS NULL OR liefermenge < bestellmenge)

ist also nicht notwendig.

294

Sandini Bib

Strategien zur Konsistenzsicherung

... vertragsart CHAR(10), telefax CHAR(15), ... CHECK (vertragsart 'Express' OR telefax IS NOT NULL),

Eindeutigkeitsbedingungen Eindeutigkeitsbedingungen sind in der Regel Bedingungen an künstlich vergebene Schlüssel wie Kundennummer oder Artikelnummer. Sie sind durch eine PRIMARY KEY-Klausel festzulegen, bei eventuell weiteren Schlüsseln durch eine UNIQUE-Klausel (vgl. Kapitel 4.3.5). Eindeutigkeitsbedingungen können aber auch bei zeitlichen Festlegungen von Ressourcen auftreten, z.B. bei der Vermietung von Sommerhäusern. Falls die zeitlichen Festlegungen jeweils durch eine kleine Anzahl vorgegebener Intervalle beschrieben werden können (z.B. die Wochen von Samstag bis Samstag), kann die Bedingung, dass ein Sommerhaus nicht gleichzeitig an mehrere Kunden vermietet werden darf, durch eine UNIQUE-Bedingung festgelegt werden; vgl. hierzu folgendes Beispiel: CREATE TABLE vermietung ( vertrag CHAR(10) NOT NULL, objekt CHAR(10) NOT NULL REFERENCES haus, mieter CHAR(10) NOT NULL REFERENCES kunde, jahr SMALLINT NOT NULL, woche SMALLINT NOT NULL CHECK (WOCHE BETWEEN 1 AND 53), PRIMARY KEY (vertrag, jahr, woche), UNIQUE (objekt, jahr, woche) );

In diesem Beispiel ist eine Vermietung für drei Wochen durch drei Einträge zu beschreiben. Wenn wir dagegen die Mietdauer durch Anfangs- und Endtag festlegen, ist das Überschneidungsproblem nicht durch eine UNIQUE-Klausel zu lösen, da z.B. Vermietungen für die Intervalle [1.7. – 15.7] und [8.7. – 20.7] verschiedene Anfangsund Endzeiten haben, aber sich dennoch überschneiden. Dieses Problem können wir durch eine Assertion lösen (vgl. Kapitel 4.3.6), über Trigger (für Einfügen und Ändern von Vermietungen) oder in folgender Weise durch eine Datensicht mit CHECK OPTION. Die Überschneidungsbedingung ist abstrakt dadurch ausgedrückt, dass es für eine Vermietung v1 keine Vermietung v2 geben darf mit v1.objekt=v2.objekt, so dass

295

Sandini Bib

7 Konsistenz und Mehrbenutzerbetrieb

sich die Intervalle [v1.beginn,v1.ende] und [v2.beginn,v2.ende] überlappen. Die Überschneidung kann in SQL durch das Prädikat (v1.beginn,v1.ende) OVERLAPS (v2.beginn,v2.ende)

abgefragt werden, und wenn das nicht zur Verfügung steht, durch: v2.beginn < v1.ende AND v1.beginn < v2.ende

Wir können das Überschneidungsproblem vollständig im Datenbankschema definieren, wenn wir im Folgenden für die Tabelle vermietung_x keine Zugriffsrechte zulassen, sondern nur für die Datensicht vermietung: CREATE TABLE vermietung_x ( vertrag CHAR(10) NOT NULL, objekt CHAR(10) NOT NULL REFERENCES haus, mieter CHAR(10) NOT NULL REFERENCES kunde, beginn DATE NOT NULL, ende DATE NOT NULL, PRIMARY KEY (vertrag) ); CREATE VIEW vermietung AS SELECT * FROM vermietung_x AS v1 WHERE NOT EXISTS ( SELECT * FROM vermietung_x AS v2 WHERE v1.objekt = v2.objekt AND v2.beginn < v1.ende AND v1.beginn < v2.ende) WITH CHECK OPTION;

Diese Datensicht vermietung ist entsprechend dem in Kapitel 6.4 Gesagten aktualisierbar. Somit ist es über diese Datensicht möglich, alle gewünschten Änderungen durchzuführen; es ist aber nicht möglich, ein Objekt für einen Zeitraum doppelt zu vermieten.

Existenzielle Abhängigkeiten In den meisten Fällen können existenzielle Abhängigkeiten über eine Fremdschlüsselbeziehung gelöst werden. Die existenzielle Abhängigkeit kann aber gewisse andere Bedingungen als Voraussetzung haben. In diesen Fällen können wir keine Fremdschlüssel verwenden. Als Beispiel betrachten wir folgende Bedingung: »Für jeden Kunden, der die Waren über Bankeinzug erhält, muss ein Girokonto existieren.« Dies können wir durch eine Assertion beschreiben (die leider noch nicht in vielen Datenbanksystemen verfügbar ist) oder wir können Trigger dazu verwenden (die noch nicht zum Standard gehören und außerdem den Nachteil haben, dass sie pro-

296

Sandini Bib

Strategien zur Konsistenzsicherung

zedural und nicht deklarativ sind). Wir zeigen im Folgenden, dass solche komplexen Bedingungen auch ohne Trigger und ohne Assertions über Datensichten mit einer CHECK-Klausel gelöst werden können. Hierzu definieren wir die Kundentabelle als kunde_x, auf die kein Benutzer Zugriffsrechte bekommt. Darüber legen wir eine Datensicht kunde, für die die entsprechenden Zugriffsrechte vergeben werden: CREATE TABLE kunde_x( kunden_nr Kunden_Key status Kunden_status name PersonenName strasse Strassenname plz Postleitzahl ort ortsname letzte_bestellung DATE, letzte_werbeaktion DATE, zahlung Zahlungsart PRIMARY KEY (kunden_nr) );

NOT NOT NOT NOT NOT NOT

NULL, NULL, NULL, NULL, NULL, NULL,

NOT NULL,

CREATE VIEW kunde AS SELECT * FROM kunde_x AS k WHERE zahlungsart 'B' OR EXISTS ( SELECT * FROM girokonto g WHERE k.kunden_nr = g.kunden_nr) WITH CHECK OPTION;

Die Datensicht kunde ist wiederum aktualisierbar. Somit können alle gewünschten Änderungen durchgeführt werden. Es ist aber nicht möglich, einen Kunden zu erfassen oder dessen Daten so zu ändern, dass er das Attribut zahlungsart = 'B' hat, aber kein entsprechendes Girokonto.

Beziehungen mit Aggregatfunktionen In diese Kategorie fallen Bedingungen wie die folgende: »Der Wert der bestellten Artikel in einer Bestellung darf den Betrag 1.000,- Euro nicht übersteigen«. Eine solche Bedingung kann ähnlich wie die beiden letzten Beispiele durch eine Assertion, durch Trigger oder durch eine Datensicht sichergestellt werden. Wir formulieren hier eine Assertion: CREATE ASSERTION nicht_mehr_als_1000 CHECK (1000 >= ALL (SELECT SUM(gesamtpreis) FROM position GROUP BY bestell_nr) );

297

Sandini Bib

7 Konsistenz und Mehrbenutzerbetrieb

7.4.2 Dynamische Geschäftsregeln Neben den statischen Geschäftsregeln können wir Regeln festlegen, welche Bedingungen Änderungsoperationen erfüllen müssen. Hierbei stellen wir Regeln auf, die nicht nur die zulässigen Datenbankzustände einbeziehen, sondern die Bedingungen beziehen sich auf den Datenbankzustand vor einer Änderung und den Zustand nach einer Änderung. Dynamische Geschäftsregeln treten u.a. in folgenden Fällen auf: 왘 Attribute, die Zustände von Entitäten beschreiben, dürfen nicht in beliebiger Reihenfolge auftreten. 왘 Attribute dürfen nicht geändert werden – allerdings dürfen Nullmarken durch einen Wert ersetzt werden. 왘 Bestandsänderungen (z.B. Kontostand, Warenbestand) dürfen nur durch vorher festgelegte Änderungsoperationen (z.B. Buchung, Warenentnahme) verändert werden, wobei die Änderungsoperationen zu protokollieren sind.

Zustandsübergänge Als Beispiel hierfür kann der Kundenstatus gelten, wenn wir vereinbaren, dass nur folgende Übergänge möglich sind: werbemassnahme -> gelegenheitskunde gelegenheitskunde -> stammkunde, stammkunde -> gelegenheitskunde

Zur Kontrolle dieser Regeln können wir entweder einen Trigger benutzen, der vor der Änderung des Attributs status aktiviert wird und andere Übergänge verhindert, oder wir verwenden eine Datenbankprozedur für die Änderung eines Zustandes. Für das Attribut zustand darf dann kein Änderungsrecht existieren.

Änderungsrecht für Nullmarken Hier haben wir eine Art von »Einfügen« neuer Daten (Wert für ein Attribut, das vorher eine Nullmarke hatte). Allerdings ist dieses Einfügen mit der UPDATEAnweisung durchzuführen. Neben den Möglichkeiten, die im vorigen Abschnitt genannt wurden, können wir diese Bedingung durch eine Datensicht festlegen. Wir gehen im Folgenden davon aus, dass es unzulässig ist, bei einem Artikel die Verpackung zu ändern, es sei denn, es ist keine Verpackung eingetragen. In diesem Fall wird für die Verpackung kein Änderungsrecht vergeben – es wird aber zusätzlich eine Datensicht erzeugt, die die Artikel ohne Verpackung enthält. Hierfür werden Änderungsrechte vergeben: CREATE VIEW artikel_ohne_verpackung AS SELECT artikel_nr, verpackung FROM artikel WHERE verpackung IS NULL;

298

Sandini Bib

Strategien zur Konsistenzsicherung

GRANT INSERT(artikel_nr,bezeichnung,verpackung,...), UPDATE(artikel_nr,bezeichnung,...), SELECT, DELETE ON artikel TO lager; GRANT UPDATE (verpackung) ON artikel_ohne_verpackung TO lager;

Protokollierte Bestandsänderungen 왘 Als Beispiele betrachten wir folgende Geschäftsregeln: 왘 Für jeden Zahlungsausgang ist zu verbuchen, wer diese Zahlung wann veran-

lasst hat. 왘 Für jede Änderung des Artikelbestandes muss ein Änderungsbeleg vorhanden

sein. Eine solche Bestandsänderung kann z.B. sein: eine Position in einer Auslieferung, eine Warenentnahme für betriebsinterne Zwecke, eine Entnahme von beschädigter, defekter oder verdorbener Ware, ein Wareneingang vom Lieferanten, die Aufnahme eines eigenen Produkts, die Rücknahme aus einer Lieferung und als Letztes eine Bestandskorrektur, wenn bei einer Inventur eine Abweichung des Istbestands vom Sollbestand nach Buchführung herauskommt. Die erste Aufgabenstellung können wir dadurch lösen, dass wir eine Tabelle ueberweisung mit den Feldern veranlasser und zeitpunkt anlegen , auf die keine

Einfüge- und Änderungsrechte vergeben werden, aber stattdessen Standardwerte durch DEFAULT-Klauseln (unveränderlich) festgelegt werden16, wie im Folgenden dargestellt: CREATE TABLE ueberweisung ( empfaenger CHAR(30) NOT NULL, blz DECIMAL(8) NOT NULL, konto_nr CHAR(10) NOT NULL, betrag MONEY, grund CHAR(120), veranlasser CHAR(12) NOT NULL DEFAULT CURRENT USER, zeitpunkt TIMESTAMP NOT NULL DEFAULT CURRENT TIMESTAMP ); GRANT INSERT (empfaenger, blz, konto_nr, betrag, grund) TO haushalt;

16 Falls – wie in Sybase SQL Anywhere – für das INSERT-Privileg keine Spalten angegeben werden können, müssen wir auch hier den Umweg über eine Datensicht nehmen, die die beiden Attribute veranlasser und zeitpunkt nicht enthält.

299

Sandini Bib

7 Konsistenz und Mehrbenutzerbetrieb

Die zweite Aufgabe können wir mithilfe zweier zusätzlicher Tabellen17 für die Warenzugänge und Warenabgänge lösen, in die die Bestandsänderungen mit Datum, Uhrzeit, gegebenenfalls Veranlasser und Art der Änderung einzutragen sind. Für diese Tabellen darf es kein DELETE-Privileg und kein UPDATE-Privileg geben: Buchungen dürfen nicht gelöscht und nicht nachträglich verändert werden; eine falsche Buchung muss durch eine weitere Korrekturbuchung mit umgekehrtem Vorzeichen rückgängig gemacht werden. Des Weiteren darf auf der Spalte bestand der Tabelle artikel kein UPDATE- oder INSERT-Privileg existieren. Es ist dann sicherzustellen, dass für jede Bestandsänderung die entsprechende Tabelle gleichzeitig mit aktualisiert wird. Dies lässt sich auf zwei Weisen erledigen: 왘 Es wird ein Satz in die Buchungstabelle geschrieben. Dafür muss ein INSERT-

Privileg vorhanden sein. Die entsprechenden Änderungen im Bestand werden durch Trigger veranlasst. 왘 Es wird kein Recht auf die Buchungstabellen vergeben. Änderungen erfolgen

jetzt über Datenbankprozeduren (vgl. Kapitel 7.3.1, dort finden Sie auch die Beispiele). Die berechtigten Benutzer bekommen dafür ein EXECUTE-Privileg für die entsprechenden Prozeduren. Die Benutzung von Datenbankprozeduren ist die direktere Lösung dieses Problems. Sie entspricht dem aus der Programmierung bekannten Verfahren der abstrakten Datentypen und der Datenkapselung bei der objektorientierten Programmierung. Die Verwendung von Triggern hat aber einen Vorteil, der für eine Reihe von mittleren Anwendungen ins Gewicht fallen kann: Falls für die Entwicklung des Frontend-Systems ein über ODBC angeschlossenes PC-Datenbanksystem wie z.B. Access verwendet wird, können wir die Oberfläche unabhängig vom Backend entwickeln. Die Daten werden in die Buchungstabellen eingetragen, und die Trigger sorgen dafür, dass die Bestandsänderung veranlasst wird. Es müssen keine ODBCProzeduren für den Aufruf der Datenbankprozeduren erstellt werden.

17 Es reicht im Prinzip eine Tabelle, in der die Zugänge durch positive Zahlen, die Abgänge durch negative Zahlen einzutragen sind. Die Formulierung der Konsistenzregeln und die Regelung der Zugriffsrechte ist dann eventuell etwas umständlicher. Es können auch mehr als zwei Tabellen genommen werden – für jede Art der Bestandsänderung eine eigene Tabelle. Dies führt aber schnell zu einer unübersichtlichen Menge von Tabellen.

300

Sandini Bib

8

Der Systemkatalog

Der Systemkatalog besteht aus Tabellen und Datensichten, die Informationen über die diversen Datenbankobjekte wie Tabellen, Datensichten, Benutzer sowie Zugriffsrechte und Indexe enthalten. Er erfüllt bei SQL eine doppelte Funktion: Einerseits kann ein Benutzer daraus Namen und Struktur von Datenbankobjekten entnehmen, die er für seine Arbeit mit SQL braucht. Andererseits benötigt das System selbst solche Informationen, um über die Datenbank Buch zu führen und Datenmanipulationen auszuführen. Beispielsweise benutzt das DBMS den Katalog, um zu registrieren, welche Tabellen es gibt und welche Spalten sie enthalten. Ändert sich die Struktur einer Tabelle, wird eine neue Tabelle erstellt oder eine alte gelöscht, so spiegelt sich dies im Datenkatalog wider. SQL prüft mittels des Katalogs, ob ein Benutzer Zugang zur Datenbank erhält und weiter dazu berechtigt ist, eine bestimmte Tabelle zu bearbeiten (siehe Kapitel 7). Wenn der DBA einen neuen Benutzer anmeldet, so werden Benutzername und Passwort in einer Datenkatalogtabelle niedergelegt. Der Query-Optimizer ermittelt bei Abfragen die zu der betroffenen Tabelle gehörigen Indexe und die jeweiligen Indexspalten aus dem Katalog. Jedes DBMS muss im Prinzip einen Systemkatalog enthalten. Jedoch ist der Zugriff darauf unter Umständen nur über spezielle Programme und für einen Benutzer unter Umständen gar nicht ohne weiteres möglich. Die Besonderheit des SQLDatenkatalogs ist, dass die Tabellen und Datensichten, aus denen er sich zusammensetzt, mit dem SQL-Befehl SELECT erreichbar sind wie jede andere Tabelle. Die unerlässliche Dokumentation jeder Datenbank wird damit automatisch geleistet, ist jederzeit abrufbar und stets auf dem neuesten Stand.

8.1 Der Systemkatalog im SQL-Standard In SQL wird ein INFORMATION_SCHEMA gefordert, das aus einer Sammlung von Datensichten besteht. Die Basistabellen, auf denen diese Datensichten beruhen, werden ebenfalls im Standard aufgeführt. Das zugehörige Schema wird DEFINITION_SCHEMA genannt.1 Es ist aber nicht so gemeint, dass ein standardkonformes DBMS genau diese Basistabellen und Datensichten bereitstellen muss. Das INFORMATION_SCHEMA kann und darf durch Datenbankhersteller jederzeit erweitert werden, wenn dies für die Funktion des DBMS erforderlich ist.

1 Vgl. [MeSi02 S. 715f].

301

Sandini Bib

8 Der Systemkatalog

Ein Benutzer hat auf Systemtabellen keinen direkten schreibenden Zugriff. Keiner der Befehle INSERT, UPDATE oder DELETE kann angewandt werden. Implizit werden jedoch bei allen DDL-Befehlen in Systemtabellen Zeilen eingefügt, verändert oder gelöscht. So zieht beispielsweise die Ausführung eines CREATE TABLEBefehls die Eintragung etlicher neuer Zeilen mit Daten über die Tabelle, ihre Spalten und Konsistenzbedingungen nach sich. DROP TABLE hingegen führt zu Löschoperationen in den Systemtabellen. Zu Informationszwecken soll das INFORMATION_SCHEMA allen Benutzern zur Verfügung stehen, wenn auch in unterschiedlicher Detaillierung. Daher ist einheitlich für alle Datensichten der Benutzergruppe PUBLIC das SELECT-Privileg zugewiesen. Um benutzerspezifische Details wiederzugeben und nichtöffentliche Informationen zu verbergen, enthalten die Datensichten meist eine dynamische Selektionsklausel, so dass jeder Benutzer nur Daten über seine eigenen und die ihm zugänglichen fremden Datenbankobjekte erhält. Das Selektionsattribut (z. B. OWNER), das den Eigentümer oder den berechtigten Benutzer (z. B. GRANTEE) eines Datenbankobjekts enthält, wird dazu mit der Pseudospalte CURRENT_USER verglichen, in der der Name des angemeldeten Benutzers zur Verfügung steht. Einige der wichtigsten Datensichten des INFORMATION_SCHEMA stellen wir kurz vor.2 Unter »Benutzer« verstehen wir den in der Datenbank niedergelegten Namen des jeweils für die aktuelle Sitzung beim DBMS angemeldeten Benutzers. Die Begriffe »zugänglich« und »eigen« beziehen sich jeweils auf den Benutzer.3 Name der Datensicht

Erläuterung

SCHEMATA

zeigt alle Schemata, die dem Benutzer gehören.

DOMAINS

zeigt die zugänglichen Domänen.

TABLES

zeigt die zugänglichen Tabellen.

VIEWS

zeigt die zugänglichen Datensichten.

COLUMNS

zeigt die Spalten der zugänglichen Tabellen.

TABLE_CONSTRAINTS

zeigt die für die eigenen Tabellen definierten Konsistenzbedingungen.

REFERENTIAL_CONSTRAINTS

zeigt die eigenen referenziellen Integritätsbedingungen, also die, die sich auf die eigenen Tabellen beziehen.

ASSERTIONS

zeigt die vom Benutzer eingerichteten Assertions.3

Tabelle 8.1: Datensichten des INFORMATION_SCHEMA in SQL

2 Eine vollständige Übersicht findet man in [MeSi02 Kap. 22]. 3 Assertions sind Integritätsbedingungen, die sich auf Werte aus mehreren Zeilen unterschiedlicher Tabellen beziehen können (siehe Kapitel 4.3.6).

302

Sandini Bib

Systemtabellen in SQL-Implementationen

Name der Datensicht

Erläuterung

COLUMN_DOMAIN_USAGE

zeigt die eigenen Tabellenspalten in Verbindung mit der bei ihrer Definition verwendeten Domäne.

ABSTRACT_DATA_TYPES

zeigt die dem Benutzer zugänglichen abstrakten Datentypen.

COLUMN_ABSTRACT_DATA_ TYPE_USAGE

zeigt die von einem abstrakten Datentyp abhängigen Tabellenspalten, soweit dem aktuellen Nutzer zugänglich.

Tabelle 8.1: Datensichten des INFORMATION_SCHEMA in SQL (Forts.)

8.2 Systemtabellen in SQLImplementationen Wir zeigen in diesem Abschnitt den Gebrauch einiger Systemtabellen anhand der Produkte Sybase Adaptive Server Anywhere und ORACLE. Bei manchen DBMS beginnen die Namen aller Katalogtabellen mit »SYS« – so auch bei Sybase Adaptive Server Anywhere. ORACLE stellt sinnigerweise jeweils das Präfix »USER_«, »DBA_« beziehungsweise »ALL_« voran. Damit ist durchgängig eine Auswahl der aufzulistenden Objekte impliziert, und die im Standard anzutreffende Vermischung von eigenen und zugänglichen Objekten wird vermieden. USER_objektkategorie

zeigt nur die eigenen Objekte des angemeldeten Benutzers.

z.B. USER_TABLES

ALL_objektkategorie

zeigt die dem Nutzer zugänglichen Objekte.

z.B. ALL_TABLES

DBA_objektkategorie

zeigt die einem Systemverwalter zugänglichen Objekte.

z.B. DBA_TABLES

Tabelle 8.2: Namenskonventionen für Systemtabellen bei ORACLE

Informationen über Tabellen SYSTABLE heißt bei Sybase die Katalogtabelle4, aus der man Informationen über die verfügbaren Tabellen erhält. Sie wird bei der Anlage einer neuen Datenbank vom System aus automatisch erzeugt. Ein entsprechender CREATE TABLE-Befehl sähe so aus:5

4 Ob es sich bei den im Folgenden vorgestellten Tabellen um Basistabellen oder Datensichten handelt, ist ohne Belang. Wir benutzen in jedem Fall den Begriff Tabelle. 5 Der Befehl läuft so aber nicht ab, denn dann müsste für SYSTABLE bereits bei der Anlage eine Zeile in SYSTABLE eingetragen werden.

303

Sandini Bib

8 Der Systemkatalog CREATE TABLE SYS.SYSTABLE ( table_id SMALLINT NOT NULL, file_id SMALLINT NOT NULL, count INTEGER NOT NULL, first_page INT NOT NULL, last_page INT NOT NULL, primary_root INT NOT NULL, creator SMALLINT NOT NULL, table_name CHAR(128) NOT NULL, table_type CHAR(10) NOT NULL, view_def LONG VARCHAR, remarks LONG VARCHAR, replicate CHAR(1) NOT NULL, PRIMARY KEY UNIQUE FOREIGN KEY )

FOREIGN KEY

( table_id ), ( table_name, creator ), ( creator ) REFERENCES SYS.SYSUSERPERM ( user_id ), REFERENCES SYS.SYSFILE

Jede Zeile in der Tabelle SYSTABLE beschreibt eine Basistabelle oder eine Datensicht. Man erkennt beispielsweise an der PRIMARY KEY-Klausel, dass es sich bei SYSTABLE in diesem DBMS selbst um eine Basistabelle und nicht um eine Datensicht handelt. Attribute wie file_id und first_page beziehen sich auf spezielle Formen der Speicherorganisation und sind produktspezifisch. Die im Standard vorgesehene Einschränkung auf Tabellen, die dem Nutzer zugänglich sind, ist hier nicht realisiert. Die Tabelle SYSTABLE zeigt alle Tabellen, und erst der Versuch, in einem SELECT-Befehl auf eine nicht verfügbare Tabelle zuzugreifen, führt zu einer Fehlermeldung. Es ist also erforderlich, eine Selektionsbedingung einzugeben, falls man nur die eigenen Tabellen sehen möchte, wie folgendes Beispiel zeigt: SELECT table_id, table_name, view_def, creator FROM systable WHERE creator > 3 table_id ======== 161 162 163 164 165 166

table_name ================ kunde mwstsatz bestellung artikel position girokonto

view_def creator ============================== ======= (NULL) 4 (NULL) 4 (NULL) 4 (NULL) 4 check(liefermenge 3 table_id ======== 161 162 163 164 165 166

table_name ============ kunde mwstsatz bestellung artikel position girokonto

view_def creator name ============================== ======= ============= (NULL) 4 chef2000 (NULL) 4 chef2000 (NULL) 4 chef2000 (NULL) 4 chef2000 check(liefermenge=0) BOOLEAN 2 check(@VALUE between 0 and 1) Prozentsatz 3 (NULL) ... Kunden_key 4 check(@VALUE>100) Kunden_status 1 check(@VALUE in('W','G','S')) Zahlungsart 1 check(@VALUE in('R','B','N','V','K') Artikel_key 4 (NULL) ...

Informationen über Integritätsbedingungen Wie bereits erwähnt, sind Integritätsbedingungen eigenständige Objekte. Sie können im Allgemeinen nicht einer bestimmten Tabelle zugeordnet werden, da sie sich auf mehrere Tabellen beziehen können. In unserem Anwendungsfall darf das Attribut zahlung in der Tabelle kunde nur dann den Wert 'B' haben, wenn in der Tabelle girokonto ein dem nämlichen Kunden per Fremdschlüssel zugeordnetes 7 Der Befehl CREATE DOMAIN wird in Kapitel 4.2 behandelt. 8 check ist hier in doppelte Apostrophe einzuschließen, da es sonst als Schlüsselwort aufgefasst wird und nicht als Name einer Spalte.

307

Sandini Bib

8 Der Systemkatalog

Tupel existiert. Sie können erst recht nicht einer einzelnen Spalte zugeordnet werden. Im Anwendungsbeispiel haben wir die Bedingung bestelldatum = 0 MINDESTBESTAND >= 0 NACHBESTELLMENGE is null or (NACHBESTELLMENGE >= 0)

ARTIKEL_NR IS NOT NULL MWST IS NOT NULL BEZEICHNUNG IS NOT NULL LISTENPREIS IS NOT NULL BESTAND IS NOT NULL BESTELL_NR IS NOT NULL KUNDEN_NR IS NOT NULL BESTELLDATUM IS NOT NULL

PK_MWST

NO ACTION

PK_KUNDE

NO ACTION

Sandini Bib

Systemtabellen in SQL-Implementationen

Übungsaufgaben Aufgabe 8.1 Ermitteln Sie die Systemtabellen des von Ihnen genutzten DBMS, die Informationen über 왘 Tabellen 왘 Spalten 왘 Benutzer 왘 Integritätsbedingungen

enthalten. Mit welchen Abfragen erhalten Sie die Daten 왘 Ihrer eigenen Datenobjekte? 왘 der Ihnen zugänglichen Datenobjekte?

Aufgabe 8.2 Welche Spalten kommen in mehreren Tabellen oder Datensichten vor? Aufgabe 8.3 Welche Spalten kommen in mehreren Basistabellen (ohne Datensichten) vor? Aufgabe 8.4 Ermitteln Sie alle zu Ihren Datenobjekten definierten Primär- und Fremdschlüssel.

309

Sandini Bib

Sandini Bib

9

Objektorientierung und SQL

Nach der breiten Durchsetzung von relationalen Datenbanksystemen zu Beginn der 80er-Jahre wurde bald klar, dass für eine Reihe von Anwendungsgebieten das relationale Datenmodell keine adäquate Grundlage darstellt. Zu diesen »NichtStandard«-Anwendungen gehören u.a. 왘 Kartographie und Katasterwesen 왘 Entwurf integrierter Schaltungen 왘 CAD-Datenbanken 왘 Datenbanken für Büro-Umgebungen, z.B. Dokumentenverwaltung 왘 Multimedia-Anwendungen

Zuerst erschienen eine Reihe von Arbeiten, die das relationale Modell erweiterten (z.B. NF²-Modell: »non first normal form«) und dabei bewährte Konzepte der relationalen Datenbanken übernahmen. Später (ab etwa 1985) erschienen Arbeiten über objektorientierte Datenbanksysteme, die ein neues Datenbankmodell forderten als Ergänzung der bereits existierenden objektorientierten Programmiersprachen wie C++ und Smalltalk um die Möglichkeit, persistente Objekte zu schaffen und zu bearbeiten und in ihrer komplexen Objektstruktur in einer Datenbank zu speichern. Ein wichtiger Hinweis: Eine Datenbank ist noch nicht objektorientiert, wenn das Entwicklungssystem, mit dem die Anwendungen erstellt werden, objektorientiert ist (wie zum Beispiel über JDBC mit Java), sondern die Eigenschaften der Objektorientierung beziehen sich auf das Datenmodell und die Datenspeicherung.

Entwicklungstendenzen der Objektorientierung im Datenbankbereich Diese Diskussionen führten zuerst im Forschungsbereich zur Entwicklung von Prototypen von objektorientierten Datenbanken, die zum Ende der 80er-Jahre auch auf den Markt drängten. Um die Entwicklungstendenzen in eine bestimmte Richtung zu lenken, haben im Jahre 1989 sechs Autoren aus mehreren Ländern auf der DOOD-Konferenz in Kyoto das Object-Oriented Database Manifesto vorgestellt, das einige Anforderungen an objektorientierte Datenbanksysteme stellt (nachzulesen in [Atki89]). Bei der Entwicklung objektorientierter Datenbanksysteme waren von Anfang an zwei Linien erkennbar. Die Vertreter der einen Linie waren der Ansicht, dass man objektorientierte Datenbanken völlig neu entwickeln müsse, um eine adäquate Technik zu schaffen, die das objektorientierte Paradigma möglichst effektiv realisiert. Die bisherige Datenbanktechnologie hielten sie für unbrauchbar, weil auf einer völlig anderen theoretischen Grundlage entstanden.

311

Sandini Bib

9 Objektorientierung und SQL

ODMG Um frühzeitig einen Standard für OO-Datenbanken zu definieren, haben sich 1993 mehrere Personen aus verschiedenen Softwarehäusern zusammengefunden. Diese Gruppe hat sich den Namen ODMG (Object Database Management Group) gegeben. Es findet eine Zusammenarbeit mit der OMG (Object Management Group) statt, die Standards für objektorientierte Methoden für Betriebssysteme und Netze entwickeln will. Das Ergebnis ist 1993 zuerst veröffentlicht worden. Die derzeit aktuelle Version 3.0 ist in [Catt00] verfügbar. Dieser Standard ist noch kein Industriestandard oder gar eine Norm – er soll aber verhindern, dass in einigen Jahren eine Vielzahl unterschiedlicher, nicht miteinander kompatibler Systeme auf dem Markt erscheint. Gegenstände der Standardisierung sind unter anderem ein objektorientiertes Datenmodell mit einem Typenkonzept, das Konstruktoren für komplexe Datenstrukturen wie set, bag, list umfasst sowie die Bildung von Typhierarchien mit Mehrfachvererbung festschreibt. Es werden eine Objektdefinitionssprache ODL und eine Sprache zur Datenmanipulation OQL (Object Query Language) definiert. Ferner wird die Sprachanbindung an C++, Smalltalk und Java behandelt.

Objektrelationale Datenbanken Dagegen argumentierten die Vertreter der anderen Linie, dass die Entwicklung der relationalen Datenbanktechnologie bis zum heutigen Reifegrad Millionen von Entwicklungsstunden gekostet habe, die man nicht einfach auf den Müllhaufen der Geschichte werfen solle. Schließlich geht es dabei nicht nur um das Speichern und Wiederfinden von Daten, sondern auch um Konzepte der Datensicherheit, Nebenläufigkeit, Datenverteilung, unterbrechungsfreien Betrieb 7*24 Stunden lang und vieles mehr. Hinzu kommt das Argument der »sanften Migration«: Wenn auf der ganzen Welt Millionen von Anwendungen in Wirtschaft und Verwaltung produktiv genutzt werden, wird es eine neue Technologie, in der die alten Systeme keinen Bestand mehr hätten, schwer haben, sich durchzusetzen. Aus diesen Erwägungen ergab sich der Ansatz, vorhandene relationale Datenbanksysteme um objektorientierte Konzepte zu erweitern; alte Systeme laufen unverändert weiter. Dieser Ansatz wird »objektrelational« genannt. Er hat in den SQL-Standard Einzug gehalten und wird von etablierten Anbietern relationaler DBMS vorangetrieben. Wir stellen in Abschnitt 9.1 zunächst in Kurzform das objektorientierte Datenbankmodell vor1. In Abschnitt 9.2 behandeln wir die objektorientierten Konzepte, die in den SQL-Standard aufgenommen wurden. Kapitel 9.3 stellt eine objektrelationale Fassung unserer Versand-Datenbank vor, wie man sie mit Oracle, Version 9 realisieren kann.

1 Einige Bemerkungen zum objektorientierten Datenmodell finden sich auch in Kapitel 3.3, in dem wir die objektorientierte »Entwurfssprache« UML behandeln.

312

Sandini Bib

Das objektorientierte Datenbankmodell

9.1 Das objektorientierte Datenbankmodell Wir beschreiben nun einige wichtige Eigenschaften des objektorientierten Datenmodells.2 Die zunächst recht abstrakten Begriffe, die wir gleich vorstellen, werden in den folgenden Abschnitten an Beispielen erläutert. In den dann folgenden Konkretisierungen – objektrelationale Erweiterungen ab SQL:1999 und objektorientierte Datenbanken nach ODMG – sind jeweils nur einige der hier angesprochenen Möglichkeiten konkret ausgebildet und dann in einer jeweils unterschiedlichen Syntax.

9.1.1 Grundbausteine Basiselemente des objektorientierten Datenbankmodells sind Objekte und Literale. Jedes Objekt hat eine eindeutige Identität. Ein Objekt kann grundsätzlich im Laufe seiner Existenz seinen Zustand ändern. Ein Literal hat keine Identität; es hat auch keinen änderbaren Zustand, sondern beschreibt einen Wert. So ist ein Mitarbeiter oder ein Artikel ein Objekt – eine Zahl, eine Zeichenkette oder eine feste Uhrzeit ist ein Literal. Objekte und Literale werden durch Typen kategorisiert. Alle Elemente eines gegebenen Typs haben dieselbe Menge an abstrakten Eigenschaften (Attribute) und dasselbe Verhalten. Ein Objekt wird als Instanz seines Typs bezeichnet. Der Zustand eines Objekts wird durch die Werte beschrieben, die seine Eigenschaften aufweisen und durch die Beziehungen, die es zu anderen Objekten hat. Das Verhalten eines Objekts wird durch die Menge an Operationen (Methoden) beschrieben, die das Objekt ausführen kann. Operationen können eine Liste von Ein- und Ausgabeparametern haben, die einem bestimmten Typ angehören. Eine Operation kann ein typisiertes Ergebnis zurückgeben. Eine objektorientierte Datenbank speichert Objekte. Sie basiert auf einem Schema und enthält Instanzen, die auf den im Schema definierten Typen basieren.

9.1.2 Typen Typen dienen der abstrakten Beschreibung von Objekten hinsichtlich ihrer Zustände und ihres Verhaltens. Sie werden durch eine externe Spezifikation und eine oder mehrere Implementierungen beschrieben. Die externe Spezifikation beschreibt die Eigenschaften und Operationen, die für Benutzer sichtbar sind. Eine Implementierung besteht aus Datenstrukturen und Methoden, die die Attribute und Operationen realisieren und die in einer konkreten Programmiersprache erstellt worden sind.

2 Vgl. [Atki89]. Siehe auch [HeSa95 S 114ff].

313

Sandini Bib

9 Objektorientierung und SQL

Beispielsweise kann die externe Spezifikation eines Typs Person durch seine Attribute Name, Adresse, Familienstand und durch eine Operation heiraten beschrieben werden. Diese sind für den Nutzer sichtbar. Verborgen hingegen sind die interne Repräsentation der Attribute (so könnte z.B. das Attribut Familienstand = verheiratet durch die Zahl 3 dargestellt werden) und der Algorithmus, mit dem der Familienstand beim Aufruf der Operation heiraten geändert wird. Typen können von Benutzern definiert werden. Ausgehend von primitiven Datentypen (wie numerische Datentypen, Zeichenketten, logische Werte, Datum, Uhrzeit, Aufzählungstypen) können durch Konstruktoren3 orthogonal4 neue Datentypen zusammengesetzt werden.

Tupel Einen Datentyp, der aus mehreren Komponenten (unterschiedlicher) Datentypen zusammengesetzt ist, erhalten wir durch den Tupel-Konstruktor. In Pascal und Modula entspricht dieses dem RECORD, in C, und C++ dem struct, in C++ und Java einer Klasse, die nur public Attribute, aber keine Operationen besitzt. Ein Beispiel dafür ist die Zusammensetzung einer Adresse aus den Attributen Straße, Hausnummer, PLZ und Ort. Es kann ein Typ typ_adresse definiert werden, der intern die genannten Attribute hat und bei der Definition einer Klasse als Ganzes für den Wertebereich eines strukturierten Attributs verwendet wird. Dieses könnte in etwa wie folgt aussehen: TYPE typ_adresse = RECORD strasse: STRING; hausnummer: INTEGER; plz: STRING; ort: STRING; END;

In SQL heißt dieser Konstruktor »ROW«.

Kollektionstypen Daneben gibt es die so genannten Kollektionstypen (auch »Sammlungen« genannt), die wir im Folgenden erläutern. Diese Konstruktoren können auf beliebige – auch strukturierte – Typen angewandt werden.

3 Der Begriff Konstruktor wird in unterschiedlichen Zusammenhängen mit unterschiedlicher Bedeutung verwendet: Wir meinen hier ein (sprachliches) Mittel, um komplexe (= zusammengesetzte) Datentypen zu konstruieren. Wenn wir dann auf diese Weise zu einer Klasse gekommen sind, gibt es in der Klasse jeweils mindestens einen Konstruktor (jetzt andere Bedeutung!); damit wird beschrieben, was beim Anlegen eines neuen Objektes in der Klasse durchzuführen ist. 4 Der Begriff »orthogonal« wird auf der nächsten Seite eingeführt.

314

Sandini Bib

Das objektorientierte Datenbankmodell

Set Der SET-Konstruktor dient zur Konstruktion von Mengen im mathematischen Sinne. Eine Menge ist eine Zusammenfassung von Elementen desselben Datentyps. Ein Element kann in einer Menge entweder nicht oder (einmal) enthalten sein. Es gibt also keine Dubletten und die Elemente sind ungeordnet. Die Anzahl der Elemente einer Menge ist nicht a priori begrenzt.

Bag oder Multiset Ein Bag oder eine Multimenge enthält ebenfalls Elemente desselben Datentyps; im Gegensatz zu Mengen sind hier Dubletten erlaubt. Eine Multimenge ist ebenfalls ungeordnet und hat beliebig viele Elemente.

List Auch eine Liste besteht aus Elementen desselben Datentyps. Jede Liste hat eine Länge, wobei die Elemente der Liste angeordnet sind: Wenn die Liste nicht leer ist, gibt es ein erstes Element; jedes Element der Liste – bis auf das letzte Element – hat genau ein Nachfolgeelement. Dasselbe Element kann in der Liste mehrfach vorkommen. Es können nachträglich Elemente vor das erste Element, zwischen zwei Elemente oder hinter das letzte Element eingefügt werden, außerdem können Elemente in einer Liste entfernt werden.

Array Ein Array ist eine Kollektion, die eine vorher festgelegte Anzahl von Elementen enthält. Die Elemente eines Arrays sind indiziert (nummeriert), der Zugriff auf ein einzelnes Element erfolgt über seinen Index. Somit können auch keine weiteren Elemente eingefügt werden, sondern nur die Elemente an den festgelegten Positionen eingefügt, abgefragt oder geändert werden. Array-Elemente können allerdings Nullmarken enthalten.

Vararray Ein dynamisches Array hat sehr viele gemeinsame Eigenschaften mit einem Array. Die Elemente eines Array sind indiziert (nummeriert), der Zugriff auf ein einzelnes Element erfolgt über seinen Index. Ein dynamisches Array kann jedoch am Ende um jeweils ein Element verlängert werden und es kann an einer bestimmten Stelle abgeschnitten werden.

Dictionary Dictionary-Typen bestehen aus einer ungeordneten Menge von Paaren von eindeutigen Schlüsselwerten und zugeordneten Werten. Für einen Schlüssel k kann es jeweils nur maximal eine Eintragung [k,v] geben. Der Schlüssel dient also als Zugriffskriterium zum Zugriff auf die Werte. Eine Relation mit zwei Attributen s und w, wobei s der Primärschlüssel ist, ist in diesem Sinne ein Dictionary. Eine

315

Sandini Bib

9 Objektorientierung und SQL

beliebige Relation mit einem Primärschlüssel k kann als Dictionary aufgefasst werden, wenn wir als Schlüssel die Zusammenfassung der Primärschlüsselattribute nehmen und als Daten die Zusammenfassung der übrigen Attribute. Diese Konstruktoren können orthogonal angewandt werden, was bedeutet, dass es für diese Konstruktionen keine spezifischen Einschränkungen gibt. Insbesondere können Datentypen auch durch mehrfache Anwendung der Konstruktoren erzeugt werden, also z.B. SET OF LIST OF RECORD a1: INTEGER; a2: STRING END

und dergleichen (die konkrete Syntax in ODMG und SQL ist hiervon jeweils unterschieden).

9.1.3 Vererbung Die Bildung von Hierarchien ist ein genuiner Bestandteil des objektorientierten Modells. Hier können Strukturen wie die Spezialisierung und Generalisierung unmittelbar umgesetzt werden, die in einem relationalen Datenmodell nicht ohne semantische Verluste abgebildet werden können. Zum Beispiel sind für einen Typ Person verschiedene Spezialisierungen in Hochschulangehörige und freie Dozenten denkbar, die ihrerseits weiter differenziert sein können. Dabei gilt für Studierende wie für Professoren bei allen spezifischen Unterschieden allgemein, dass sie Personen sind und damit alle Merkmale von Personen aufweisen.

Person

HochschulAngehöriger

Studierender

sonstiger Bediensteter

Dozent

Professor

Lehrbeauftragter

Abbildung 9.1: Typenhierarchie von Personen im Hochschulbereich

Im Bereich der Geografie – speziell der Kartografie – haben wir es mit Linienzügen zu tun, die Verschiedenes darstellen können, etwa Küstenlinien, Wasserwege, darunter Kanäle etc. Abgesehen von speziellen Eigenschaften wie Farben haben sie

316

Sandini Bib

Das objektorientierte Datenbankmodell

viele gemeinsame Eigenschaften, wie z.B. das Verhalten bei Veränderungen des Abbildungsmaßstabes. Linienzug

Küstenlinie

Wasserweg

Verkehrsweg

Grenze

Kanal

Fluss

Straße

Schiene

Abbildung 9.2: Typenhierarchie von Linienzügen im Bereich Geografie

Die Hierarchiebildung wird dabei durch das Vererbungskonzept unterstützt, welches zwei Ausprägungen hat: Strukturvererbung und Verhaltensvererbung. Die Strukturvererbung bedeutet, dass jeder Subtyp alle Attribute des Obertyps enthält. Er kann aber weitere Attribute enthalten oder auch Attribute des Obertyps in modifizierter Form übernehmen.5 Beispielsweise hat jede Person eine Adresse, bestehend aus Strasse, Hausnummer, Name, PLZ und Ort. Bei Hochschulangehörigen könnte zusätzlich ein Datum des Ersteintritts verwaltet werden. Professoren und sonstige Bedienstete haben eine Gehaltsstufe, Studenten aber nicht; bei Studenten wird wegen häufigen Umzugs eine zusätzliche Heimatadresse verwaltet. Die Verhaltensvererbung erläutern wir im nächsten Abschnitt näher. Das ODMB Objekt Modell unterstützt die Mehrfachvererbung. In dem obigen Beispiel ist der Subtyp Professor zugleich eine Spezialisierung von Dozent und von HS-Angehöriger und erbt daher von beiden die Attribute und Methoden.

9.1.4 Verhaltensvererbung und Polymorphismus Die Verhaltensvererbung bedeutet, dass jeder Subtyp automatisch die Methoden des Obertyps übernimmt. Er kann jedoch zusätzliche Methoden anbieten oder ererbte Methoden redefinieren.6 Dies wird mit dem Begriff Polymorphismus gekennzeichnet. Beispielsweise können alle Hochschulangehörigen heiraten, aber nur bei Professoren und sonstigen Bediensteten ändert sich dann automatisch die Gehaltshöhe. 5 Dabei muss der Typ des modifizierten Attributs eine Spezialisierung des geerbten Attributs sein. 6 Dabei muss die modifizierte Methode »aufrufkompatibel« zur ererbten sein. Das betrifft im Wesentlichen die Anzahl und die Typen der Ein- und Ausgabeparameter.

317

Sandini Bib

9 Objektorientierung und SQL

Welche spezielle Ausprägung einer Methode für ein konkretes Objekt anzuwenden ist, muss das System anhand der Zuordnung zu einer Subklasse entscheiden. Beispiel: Für geometrische Figuren sei grundsätzlich die Methode Fläche definiert. Jede Figur ist ein Ellipsenelement, Kreissegment, Kreis, Polygonzug, Viereck, Dreieck oder achsenparalleles Rechteck. Für jede dieser Figuren ist eine Formel für Fläche definiert. Für eine beliebige Figur f kann erst zur Laufzeit bestimmt werden, welche Formel zu wählen ist. Die Benutzung des einheitlichen Operators Fläche, der für die verschiedenen Subklassen abweichend von der Oberklasse implementiert ist, wird als Überschreiben bezeichnet, das Laden des entsprechenden Programmcodes Überladung. Den Vorgang, dass ein Programm zur Laufzeit aufgrund der Subklassenzugehörigkeit eines Objekts den passenden Algorithmus für Fläche(f) auswählt, nennen wir spätes Binden.

9.1.5 Klassen und Extents Eine Klasse ist laut Definition der ODMG ein Typ, der unmittelbar Objekte aufnehmen kann. Objekte einer Klasse werden (in Übersetzung des englischen Begriffs instance) auch als Instanzen bezeichnet. Zum einen hat eine Klasse also eine Funktion als Behälter. Daneben beschreibt eine Klasse durch ihre öffentlichen Operationen aber auch eine Schnittstelle, über die mit den Objekten der Klasse kommuniziert werden kann. Neben den durch die Klassen festgelegten Schnittstellen gibt es auch Interfaces, die eine Schnittstelle beschreiben, ohne damit die Struktur einer Klasse zu beschreiben. Beispielsweise kann es sein, dass in unserer objektorientierten Hochschulverwaltungs-Datenbank eine Bibliotheksverwaltung integriert ist. Kunden der Bibliothek können Hochschulangehörige sowie externe Kunden sein – externe Kunden bilden eine eigene Klasse – und es gibt eine Schnittstelle, die das Verhalten der Hochschulangehörigen und der externen Kunden gegenüber der Bibliothek definiert. Ein Interface kann durch verschiedene Klassen implementiert werden. Klassen sind nach dem Verständnis der ODMG Vorschriften zur Bildung von konkreten Instanzen, also Objekten. Dagegen sind Schnittstellen abstrakte Beschreibungen des Verhaltens von Objekten. Für die Sammlung der Objekte einer Klasse sind Extents zuständig. Ein Extent bezeichnet die Menge aller Instanzen eines Typs. Extents werden auch als Behälter bezeichnet. Im Zusammenhang mit der Typen- und Klassenhierarchie gilt dabei: wenn A der Extent des Typs a_typ ist, und b_typ ein Subtyp von a_typ, dann ist der Extent B von b_typ eine Teilmenge von A. Ein Objekt, das einer Unterklasse angehört, kann auch als Argument einer Operation der Oberklasse zugewiesen werden. Das Umgekehrte gilt nicht.

318

Sandini Bib

Das objektorientierte Datenbankmodell

In der objektorientierten Programmierung (im Gegensatz zu objektorientierten Datenbanken) wird in der Regel nicht zwischen Klasse und Extent unterschieden, da Objekte in Programmen erzeugt werden und über einen Bezeichner oder eine Referenz auf sie zugegriffen werden kann. In objektorientierten Programmiersprachen mit automatischer Speicherverwaltung (sog. garbage collection) werden nicht erreichbare Objekte automatisch aus dem Speicher entfernt (z.B. bei Smalltalk und Java). In Datenbanken wollen wir dagegen auch in Programmläufen auf Objekte zugreifen, die in anderen Programmläufen erzeugt wurden. Daher benötigen wir hier für viele Anwendungen Extents von Klassen, um alle Objekte einer Klasse verarbeiten können.

Objektklasse

Subklasse

Objekt Objekttyp

OODBBegriffe

Subtyp

Abbildung 9.3: Begriffe im Zusammenhang mit objektorientierten Datenbanken

9.1.6 Objektidentität und Gleichheit Ein Objekt muss systemweit identifizierbar sein. Die Identität (OID) wird vom System selbst gepflegt. Sie ist nicht von der Schemadefinition abhängig – es muss kein Attribut dafür definiert werden. Somit gibt es keine Wertzuweisungen, wie das bei Schlüsselwerten im relationalen Datenmodell der Fall ist. Die Objektidentität ist von allen Attributwerten unabhängig und kann durch keine Operation geändert werden. Nach Löschen eines Objektes darf seine OID auch nicht an ein anderes Objekt übergehen. Die Objektidentität ist nicht für Benutzer als Wert erkennbar, sie ist ein rein systeminternes Merkmal. Hier ist ein gravierender Unterschied zum relationalen Modell vorhanden, welches Bezüge auf der Basis von Werte-Gleichheit herstellt und nicht auf der Basis von Objekt-Identität. Daher muss für Objekte der Begriff der Gleichheit von dem Begriff der Identität unterschieden werden. Gleichheit beruht auf dem Vergleich der Attri-

319

Sandini Bib

9 Objektorientierung und SQL

butwerte von zwei Objekten, so dass zwei nicht identische Objekte in diesem Sinne »gleich« sein können.7 Die Rolle des Primärschlüssels, der bei relationalen Systemen Tupel identifiziert und die Verschiedenheit aller Tupel gewährleistet, wird damit entwertet. Gleichwohl kann es ein-eindeutige Attribute wie Kundennummern etc. geben, mit denen der Benutzer ein Objekt identifiziert.

9.1.7 Kapselung Objekte können nach außen hin »gekapselt« werden. Das bedeutet, dass ein direkter Zugriff von Benutzern respektive Anwendungsprogrammen auf die Attributwerte eines Objekts verwehrt ist. Kommuniziert wird mit Objekten ausschließlich über ihre Operationen (Methoden). Um den Namen der Dozenten von Seminaren zu erfahren, muss das Objekt Dozent eine Methode anbieten, die beispielsweise unter der Bezeichnung get_dozent aufgerufen werden kann und den geforderten Attributwert zurückliefert. Somit können Objekte zur Implementierung von abstrakten Datentypen verwendet werden. Dozent SELECT * FROM dozent WHERE kurs_nr = 1234 einstelle_dozent() versetze_dozent() get_dozent() ...

Methoden-Aufruf

Ergebnis

get_dozent( )

Petersen, Paul Matzen, Matthias Mäkinen, Tuula

Abbildung 9.4: Kapselung

Es ist aber möglich, spezielle Komponenten bei der Deklaration der Objektklasse als PUBLIC festzulegen. Der Zugriff auf solche Attribute kann dann in einer SQLähnlichen Sprache formuliert werden, so dass die Kapselung vom Benutzer gar nicht bemerkt wird.

7 Die Alltagssprache unterscheidet auch zwischen »dasselbe« (Identität) und »das Gleiche« (Gleichheit).

320

Sandini Bib

Objektorientierung im SQL-Standard

9.1.8 Lebenszeit von Objekten Zwei Lebenszeiten sind im Objektmodell vorgesehen, die bei der Anlage von Objekten angegeben werden müssen. Transiente Objekte sind an die Laufzeit des Programms gebunden, in dem sie erstellt werden. Sie verschwinden mit der Beendigung des Programms. Persistente Objekte werden durch das ObjektdatenbankManagementsystem verwaltet und existieren unabhängig von dem Programm, das sie ins Leben gerufen hat. Dieses sind die eigentlichen Datenbankobjekte.

9.1.9 Beziehungen Beziehungen werden zwischen Typen definiert. Das ODMG Objektmodell unterstützt nur Beziehungen zwischen zwei Typen. Im Entity Relationship Modell und in der UML sind auch mehr-stellige Beziehungen möglich. Kardinalitäten werden ebenso festgehalten wie im Entity Relationship Modell (vgl. Kapitel 3). Eine Beziehung ist selbst kein Objekt und hat keine Identität, sie dient lediglich dazu, einen Navigationspfad zwischen Objekten herzustellen und ermöglicht es Anwendungsprogrammen, die logischen Verbindungen zwischen Objekten verschiedener Klassen zu verfolgen. Die referenzielle Integrität wird durch das ODBMS gewährleistet. Die Definition von Beziehungen in Objektdatenbanken ist auf verschiedene Weise möglich. Wir zeigen in den Abschnitten 9.3 und 9.4 Beispiele dafür.

9.2 Objektorientierung im SQL-Standard Im SQL-Standard wird Objektorientierung nicht verstanden als ein neues Paradigma, das den alten, relationalen Ansatz ablöst, sondern als eine Erweiterung des Konzepts, das damit sozusagen »aufwärtskompatibel« zum relationalen Modell herkömmlicher Prägung ist. Dieser Ansatz wird als »objektrelational« bezeichnet. So erlaubt SQL die Konstruktion von Datentypen beliebig komplexer Struktur einschließlich der Definition von Methoden, also »abstrakte Datentypen«. Diese Datentypen können Attributen zugewiesen werden oder es können Objekttypen mit einer modifizierten Form der CREATE TABLE-Anweisung auf Basis eines Datentyps definiert werden. Die Implementierung eines Objekttyps ist immer eine Tabelle, wenngleich diese sich durch Attribute mit komplexer Struktur erheblich von einer »flachen« Tabelle, die die erste Normalform erfüllt, unterscheiden kann. Die »klassischen Tabellen«, wie wir sie in den übrigen Kapiteln des Buchs behandelt haben, sind nurmehr ein Spezialfall des erweiterten Konzepts.

9.2.1 Definition von Typen und Tabellen SQL unterstützt die Definition benutzerdefinierter Datentypen mit folgenden Eigenschaften: 왘 Ein Typ ist zusammengesetzt aus einem oder mehreren Attributen. 왘 Jedes Attribut hat einen Datentyp, wobei Standarddatentypen wie INTEGER

ebenso verwendet werden können wie nutzerdefinierte Datentypen. 321

Sandini Bib

9 Objektorientierung und SQL 왘 Das Verhalten eines Datentyps wird durch Methoden (Funktionen oder Proze-

duren) bestimmt. 왘 Die Komponenten (Attribute und Methoden) sind gekapselt. Der Zugriff erfolgt

über systemgenerierte Funktionen (»get and set functions« [EiMe99, S. 131]). 왘 Um Instanzen eines Typs zu erzeugen, muss der systemgenerierte Konstruktor

benutzt werden. Der Konstruktor hat denselben Namen wie der Typ. 왘 Wertvergleiche und eine Sortierung der Exemplare eines Typs erfolgen anhand

benutzerdefinierter Funktionen für Vergleiche und Sortierung. 왘 Typen können hierarchisch aufgebaut sein. Alle Subtypen erben die Attribute

und Methoden der Supertypen und können diese umbenennen, umdefinieren und durch eigene Komponenten erweitern. Es ist keine Mehrfach-Vererbung vorgesehen. Ein Subtyp kann in der Regel dort verwendet werden, wo sein Supertyp erwartet wird. Die SQL-Anweisung zum Anlegen eines abstrakten Datentyps lautet in vereinfachter Form: CREATE value_or_object TYPE typname [UNDER supertyp] [AS (attributliste)] [methodendeklarationsliste] value_oder_objekt ::= VALUE | OBJECT

Durch VALUE bzw. OBJECT wird festgelegt, ob der Typ instanziierbar ist, d.h. ob auf seiner Basis Objekttabellen erzeugt werden können. Ansonsten ist nur die Verwendung als Datentyp von Attributen möglich. Wenn ein Supertyp angegeben ist, erbt der aktuelle Datentyp dessen Attribute und Methoden. Zu jedem Element der Attributliste wird Name und Datentyp angegeben. Der Datentyp eines Attributs kann selbst wieder ein nutzerdefinierter Datentyp sein. Die Methodendeklaration enthält nur die Signatur, d.h. den Namen der Methode, die Eingabeparameter und den Datentyp des Rückgabewerts. Ein kleines Beispiel8 möge zunächst die Syntax erläutern. In Abschnitt 9.3 stellen wir ein ausführlicheres Beispiel vor, das dort allerdings vom Standard abweicht, da wir es unter Oracle9 erstellt haben. CREATE OBJECT TYPE otyp_angestellter UNDER otyp_person AS ( angest_nr INTEGER, gehalt DECIMAL(7,2)), INSTANCE METHOD gehaltserhoehung ( abs_oder_prozent BOOLEAN, betrag DECIMAL (7,2) RETURNS DECIMAL (7,2);

8 Angelehnt an [EiMe99, S. 134].

322

Sandini Bib

Objektorientierung im SQL-Standard

Hier wird ein Typ für Angestellte als Subtyp von otyp_person eingerichtet, der seinerseits zuvor deklariert worden sein muss, und den wir hier einfach unterstellen. Die Attribute angest_nr und gehalt ergänzen die Attribute des Typs otyp_person. Die Methode gehaltserhoehung kann von außen aufgerufen werden. Von dieser Methode sehen wir hier nur die Signatur, aus der hervorgeht, dass man einen Booleschen Wert zu übergeben hat, der festlegt, ob die Gehaltserhöhung um einen absoluten Geldbetrag oder prozentual erfolgt. Der Rückgabewert ist eine Zahl vom Typ DECIMAL(7,2), das neue Gehalt. Die Implementierung der Methode ist hier nicht sichtbar. Sie erfolgt mit prozeduralen Sprachelementen von SQL9.

Tabellendefinition auf Typbasis Benutzerdefinierte Typen, die mit dem Zusatz OBJECT angelegt wurden, können zur Definition von Tabellen verwendet werden. Der entsprechende Befehl lautet: CREATE TABLE tabelle OF typ

Dabei übernimmt die Tabelle alle Attribute und Methoden des Typs. Jedes Typattribut wird in eine Tabellenspalte übernommen. Da der Datentyp eines Attributs selbst wieder ein komplexer Typ sein kann, ist die Vorstellung von einer Tabelle als zweidimensionale Struktur von Zeilen und Spalten, wobei jede Zelle am Schnittpunkt von Zeile und Spalte einen skalaren Wert aufweist, allerdings überholt – er kann auch mehrwertig sein. Die erste Normalform ist somit nicht mehr notwendig. Dennoch werden die Begriffe Zeile, Spalte und Tabelle beibehalten. Jede Zeile in der typisierten Tabelle stellt eine Instanz des Objekttyps dar. Sie erhält automatisch eine systemgenerierte OID (»object identifier«), der von den Attributwerten unabhängig ist und vom Nutzer nicht geändert werden kann.

9.2.2 Konstruktoren für komplexe Typen Spezielle Konstruktoren sind für die Erzeugung von »collection types« vorgesehen (vgl, Abschnitt 9.1.2). SQL sieht die Konstruktoren ARRAY und MULTISET vor. MULTISET haben wir in 9.1.2 als bag eingeführt.

Beispiel: Eine Rundreise, die über bis zu 12 Orte geht und mehrere Teilnehmer hat, kann folgende Attribute enthalten: teilnehmer otyp_person MULTISET, stationen otyp_ort ARRAY[12]

9 Vgl. Kapitel 7.3

323

Sandini Bib

9 Objektorientierung und SQL

Die Schachtelung der Konstruktoren wie beispielsweise INTEGER ARRAY[6] MULTISET ist erlaubt. Als Datentypen kommen auch nutzerdefinierte in Frage. Wir können daher beispielsweise einen Objekttyp abteilung_typ definieren, der seine Angestellten enthält, indem wir folgende Attributspezifikation vornehmen: CREATE OBJECT abt_nr abt_name angestellte ... )

TYPE abteilung AS INTEGER, VARCHAR(20), otyp_angestellter MULTISET,

Ausprägungen der drei Kollektionstypen können auch leer sein. Ein weiterer Konstruktor, ROW, dient der Definition von Tupeln als Datentyp. Demnach hat eine herkömmliche SQL-Tabelle den Typ ROW(attributliste) MULTISET.

Diese Strukturen umgehen Einschränkungen des relationalen Modells, die sich aus der Verpflichtung auf die erste Normalform ergeben (Kapitel 3.4). Im Resultat führt dort die Notwendigkeit zur Ausgliederung von Wiederholungsgruppen zur Verteilung zusammengehöriger Daten auf mehrere Tabellen. Im objektorientierten Modell können wir eine Menge von Tupeln als Einzelattribut in einen Objekttyp einbinden.

9.2.3 Referenzen Nachdem im objektorientierten Konzept die Identifizierung von Objekten über die systemverwaltete OID erfolgt und nicht über dessen (veränderliche) Attributwerte, hat konsequenterweise der Fremdschlüssel für den Bezug auf ein fremdes Objekt ausgedient. Bezüge werden über die OID hergestellt. Die Einbindung einer »fremden« OID in ein Objekt geschieht sozusagen als Referenz auf das fremde Objekt. Das Attribut, das diese Referenz enthält, wird mit folgendermaßen definiert: attribut REF (fremder_objekt_typ)

Beispielsweise kann in einer Bibliotheksverwaltung der Ausleiher eines Buchs als Bestandteil der Definition eines Buchtyps folgendermaßen festgehalten werden: CREATE OBJECT TYPE otyp_buch AS (signatur VARCHAR(12), ausleiher REF otyp_person, ....

Wenn nun eine Objekttabelle CREATE TABLE Buch OF otyp_buch

angelegt wird, enthält diese als Attribut die Referenz auf ein in einer anderen Tabelle gespeichertes Objekt vom Typ person_typ.

324

Sandini Bib

Objektrelationales Modell der Versanddatenbank

Der Zugriff auf die Attribute des eingebetteten Typs erfolgt nunmehr im Vergleich zum Join bei der relationalen Modellierung über die »Punktnotation«. Wenn wir von obigem Beispiel ausgehen, erfahren wir den Namen des Ausleihers über den Ausdruck buch.ausleiher.name

Die Aufnahme eines Referenztyps in eine Tabelle setzt die selbständige Existenz des referenzierten Typs mit eigenem Extent10 (Objekttabelle) voraus. Eine Wertzuweisung kann auch nur dann erfolgen, wenn die gewünschte Instanz des referenzierten Typs in der Datenbank vorhanden ist. So wird in der objektorientierten Welt die referenzielle Integrität realisiert. Im Unterschied dazu ist die Einbettung von Tupeln in eine Objekttabelle über die Typzuweisung freunde otyp_person MULTISET

so zu verstehen, dass die Personen, die in dieses Attribut eingetragen werden, nur als Attributwerte des Tupels existieren. Dies entspricht dem Konzept des abhängigen Entitätstyps, das wir in Kapitel 3.2 vorgestellt haben. Sie werden auch nicht getrennt erfasst, sondern bei der Instanziierung des sie enthaltenden Typs zusammen mit den anderen Attributwerten angegeben.

9.3 Objektrelationales Modell der Versanddatenbank Es folgen nun Beispiele für die im vorigen Abschnitt vorgestellten Modellelemente. Wir realisieren das in folgendem UML-Diagramm wiedergegebene objektorientierte Modell der Versand-Datenbank.11 Die Umsetzung der Beispiele folgt nicht dem Standard, wir haben sie mit einem Oracle9-DBMS erstellt und getestet. Es gibt eine Reihe von Abweichungen zwischen Oracle und dem Standard12; deren bedeutendste sind: 왘 Die Kollektionstypen, die zur Zeit unterstützt werden, sind TABLE (entspricht MULTISET(ROW))und VARRAY. Ein VARRAY ist im wesentlichen ein Array mit einer jeweils vorgegebenen Maximalzahl von Komponenten; es kann aber auch weniger Komponenten enthalten.

10 Ein Extent für einen Typ ist an eine Objekttabelle gebunden. Typen ohne Extent sind auch möglich; dieses ist z.B. sinnvoll für einen Typ für Adressen. 11 UML wird in Kapitel 3 beschrieben. 12 Siehe auch [CHRS98, S. 420ff.].

325

Sandini Bib

9 Objektorientierung und SQL

Abbildung 9.5: UML-Diagramm der Versand-Datenbank – objektorientiert 왘 Oracle bietet zur Formulierung von Methoden eine eigene Programmierspra-

che an, deren Syntax von SQL/PSM-Sprache abweicht. Sie ist als prozedurale Erweiterung von SQL entwickelt worden und heißt PL/SQL. Daneben können Methoden auch mit Java entwickelt werden. Daneben fällt auf, dass die unterstützten Möglichkeiten objektorientierter Datenmanipulation mittels SQL nicht orthogonal realisiert sind. Das bedeutet: nicht überall, wo es theoretisch sinnvoll ist, auf einen Typ und seine Methoden zuzugreifen, ist es auch möglich.

Namenskonventionen Die erweiterten Möglichkeiten, die wir durch die Definition von Datentypen erhalten, bedingen gleichzeitig eine gesteigerte Vielfalt an Namen. Und weil es häufig notwendig ist, den Typkonstruktor beim Zugriff auf Attribute anzuwenden, kommt einer sauberen Unterscheidung von Typnamen, Attributbezeichnern und Objektnamen Bedeutung zu. Wir wenden in diesem Kapitel folgende Notationsrichtlinien an:

326

Sandini Bib

Objektrelationales Modell der Versanddatenbank

Datenstruktur Name vorangestellt --------------------------------------------Object Type names otyp_ Varray Names varr_ Nested Table Types ntyp_ Object Tables otab_ Relational Tables rtab_ Nested Table ntab_ Object View ov_ Local Variables lvar_ Input Parameters ip_ Output Parameters op_ Input-Output Parameters iop_

9.3.1 Abstrakte Datentypen als Wertebereich für Attribute In diesem Abschnitt geht es zunächst um Datentypen, die als Basis bei der Deklaration von Attributen und Variablen verwandt werden. Der SQL Standard stellt dafür beispielsweise INTEGER, REAL und VARCHAR zur Verfügung. In Kapitel 4 haben wir behandelt, wie man mit dem Befehl CREATE DOMAIN eigene Datentypen als Domänen definieren kann. Die so erzeugten Domänen stellen aber im Grunde nichts anderes als einen Standard-Datentyp mit einer zusätzlichen Einschränkung des Wertebereichs dar. Dabei fehlt bisher eine Möglichkeit, die Funktionalität eines solchen Typs zu definieren. Zu einem abstrakten Datentyp gehört aber auch die Festlegung seines Verhaltens, seiner Vergleichbarkeit und der sonstigen Operationen, die mit ihm ausgeführt werden können. Wir definieren zunächst einen abstrakten Datentyp für Kundennummern. Das Verhalten dieses Typs ist relativ simpel: er soll in der Lage sein, eine neue fortlaufende Nummer zu erzeugen. Wir erzeugen den Typ zunächst nur mit der Signatur der Methode. CREATE OR REPLACE TYPE otyp_kunden_key AS OBJECT ( kunden_key number (4,0), STATIC FUNCTION neuer_kunden_key RETURN otyp_kunden_key ) ; /

Die Methode wird mit der Klausel STATIC FUNCTION angekündigt, ihr Name und gegebenenfalls ihre Parameter sowie der Ausgabe-Datentyp – hier ein Objekt vom Typ otyp_kunden_key – werden festgelegt. Der Zusatz STATIC besagt, dass diese Methode nicht objektbezogen arbeitet, sondern für die gesamte Klasse ein einziges Mal vorhanden ist. Dies ist hier richtig, da die Erzeugung einer neuen Nummer gleichzeitig mit der Erzeugung eines neuen Objekts vom Typ otyp_kunden_key passiert. Für eine objektbezogene Methode (MEMBER FUNCTION) müsste erst ein Objekt existieren, das diese dann ausführen kann. Mit dem obigen Befehl ist die Schnittstelle

327

Sandini Bib

9 Objektorientierung und SQL

definiert. Ein Benutzer, der mit diesem Typ arbeiten will, muss lediglich diese Schnittstelle kennen, aber nicht die Implementierung. Diese wird nun vorgenommen: CREATE OR REPLACE TYPE BODY otyp_kunden_key AS STATIC FUNCTION neuer_kunden_key RETURN otyp_kunden_key IS nextnum number (4,0); BEGIN SELECT sq_kunden_nr.nextval INTO nextnum FROM dual; RETURN otyp_kunden_key(nextnum); END; END;

Die ersten beiden Zeilen wiederholen nur die Signatur der Funktion. Im Implementierungsteil wird zunächst eine lokale Variable definiert, die die nächste erzeugte Nummer aufnehmen soll. Diese wird erzeugt durch eine Instanz des Oracle-eigenen Objekttyps SEQUENCE, der im Grunde selbst einen abstrakten Datentyp vorstellt und die Methoden nextval und currval kennt. Diese Instanz haben wir außerhalb der Definition von otyp_kunden_key angelegt13 und sq_kunden_nr genannt. Interessant ist noch die Zeile RETURN otyp_kunden_key(lvar_nextnum)

Hier wird eine Instanz des soeben definierten Typs erzeugt. Wir müssen dazu den Konstruktor benutzen, der den Namen des Typs selbst trägt. Man merkt an dieser Stelle, dass das Typkonzept in dieser Form zur Disziplin zwingt. Eine Nummer ist nicht mehr einfach eine Nummer; wenn es eine Kundennummer sein soll, muss man Typnamen mit angeben, wenn man den Wert übergeben will. Wir erzeugen nun einen Basistyp mit Struktur. In jeder Adresse kommen immer wieder die Angaben strasse, plz, ort vor. Warum nicht einfach einen Typ Adresse definieren, der diese Attribute als Komponenten enthält? CREATE OR REPLACE TYPE otyp_adresse AS OBJECT ( strasse varchar2(30), plz varchar2(5), ort varchar2(30));

Der nächste Typ wird als VARRAY (VARYING ARRAY) deklariert, eine Struktur, die eine von vornherein beschränkte Anzahl gleichartiger Werte aufnehmen kann. Angesichts der um sich greifenden Kommunikationstechnik könnten 5 Telefonnummern pro Person nützlich sein. CREATE TYPE varr_telefonliste AS VARRAY (5) OF VARCHAR2(20); 13 Der Befehl lautet: CREATE SEQUENCE sq_kunden_nr START WITH 100 INCREMENT BY 1. Die hier vorgestellten Befehle sind als SQL-Skripte auf der CD im Verzeichnis \...\OracleOO zu finden. Hier geht es gerade um das Skript crykunde0.

328

Sandini Bib

Objektrelationales Modell der Versanddatenbank

Bei den letzten beiden Typen brauchen wir uns nicht weiter mit der Definition von Methoden zu beschäftigen. Es reicht aus, dass wir Exemplare dieser Typen erzeugen und darstellen können. Dazu genügen die Standardmethoden, die SQL gleich mitliefert. Beide Typen sind im übrigen ein Affront gegen die erste Normalform für Relationen (siehe Kapitel 3)!

9.3.2 Komplexe Objekttypen und Objekttabellen Wir zeigen nun, wie die oben definierten abstrakten Datentypen (ADT) bei der Einrichtung eines komplexen Objekttyps verwendet werden können. Unsere bekannte Kundenrelation haben wird in Kapitel 4 mit dem Befehl CREATE TABLE angelegt. Hier wird nun zunächst ein Objekttyp erzeugt, der dann als Basis für eine Objekttabelle dient. CREATE OR REPLACE TYPE otyp_kunde0 AS OBJECT ( kunden_nr otyp_kunden_key, status varchar2(1), name varchar2(30), telefonliste varr_telefonliste, adresse otyp_adresse, letzte_bestellung date, letzte_werbeaktion date, zahlungsart char(1));

Wir benutzen hier die im vorigen Abschnitt definierten ADTs als Typangabe für die Attribute kunden_nr, telefonliste, adresse. An dieser Stelle können keine Integritätsbedingungen angegeben werden. UNIQUE-Klauseln und ähnliches sind auf Typebene nicht gestattet. Wir müssen trotzdem nicht ganz auf sie verzichten, da wir beim Einrichten einer Objekttabelle darauf zurückkommen können. Hierauf gehen wir später ein. Die Struktur des Objekttyps otyp_kunde ist nun definiert. Hätten wir Methoden mit angegeben, so müssten diese anschließend implementiert werden. Um den Typen zu instanziieren, benötigen wir einen Behälter (Extent), die die Objekte aufnehmen kann. Hier liegt der wesentliche Unterschied zwischen objektorientierten und objektrelationalen Datenbanken: der Behälter für Objekttypen ist eine Tabelle. Die CREATE TABLE-Anweisung kommt in neuer Form daher, um solche typisierten Tabellen zu erstellen: CREATE TABLE otab_kunde0 OF otyp_kunde0 ( status NOT NULL, CHECK (status IN ('S','W','G')), adresse NOT NULL, zahlungsart NOT NULL, CHECK (zahlungsart in ('R','B','N','V','K')) )

329

Sandini Bib

9 Objektorientierung und SQL

Hier werden, wie man sieht, die altbekannten Integritätsbedingungen (vgl. Kapitel 4) formuliert.14 Nicht auf der Ebene der Typ-Definition werden diese festgelegt, sondern auf der Ebene der Definition von Extents.15 Das führt zu einem Konflikt. Legen wir bei der Kundennummer Wert darauf, dass sie die Fähigkeit hat, selbst fortlaufende Nummern zu erzeugen und nicht mit Artikelnummern vergleichbar zu sein oder legen wir Wert darauf, dass die Primärschlüsseleigenschaft festgehalten wird? Letztere brauchen wir zwar in Objektorientierten Datenbanken nicht wegen der Entitätsintegrität – die OID ist ein besserer Ersatz für den Primärschlüssel. Als Anwender wollen wir aber vielleicht doch nicht die identifizierende Funktion der Kundennummer missen. Beides zugleich geht jedenfalls nicht so ohne weiteres. Die PRIMARY KEY-Klausel ist zwar für Objekttabellen erlaubt, aber nicht für Attribute, deren Basis ein ADT ist!16 Dies ist ein Beispiel für die derzeit mangelnde Orthogonalität dieser objektrelationalen SQL-Implementierung. Wenn wir auf die Deklaration eines Schlüssels nicht verzichten wollen, müssen wir wohl oder übel als Wertebereich für Kunden_nr den Standarddatentyp NUMBER(4,0) einsetzen, und können dann die Anweisung CREATE TABLE otab_kunde um die Klausel CONSTRAINT pk_kunde PRIMARY KEY (kunden_nr),

ergänzen.17 Die Verwendung von ADTs als Wertebereich für Attribute erfordert, wie wir bereits oben (Seite 327) gezeigt haben, Sorgfalt im Hinblick auf die Verarbeitung ihrer Werte. Wir können beim Einfügen eines Kundentupels in die neue Tabelle nicht einfach drei Strings als Adresse übergeben, sondern müssen als Attributwert jeweils ein Objekt vom Typ otyp_kunden_key und otyp_adresse konstruieren und diese komplett verarbeiten. Gleiches gilt für die Telefonliste. INSERT INTO otab_kunde0 (kunden_nr, name, telefonliste, adresse, letzte_bestellung, letzte_werbeaktion, status, zahlungsart) VALUES (otyp_kunden_key.neuer_kunden_key(), 'Voss, Hans', varr_telefonliste('0421-3499483','0170-3421808'), otyp_adresse('Kuhdamm 12','23863', 'Nienwohld'),NULL, TO_DATE('01-12-1999','DD-MM-YYYY'),'S','N')

14 Es werden aber keine Einschränkungen außer NOT NULL für Spalten, deren Typ ein Objekt, eine eingebettete Tabelle, VARRAY, REF oder LOB ist, akzeptiert [ORA01a, S 11-73]. 15 Wir halten es für einen Mangel des objektorientierten Datenmodells, dass Integritätsbedingungen nicht deklarativ auf Typebene formulierbar sind. Es müssen dafür jeweils Methoden definiert werden, die beim Einfügen oder Ändern einer Objektinstanz die Einhaltung von Bedingungen überprüfen. Eine recht umständliche Angelegenheit! Darüber hinaus ist das Redefinieren eines Typ-Konstruktors vielfach im objektrelationalen Modell nicht möglich. 16 Vgl. [Ora01a, S. 11-81]. 17 In den Beispielen auf der CD verwendet das Skript crykunde.sql die Variante mit »normalem« Datentyp und PRIMARY KEY-Klausel.

330

Sandini Bib

Objektrelationales Modell der Versanddatenbank

Wir haben im relationalen Modell unserer Versand-Datenbank (vgl. Kapitel 3) die Einrichtung einer eigenen Tabelle für die Mehrwertsteuersätze als zweckmäßig erachtet. Diese Sätze ändern sich nicht sehr häufig und kommen immer wieder bei jedem Verkauf eines Artikels zur Anwendung. Aus demselben Grund ist auch die Einrichtung einer eigenen Objekttabelle für die Mehrwertsteuer im objektrelationalen Modell sinnvoll. Wir zeigen an dieser Variante einer Typdefinition die Möglichkeit, eine eigene Methode für die Sortierung einzurichten (wobei dieses Beispiel nicht sehr kompliziert ist, anders z.B. bei Multimedia- oder Geografie-Daten). Weiter enthält dieses Beispiel einen Konstruktor, um ein neues Objekt zu erzeugen und dabei auf die Einhaltung des Wertebereichs für den Schlüssel zu achten. Leider kann der Standardkonstruktor, der den Namen des Typs hat, nicht überschrieben werden, so dass wir hier einen eigenen Namen vergeben müssen. Der Konstruktor ist eine STATIC-Funktion, da er nur einmal für die ganze Klasse existiert, die Sortierfunktion wird hingegen als MEMBER-Funktion eingerichtet, da sie für jedes Objekt einmal ausgeführt werden muss. CREATE OR REPLACE TYPE otyp_mwstsatz AS OBJECT ( mwst integer, prozent number (3,3), beschreibung varchar2(10), -- Mit der MAP-Funktion wird eine Sortierung ermoeglicht MAP MEMBER FUNCTION mwst_order RETURN REAL, PRAGMA RESTRICT_REFERENCES (mwst_order, RNDS, WNDS, RNPS, WNPS), STATIC FUNCTION construct_mwst (in_mwst IN INTEGER, in_prozent IN NUMBER, in_beschreib IN VARCHAR2) RETURN otyp_mwstsatz -In der Parameterliste von Funktionen haben Variablen -bei PL/SQL keine Laengenangabe );

Die Implementierung der Methoden erfolgt separat. CREATE OR REPLACE TYPE BODY otyp_mwstsatz AS MAP MEMBER FUNCTION mwst_order RETURN REAL IS BEGIN RETURN prozent; -- Unqualified attributes refer to the "self" object. END mwst_order; STATIC FUNCTION construct_mwst (in_mwst IN INTEGER, in_prozent IN NUMBER, in_beschreib IN VARCHAR2) RETURN otyp_mwstsatz IS

331

Sandini Bib

9 Objektorientierung und SQL

BEGIN -- Constraints implementieren IF in_mwst < 0 THEN DBMS_OUTPUT.PUT_LINE ('Mwst-Schluessel muss >=0 sein'); raise_application_error (-1,'Wertfehler bei mwst',FALSE); ELSE RETURN otyp_mwstsatz(in_mwst,in_prozent,in_beschreib); END IF; END construct_mwst; END;

Die MAP-Funktion bildet ein Objekt vom Typ otyp_mwstsatz auf eine Zahl ab. Die Abbildungsvorschrift wird mit der Implementierung festgelegt. Wir haben hier einfach den Prozentsatz genommen. Es könnte aber jeder beliebige numerische Ausdruck sein, der sich beispielsweise bei einer geometrischen Figur aus einer mehr oder weniger komplizierten Flächenberechnung ergäbe. Die Definition dieser Methode eröffnet uns die Möglichkeit, bei der Ausgabe der Tupel mit der ORDER BY VALUE-Klausel eine Standardsortierung anzufordern. SELECT * FROM otab_mwstsatz m ORDER BY VALUE(m);

Die Angabe PRAGMA RESTRICT_REFERENCES (mwst_order, RNDS, WNDS, RNPS, WNPS),

ist eine »Compiler-Direktive«. Sie ist notwendig, um »Seiteneffekte« zu kontrollieren und besagt, dass weder Datenbank-Zustände gelesen oder verändert werden noch Prozedurvariablen. Wir beschäftigen uns mit diesen mehr technischen Dingen hier nicht weiter. Der Bezeichner self zeigt zur Laufzeit auf das Objekt (Exemplar), bei dessen Bearbeitung die Methode aufgerufen wurde. Wir erzeugen eine Objekttabelle auf Basis des Typen: CREATE TABLE otab_mwstsatz OF otyp_mwstsatz ( mwst NOT NULL, prozent NOT NULL, CONSTRAINT pk_mwstsatz PRIMARY KEY (mwst) )

In diese können wir nun Tupel mit Hilfe des Konstruktors einfügen, z.B: INSERT INTO otab_mwstsatz VALUES (otyp_mwstsatz.construct_mwst(1,.07,'halbe'))18

332

Sandini Bib

Objektrelationales Modell der Versanddatenbank

9.3.3 Vererbung Das UML-Diagramm am Anfang des Abschnitts 9.3 enthält eine Spezialisierungsbeziehung zwischen Kunde und Kunde_mit_Bankeinzug. Der Subtyp enthält zusätzliche Attribute. Da eine Bankverbindung immer dieselben Attribute hat, können wir verfahren wie bei der Adresse und dafür einen eigenen Typen einführen. CREATE OR REPLACE TYPE otyp_girokonto AS OBJECT ( konto_inhaber varchar2(30), blz varchar2(8), kontonr varchar2(10) );

Der Typ für Kunden mit Bankeinzug wird nun als Subtyp erzeugt, indem man mit der Klausel UNDER den Obertypen19 referenziert und ansonsten nur die zusätzlichen Attribute (und gegebenenfalls Methoden) spezifiziert. CREATE OR REPLACE TYPE otyp_kunde_mit_bankeinzug UNDER otyp_kunde ( bankverbindung otyp_girokonto );

Um einen Extent zu erzeugen, der Kunden und Kunden mit Bankverbindung als Objekte speichern kann, lässt sich nun ausnutzen, dass Objekte einer Unterklasse immer zugleich Objekte der Oberklasse sind. Das bedeutet, dass es nicht notwendig ist, eine eigene Extent-Tabelle für Kunden mit Bankverbindung anzulegen.20 Der Extent für Kunden wird angelegt, wobei wir mit der Klausel SUBSTITUTABLE AT ALL LEVELS verlangen, dass immer dann ein Subtyp von otyp_kunde verwendet werden darf, wo ein Kunde gefragt ist. CREATE TABLE otab_kunde OF otyp_kunde SUBSTITUTABLE AT ALL LEVELS ( CONSTRAINT pk_kunde PRIMARY KEY (kunden_nr), status NOT NULL, CONSTRAINT chk_status 18 Dieses Beispiel ist mit in den Skriptdateien cryartikel.sql und insartikel.sql auf der CD enthalten. Beide befinden sich im Unterverzeichnis \...\OracleOO. 19 Wir haben hier den Obertypen otyp_kunde angegeben. Dieser hat gegenüber dem Beispiel otyp_kunde0, das wir im vorigen Abschnitt besprochen haben, ein skalares Attribut als Kundennummer. Bei der Anlage der Objekttabelle otab_kunde kann man dann deklarativ einen Primärschlüssel erzeugen: CREATE OR REPLACE TYPE otyp_kunde AS OBJECT (kunden_nr

number (4,0),

...) Auf der CD befindet sich dieses Beispiel im Skript crykunde.sql. 20 Es wäre zwar möglich, dies zu tun, dann würde der Extent von otyp_kunde aber nicht die Objekte von otyp_kunde_mit_Bankverbindung enthalten, im Widerspruch zum Prinzip, dass Objekte der Unterklasse Objekte der Oberklasse sind.

333

Sandini Bib

9 Objektorientierung und SQL

CHECK (status IN ('S','W','G')), adresse NOT NULL, zahlungsart NOT NULL, CONSTRAINT chk_zahlart CHECK (zahlungsart in ('R','B','N','V','K')) );

Wir fügen nun zwei Tupel in die Objekttabelle otab_kunde ein, eines ohne und eines mit Bankverbindung. Beim zweiten Mal müssen wir unbedingt den Konstruktor für otyp_kunde benutzen, da dieser prinzipiell auch als Methode an die Unterklasse vererbt wird. Sonst würde eine Fehlermeldung erzeugt, die angibt, dass die VALUES-Klausel des INSERT-Befehls mehr Spalten enthält als die Tabelle. INSERT INTO otab_kunde -- wuerde auch ohne den Konstruktor funktionieren VALUES (otyp_kunde(100, 'S','Voss, Hans', varr_telefonliste('0421-3499483','0170-3421808'), otyp_adresse.construct_adresse( 'Kuhdamm 12','23863','Nienwohld'), NULL, TO_DATE('01-12-1999','DD-MM-YYYY'),'N') ) / INSERT INTO otab_kunde -- funktioniert nicht ohne Konstruktor, da sonst zu viele Spalten VALUES (otyp_kunde_mit_bankeinzug(101,'S','Stein, Peter', varr_telefonliste('04523-3456'), otyp_adresse.construct_adresse( 'Moordamm 34','23863','Kayhude'), TO_DATE('28-04-2000','DD-MM-YYYY'), TO_DATE('01-12-1999','DD-MM-YYYY'),'B', otyp_girokonto('Dagmar Stein', '23410022','123456789')) ) /

Abfragen von Daten aus einer Objekttabelle behandeln wir wenig später in Abschnitt 9.3.5.

9.3.4 Referenzen Die Beziehung zu einem Objekt eines eigenständigen Objekttyps wird durch eine »Referenz« hergestellt21. Implizit wird dafür die OID genutzt, der Nutzer hat 21 In imperativen Programmiersprachen wie Pascal, C, C++ entspricht das im Wesentlichen einem Pointer bzw. einer Adresse.

334

Sandini Bib

Objektrelationales Modell der Versanddatenbank

jedoch damit nichts zu tun. Voraussetzung für die Referenzierbarkeit eines Objekttyps ist, dass ein Extent in Form einer Objekttabelle erzeugt worden ist. Die Einbindung einer Referenz in eine Typdefinition geschieht über ein Attribut (»Referenzattribut«). Dessen Typ wird auf folgende Weise angegeben: referenzattribut

REF objekttyp

Wir nutzen dieses Konstrukt, um einen Objekttyp für Artikel zu erzeugen, der eine Referenz auf den zugehörigen MwStSatz enthält.22 CREATE OR REPLACE TYPE otyp_artikel AS OBJECT ( artikel_nr varchar2(4), mwst REF otyp_mwstsatz, bezeichnung varchar2(15), listenpreis number(8,2), bestand number(5,0), mindestbestand number (5,0), verpackung varchar2(15), lagerplatz number(2,0), kann_wegfallen number(1,0), bestellvorschlag date, nachbestellung date, nachbestellmenge number(5,0), MEMBER FUNCTION get_mwst RETURN REAL, PRAGMA RESTRICT_REFERENCES (get_mwst, WNDS, WNPS) -- moegl. Methoden: -init_nachbestellung, entferne_aus_lager, -neue_artikel_nr, preiserhoehung );

Wir haben eine Methode angegeben, die den MwStSatz eines Artikels zurückgibt. Die Implementierung überlassen wir als Übung dem Leser.23 Wie in den vorherigen Fällen richten wir als Extent eine Tabelle ein, zu der dann auch die Integritätsbedingungen so formuliert werden, wie wir es bei der relationalen Fassung auch getan haben. CREATE TABLE otab_artikel OF otyp_artikel ( CONSTRAINT pk_artikel PRIMARY KEY (artikel_nr), CONSTRAINT nn_mwst mwst NOT NULL, CONSTRAINT nn_bezeichnung bezeichnung NOT NULL, CONSTRAINT nn_listenpreis listenpreis NOT NULL, CONSTRAINT nn_bestand bestand NOT NULL, CONSTRAINT chk_bestand CHECK (bestand >= 0), 22 Dieses und alle anderen Beispiele sind in vollständiger Ausführung auf der CD im Unterverzeichnis \...\OracleOO enthalten. 23 In der Datei cryartikel auf der CD findet sich die Lösung.

335

Sandini Bib

9 Objektorientierung und SQL

CONSTRAINT nn_mindestbestand mindestbestand NOT NULL, CONSTRAINT chk_mindestbestand CHECK (mindestbestand >= 0), CONSTRAINT chk_nachbestell CHECK (nachbestellmenge >= 0) -- FOREIGN KEY entfaellt wegen Einbindung mwst als REF-Typ );

Beim Einfügen von Tupeln muss, wie wir bereits gesehen haben, der Typ der Attribute respektiert werden, was bei ADTs den Einsatz des Konstruktors erfordert. Der Konstruktor für den MwstSatz heißt in unserem Fall REF und muss sich auf ein konkretes Objekt vom Typ otyp_mwstsatz beziehen. Dies macht eine Abfrage erforderlich, weil wir auf andere Weise keine Referenz auf ein Mwst-Objekt erzeugen können. Alle anderen Attribute müssen dabei als Konstante mit angegeben werden. INSERT INTO otab_artikel (Artikel_Nr, Verpackung, Bezeichnung, Lagerplatz, Bestand, Mindestbestand, Listenpreis, MWST) SELECT 'G001','0,7 l','Whisky',7,397,50,38.50, REF(m) FROM otab_mwstsatz m WHERE m.mwst = 2

Mit der obigen Einfügeabfrage wird für das Attribut MWST die OID des Objekts mit dem Schlüsselwert mwst = 2 eingetragen.

9.3.5 Abfragen Für die Abfrage einer Objekttabelle steht zunächst einmal der SELECT-Befehl in seiner bekannten Form zur Verfügung. Allerdings sind die Resultate nicht unbedingt sehr leserlich, wenn man in der Projektionsangabe den Namen eines nichtskalaren Attributs angibt. Zum Beispiel liefert die Abfrage des Attributs mwst der Tabelle otab_artikel eine Ausgabe der folgenden Art: 0000220208A456CA777B2811D3A9080000E867DD32A456CA437B2811D3A

Abgesehen davon, dass man die OID eigentlich als Nutzer nicht sehen sollte, ist das natürlich keine Aussage von Wert. Man muss daher, um die Mehrwertsteuerangaben eines Artikels im Klartext zu sehen, die Referenz auflösen, sozusagen ersetzen durch das konkrete Objekt, auf das sie zeigt. Dafür gibt es den Operator DEREF SELECT artikel_nr, verpackung, bezeichnung, DEREF(mwst) FROM otab_artikel;

In der Antwort werden nicht einfach die Werte des entsprechenden Tupels der Mehrwertsteuer-Tabelle ausgegeben, sondern dies geschieht mit vorangestellten Typbezeichnern in Klammern. Auch hier sieht man, dass das objektrelationale Modell sehr genau Typen und Werte unterscheidet.

336

Sandini Bib

Objektrelationales Modell der Versanddatenbank

ARTIKEL_NR VERPACKUNG BEZEICHNUNG ---------- --------------- --------------DEREF(MWST)(MWST, PROZENT, BESCHREIBUNG) ------------------------------------------------------------------------------G001 0,7 l Whisky OTYP_MWSTSATZ(2, .16, 'volle') G002 0,5 l Portwein OTYP_MWSTSATZ(2, .16, 'volle') G003 6er Pack Bier OTYP_MWSTSATZ(2, .16, 'volle') K001 Karton Schuhe OTYP_MWSTSATZ(2, .16, 'volle') ...

Interessant ist aber die Möglichkeit, die wir im Folgenden vorstellen. Die Einbettung eines Verweises auf ein Tupel der Mehrwertsteuer-Tabelle über eine Referenz macht den Zugriff auf seine Attribute quasi als Eigenschaft eines Artikels möglich. Dazu dient die sogenannte »Punktnotation«. SELECT a.artikel_nr, a.mwst.prozent from otab_artikel a WHERE a.mwst.prozent = 0.16; ARTIKEL_NR MWST.PROZENT ---------- -----------G001 ,16 G002 ,16 G003 ,16 K001 ,16 K002 ,16 K003 ,16 L004 ,16 L005 ,16...

Im Ausdruck a.artikel_nr wird – wie von der relationalen Datenmanipulation her bekannt – kundgetan, dass artikel_nr ein Attribut der Tabelle otab_artikel mit dem Alias a ist. Der Ausdruck a.mwst.prozent gibt an, dass prozent ein Attribut von mwst und mwst ein Attribut von a ist. Gegenüber der oft recht aufwendigen Formulierung eines Joins ist der Zugriff hier eindeutig erleichtert. Man bezeichnet diese Art auch als »navigierenden Zugriff«, da man über ein Objekt »einsteigt« und über die von ihm ausgehenden Referenzen zu anderen Objekten hin »navigiert«.

337

Sandini Bib

9 Objektorientierung und SQL

Die Objekte von Kunden mit Bankverbindung waren in Abschnitt 9.3.3 in die Objekttabelle für Kunden eingefügt worden, die ja per Definition eigentlich nicht über die Attribute der Bankverbindung verfügt. Da wir aber den Typ für Kunden mit Girokonto als Subtyp von otyp_kunde eingeführt hatten, lassen sich dessen Objekte wie normale Kunden behandeln. Nun muss sich zeigen, dass die Zusatzangaben auch bei Abfragen wieder zur Verfügung stehen. Dazu ist es erforderlich, die Behandlung der zusätzlichen Attribute explizit anzufordern, indem man verlangt, dass alle Kunden wie Exemplare des Subtyps behandelt werden. Damit werden die zusätzlichen Attribute des spezialisierten Typs in die Projektionsliste übernommen, und für normale Kunden erhalten sie den Wert NULL: SELECT kunden_nr, name, TREAT (VALUE(k) AS otyp_kunde_mit_bankeinzug). bankverbindung.konto_inhaber AS konto_inhaber, TREAT (VALUE(k) AS otyp_kunde_mit_bankeinzug). bankverbindung.kontonr AS kontonr, TREAT(VALUE(k) AS otyp_kunde_mit_bankeinzug). bankverbindung.blz AS blz FROM otab_kunde k; KUNDEN_NR NAME KONTO_INHABER ---------- ------------------------------ ----------------------KONTONR BLZ ---------- -------100 Voss, Hans

101 Stein, Peter 123456789 23410022

Dagmar Stein

103 Randers, Nis 20001234 23410112

Tetsche Wind

...

9.3.6 Eingebettete Objekttypen In Abschnitt 9.2.2 haben wir die Kollektionstypen vorgestellt, die der Standard fordert: MULTISET und ARRAY24. Oracle unterstützt zur Zeit zwei Kollektionstypen: VARRAY (siehe Seite 328) und die eingebettete Tabelle (nested table). Mit eingebetteten Tabellen als Typ können Attribute definiert werden, die eine Multimenge von 24 Vgl. 9.2.2.

338

Sandini Bib

Objektrelationales Modell der Versanddatenbank

Tupeln enthalten. Wenn eine solche Tabelle nur ein Attribut enthält, handelt es sich eben um eine Multimenge von Einzelwerten. Die Einbettung einer Tabelle, die selbst auf einem Objekttyp beruht, in einen anderen Objekttyp stellt eine sehr enge Verbindung dar. Wir haben sie in Kapitel 3.3 als Komposition eingeführt. In unserer Fallstudie kann die Verbindung zwischen einer Bestellung und ihren Positionen als Komposition aufgefasst werden. Im Entity-Relationship-Modell würde man einen eingebetteten Objekttyp als abhängigen Entitätstyp modellieren. Um diese Idee umzusetzen, müssen wir erst einen Objekttyp für Positionen definieren, den wir dann in einen Typ für Bestellungen einbetten. Langsam werden unsere Objekttypen auch komplexer, denn eine Position enthält einen Verweis auf einen Artikel. Wir verwalten Artikel unabhängig von Bestellpositionen und sollten deshalb hierfür eine Referenz einsetzen. Da der Typ otyp_artikel selbst wieder ein Attribut vom Typ REF otyp_mwsatz enthält, haben wir dann gleich eine mehrstufige Referenz. Wir zeigen hierbei auch noch einmal ein Beispiel für eine Methode mit dem Namen get_artikel_nr, die die Anzeige der Artikelnummer einer Bestellposition etwas einfacher gestaltet. CREATE OR REPLACE TYPE otyp_position AS OBJECT ( pos_artikel REF otyp_artikel, mwst number (4,3), -- tatsaechlich angewandter MWST-Satz als Dezimalzahl bestellmenge number (5,0), liefermenge number(5,0), gesamtpreis number(10,2), MEMBER FUNCTION get_artikel_nr RETURN VARCHAR2, PRAGMA RESTRICT_REFERENCES (get_artikel_nr, WNDS, WNPS) ); CREATE OR REPLACE TYPE BODY otyp_position AS MEMBER FUNCTION get_artikel_nr RETURN VARCHAR2 IS lvar_artnr VARCHAR2(4); BEGIN SELECT artikel_nr INTO lvar_artnr FROM otab_artikel a WHERE VALUE(a) = DEREF(pos_artikel); RETURN lvar_artnr; END get_artikel_nr; ;

Wir haben nunmehr den Typ einer einzelnen Position beschrieben. Wenn wir eine ganze Tabelle davon in eine Bestellung einbetten wollen, müssen wir einen Kollektionstyp definieren. CREATE OR REPLACE TYPE ntyp_position AS TABLE OF otyp_position;

339

Sandini Bib

9 Objektorientierung und SQL

Jetzt kann otyp_bestellung erstellt werden.25 CREATE OR REPLACE TYPE otyp_bestellung AS OBJECT ( bestell_nr number(6,0), bestellkunde REF otyp_kunde, bestelldatum date, lieferdatum date, positionen ntyp_position, rechnungsbetrag number(10,2) );

Wir erzeugen anschließend einen Extent für diesen Typ mit der Besonderheit, dass wir auch für die eingebettete Tabelle einen Namen vergeben können. CREATE TABLE otab_bestellung OF otyp_bestellung NESTED TABLE positionen STORE AS ntab_position;

Das Einfügen eines neuen Tupels in Bestellung wird nun wegen der relativ komplizierten Struktur schon etwas aufwändig. Es lässt sich aber vermeiden, dass man mit der Bestellung gleich alle Positionen übergibt. Mit dem Ausdruck ntyp_position ()

wird die Sammlung instanziiert, bleibt aber leer. Die Tupel, die ihn mit Inhalt füllen, können später separat an die Datenbank übermittelt werden. INSERT INTO otab_bestellung (bestell_nr, Bestelldatum, bestellkunde, Lieferdatum, Rechnungsbetrag, Positionen) SELECT 151,TO_DATE('28-04-2000','DD-MM-YYYY'),REF(k), TO_DATE('02-05-2000','DD-MM-YYYY'), 196.75, ntyp_position () /* der Positionen-Sammler wird hier nur instanziiert, aber nicht mit Objekten gefuellt [Kähl99 S. 230]. Wichtig hier die Angabe des Nested-Tabellen-Typs. */ FROM otab_kunde k WHERE k.kunden_nr = 101

Die Tatsache, dass ein Attribut nicht einen Wert, sondern eine Tabelle enthalten kann, hat weitreichende Konsequenzen. Wir haben in Kapitel 5.4 gesehen, dass in einer Unterabfrage (SELECT ausdruck FROM tabelle ...)

mit dem Wert des Ausdrucks in dem Ergebnistupel identifiziert wird (vorausgesetzt, die Abfrage liefert eine Relation mit genau einem Tupel). Diese Unterabfrage kann an jeder Stelle stehen, wo ein Wert stehen kann. 25 Im nächsten Abschnitt wird gezeigt, dass die Einbettung von Positionen in Bestellungen als nested table unter dem Gesichtspunkt des UPDATE nicht günstig ist. Vorgeschlagen wird eine Referenz auf Positionsdaten, die in einer eigenen Objekttabelle gehalten werden.

340

Sandini Bib

Objektrelationales Modell der Versanddatenbank

Wir haben jetzt eine ähnliche Situation, wenn ausdruck als Ergebnis eine Tabelle liefert, TABLE (SELECT ausdruck FROM tabelle ...)26

liefert uns eine Tabelle, die an Stellen, in denen Tabellen auftreten können, eingesetzt werden kann. Das sind neben der SELECT-Anweisung auch die INSERT-, UPDATE- und DELETE-Anweisung. Damit wir das folgende Tupel der richtigen Bestellung zuordnen können, wird die Zieltabelle für den folgenden INSERT-Befehl durch eine Abfrage erzeugt. Die Referenz auf einen Artikel lässt sich wieder nur über eine Query darstellen und in das neue Tupel einfügen. INSERT INTO TABLE ( SELECT positionen FROM otab_bestellung WHERE bestell_nr = 151) SELECT REF(a1),a1.get_mwst(),4,4,49.80 FROM otab_artikel a1 WHERE artikel_nr = 'G001' /

Die Anzeige von Bestelldaten mit dem Namen des Kunden kommt wieder ohne Join aus. select bestell_nr, bestelldatum, b.bestellkunde.kunden_nr, b.bestellkunde.name from otab_bestellung b; BESTELL_NR ---------151 152

BESTELLDATUM BESTELLKUNDE.KUNDEN_NR BESTELLKUNDE.NAME ------------ ---------------------- -----------------28.04.00 101 Stein, Peter 30.04.00 103 Randers, Nis

Die Positionsdaten einer Bestellung aus der eingebetteten Tabelle anzuzeigen, erfordert noch ein syntaktisches Konstrukt, die CURSOR-Klausel. Der Cursor liefert einen sequenziellen Zugriff auf die Tupel der Untertabelle, um dort, wo sonst ein einzelner Attributwert steht, eine Menge von Tupeln als Tabelle anzuzeigen.27 Bei der ersten Variante erscheint wieder die unleserliche OID, die die Referenz auf den MwStSatz des Artikels darstellt. In der zweiten Varianten projizieren wir, entlang der Referenzen navigierend, auf Einzelattribute. 1. Variante: SELECT b.bestell_nr, CURSOR (SELECT DEREF(pos_artikel), bestellmenge FROM TABLE (b.positionen) 26 In der Version 8 war das Schlüsselwort THE statt TABLE. 27 In imperativen Programmiersprachen dient ein gleichnamiges Konzept dazu, die mengenmäßig strukturierte Ausgabe einer SQL-Abfrage in eine konventionelle Satzstruktur abzubilden, die dann beispielsweise in Schleifen Satz für Satz bearbeitet werden kann. Mehr dazu findet sich in Kapitel 7.3.4.

341

Sandini Bib

9 Objektorientierung und SQL

) FROM otab_bestellung b ; BESTELL_NR CURSOR(SELECTDEREF(P ---------- -------------------151 CURSOR STATEMENT : 2 CURSOR STATEMENT : 2 DEREF(POS_ARTIKEL)(ARTIKEL_NR, MWST, BEZEICHNUNG, LISTENPREIS, BESTAND, MINDESTB ----------------------------------------------------------------BESTELLMENGE -----------OTYP_ARTIKEL('K002', 0000220208F6C875DF3D4C4067AB8323CBFBC3B3889E1EB69AB2DC4B139 A4B6698472A1C6C, 'Hose', 112,8, 62, 25, NULL, 2, NULL, NULL, NULL, NULL) 3 OTYP_ARTIKEL('G001', 0000220208F6C875DF3D4C4067AB8323CBFBC3B3889E1EB69AB2DC4B139 A4B6698472A1C6C, 'Whisky', 38,5, 397, 50, '0,7 l', 7, NULL, NULL, NULL, NULL) 4 ...

2. Variante select bestell_nr, bestelldatum, b.bestellkunde.kunden_nr, b.bestellkunde.name, CURSOR (SELECT p.pos_artikel.artikel_nr AS artikel_nr, p.pos_artikel.bezeichnung AS bezeichnung, p.bestellmenge AS bestellmenge FROM TABLE (b.positionen) p) from otab_bestellung b; BESTELL_NR BESTELLDATUM BESTELLKUNDE.KUNDEN_NR BESTELLKUNDE.NAME ---------- ------------ ---------------------- -----------------CURSOR(SELECTP.POS_A -------------------151 28.04.00 101 Stein, Peter CURSOR STATEMENT : 5 CURSOR STATEMENT : 5

342

Sandini Bib

Objektrelationales Modell der Versanddatenbank

ARTIKEL_NR ---------K002 G001 G003 K003 L002

BEZEICHNUNG BESTELLMENGE --------------- -----------Hose 3 Whisky 4 Bier 3 Damenhut 1 China-Tee 10

9.3.7 Schreiboperationen in Objekttabellen Wir haben bereits vorgeführt, wie man Daten in eine Objekttabelle einfügt. Weitere Schreiboperationen sind Änderungen an vorhandenen Objekten und Löschungen. Das Löschen von Daten aus Objekttabellen geht genauso vor sich wie bei der relationalen Variante. Der folgende Befehl löscht die Bestellung 151: DELETE FROM otab_bestellung WHERE bestell_nr = 151;

Damit werden gleichzeitig die Positionsdaten in der eingebetteten Tabelle gelöscht. Eine Besonderheit gibt es bei eingebetteten Tabellen. Hier muss eine Subquery mit dem Typkonstruktor TABLE verwendet werden. Der folgende Befehl löscht alle Positionen der Bestellung 151: DELETE FROM TABLE (SELECT b.positionen FROM otab_bestellung b WHERE b.bestell_nr =151);

Das Ändern von Daten mit dem UPDATE-Befehl unterliegt einigen Besonderheiten, wenn es sich nicht um skalare Attribute handelt, sondern Attribute, die auf einem benutzerdefinierten Typ beruhen. Im Falle der Kundenadresse haben wir ein Attribut auf Basis des Typs otyp_adresse mit innerer Struktur definiert. Der Zugriff auf eine einzelne Komponente erfolgt mit der »Punktnotation«: update otab_kunde k set k.adresse.strasse = 'neue Strasse 3' WHERE kunden_nr = 103;

Der Tabellenalias k darf dabei nicht fehlen. Erlaubt ist auch die Anwendung des UPDATE-Befehls auf eine konstruierte Tabelle, die Resultat einer Abfrage ist. update (SELECT kunden_nr, k.adresse.strasse strasse, k.adresse.plz FROM otab_kunde k WHERE kunden_nr = 103) set strasse = 'neue Strasse 4';

343

Sandini Bib

9 Objektorientierung und SQL

Hier haben wir die Struktur der Adresse aufgelöst, so dass eine »flache« Tabelle vorliegt.

Schreiboperationen in eingebettete Tabellen Schwierigkeiten bereitet der UPDATE-Befehl bei einer eingebetteten Tabelle. Da jede Änderungsoperation eine Sperre auf das Vater-Objekt auslöst, kann immer nur eine Operation zur Zeit ausgeführt werden.28 Das bedeutet, dass ein Objekt in einer eingebetteten Tabelle nur über ein Benutzerprogramm geändert werden kann, das Reihe für Reihe in Form eines CURSORS verarbeitet.29 Der SQL-Befehl UPDATE ist aber mengenorientiert und verarbeitet daher Mengen von Objekten, selbst wenn die Selektionsbedingung nur eine einzige Reihe qualifiziert. Da die Positionen einer Bestellung im Einzelnen aktualisiert werden müssen, brauchen wir eine befriedigende Lösung für dieses Problem. Sie besteht darin, eine eigene Objekttabelle für Bestellpositionen zu erzeugen, und in die Bestellungen dann Referenzen auf ihre Positionen-Objekte einzubauen. Diese Entscheidung hat mehrere Konsequenzen: 왘 Jede Bestellposition muss einen Verweis auf die zugehörige Bestellung enthalten. Dies kann entweder über eine Referenz geschehen, wir hätten dann einen Zyklus an Referenzen, was möglich ist. Oder wir übernehmen die Bestellnummer als konventionellen Fremdschlüssel in die Positionen, wie beim relationalen Modell. Diese Variante haben wir im folgenden Beispiel umgesetzt. 왘 Wenn wir die Verweise auf die Positionen in jede Bestellung einfügen wollen, brauchen wir nach wie vor eine eingebettete Tabelle, die aber nunmehr nicht die Positionen, sondern die Verweise darauf enthält. 왘 Für diese eingebettete Tabelle ist ein weiterer Datentyp erforderlich. 왘 Die Anfragen werden komplizierter und abstrakter, da durch die aufzulösende Referenz ein weiterer Zwischenschritt hin zu den Attributen der Position erforderlich ist. 왘 Beim Löschen einer Bestellung werden nicht automatisch die Positionen mit gelöscht. Dies müssen wir über Verfahrensregeln für den Fremdschlüssel in der Objekttabelle für die Positionen regeln. Wir definieren die Typen für Bestellung und Position neu30. Die Bestellnummer wird in otyp_position2 mit aufgenommen: CREATE OR REPLACE TYPE otyp_position2 AS OBJECT ( bestell_nr number(6,0), pos_artikel REF otyp_artikel, mwst number (4,3), -- tatsaechlich angewandter MWST-Satz als Dezimalzahl 28 Vgl. [Ora01b, S. 8-22]. 29 Vgl. Kapitel 7.3.4. 30 Das Beispiel findet sich auf der CD in der Skriptdatei crybestellung2.sql im Verzeichnis \...\OracleOO.

344

Sandini Bib

Objektrelationales Modell der Versanddatenbank

bestellmenge number (5,0), liefermenge number(5,0), gesamtpreis number(10,2), MEMBER FUNCTION get_artikel_nr RETURN VARCHAR2, PRAGMA RESTRICT_REFERENCES (get_artikel_nr, WNDS, WNPS) );

Es folgt die Anlage einer eigenen Objektdatei für Positionen. CREATE TABLE otab_position2 OF otyp_position2

Für die Einbettung in Bestellungen brauchen wir einen REF-Datentyp auf eine Position. Dieser hat nur ein einziges Attribut, nämlich die Referenz. Bei Abfragen ist dies dann der Einstiegspunkt, um zu den Attributen der Position zu navigieren. CREATE TYPE otyp_refpos2 AS OBJECT ( ref_pos REF otyp_position2 )

Der nächste Schritt ist die Definition einer einzubettenden Tabelle mit Tupel vom Typ otyp_refpos2. CREATE OR REPLACE TYPE ntyp_refpos2 AS TABLE OF otyp_refpos2

Schließlich wird der Typ für Bestellungen neu bestimmt: CREATE OR REPLACE TYPE otyp_bestellung2 AS OBJECT ( bestell_nr number(6,0), bestellkunde REF otyp_kunde, bestelldatum date, lieferdatum date, ref_pos_liste ntyp_refpos2, rechnungsbetrag number(10,2) );

Abschließend legen wir eine Objekttabelle für Bestellungen an. CREATE TABLE otab_bestellung2 OF otyp_bestellung2 NESTED TABLE ref_pos_liste STORE AS ntab_ref_pos;

Das Einfügen von Daten in unsere Tabellen geschieht nun in drei Schritten: 1) Erst werden Daten in otab_bestellung2 eingefügt. Die Referenzen auf Positionen werden dabei mit NULL initialisiert. 2) Für jede Bestellposition wird ein Objekt in otab_position2 eingefügt. 3) In die eingebettete Tabelle werden Referenzen auf die Positionen eingefügt. Dabei brauchen wir die Selektionsmöglichkeit über den Fremdschlüssel bestell_nr.

345

Sandini Bib

9 Objektorientierung und SQL

INSERT INTO otab_bestellung2

(bestell_nr, Bestelldatum, bestellkunde, Lieferdatum, Rechnungsbetrag, ref_pos_liste) SELECT 151,TO_DATE('28-04-2000','DD-MM-YYYY'), REF(k), TO_DATE('02-05-2000','DD-MM-YYYY'), 196.75, ntyp_refpos2 () FROM otab_kunde k WHERE k.kunden_nr = 101 INSERT INTO otab_position2 (SELECT 151, REF(a1), a1.get_mwst(),4,4,49.80 FROM otab_artikel a1 WHERE artikel_nr = 'G001')

... und so weiter für jede Position. INSERT INTO TABLE (SELECT ref_pos_liste FROM otab_bestellung2 WHERE bestell_nr = 151) SELECT REF(p) FROM otab_position2 p WHERE bestell_nr = 151

Bei der Abfrage ist es nun notwendig, die Navigation beispielsweise zur Artikelnummer bei der Referenz ref_pos auf die Position, in der sie vorkommt, zu beginnen. select bestell_nr, bestelldatum, b.bestellkunde.kunden_nr, b.bestellkunde.name, CURSOR (SELECT p.ref_pos.pos_artikel.artikel_nr AS artikel_nr, p.ref_pos.pos_artikel.bezeichnung AS bezeichnung, p.ref_pos.bestellmenge AS bestellmenge FROM TABLE (b.ref_pos_liste) p) from otab_bestellung2 b; BESTELL_NR BESTELLDATUM BESTELLKUNDE.KUNDEN_NR BESTELLKUNDE.NAME ---------- ------------ ---------------------- -----------------CURSOR(SELECTP.REF_P -------------------151 28.04.00 101 Stein, Peter CURSOR STATEMENT : 5 CURSOR STATEMENT : 5 ARTI ---G001 G003

346

BEZEICHNUNG BESTELLMENGE --------------- -----------Whisky 4 Bier 3

Sandini Bib

Objektrelationales Modell der Versanddatenbank

K002 Hose K003 Damenhut L002 China-Tee

3 1 10

9.3.8 Object Views Ein View ist eine virtuelle Tabelle, erzeugt durch eine Abfrage. Wir haben dies in Kapitel 6 beschrieben. Ein object view ist das Gleiche als Objekttabelle. Jede Zeile in einem object view ist ein Objekt mit Attributen und möglicherweise Methoden. Ein interessanter Aspekt an dieser Form der Datensichten besteht darin, dass es möglich ist, object views auf relationalen Basistabellen aufzubauen. Damit gewinnt man Vorteile bei der objektorientierten Programmierung von Anwendungen.31 Die Zugriffe auf Daten können beispielsweise über die object views erfolgen, so als wären die Datenstrukturen objektorientiert und nicht relational.32 Ein weiterer Vorteil besteht darin, dass die Navigation zu den Werten komplexer, auf abstrakten Datentypen basierender Attribute einfacher sein kann33, als ein komplizierter Join über 2 oder mehr Tabellen. Wir zeigen ein Beispiel, in dem wir object views über den Basistabellen unserer relationalen Versanddatenbank anlegen. Im Unterschied zu relationalen Datensichten sind jeweils zwei Schritte erforderlich. Zunächst erzeugen wir einen Datentyp für Kundenobjekte. Dabei wollen wir die Adresse als benutzerdefinierten Datentyp verwalten. create type otyp_KUNDE4view AS OBJECT ( kunden_nr number (4,0) , status varchar2(1) , name varchar2(30) , adresse otyp_adresse, letzte_bestellung date, letzte_werbeaktion date, zahlungsart char(1) )

Im zweiten Schritt erzeugen wir den view über eine Abfrage, die natürlich objektspezifische Eigenarten enthält. Die eine ist die optionale Festlegung, dass die OID auf Basis des Primärschlüssels erzeugt werden soll. Weiterhin müssen wir den Standardkonstruktor für eine Adresse benutzen, um mit den Werten von Straße, Postleitzahl und Ort ein Objekt vom Typ otyp_adresse zu erzeugen. 31 Vgl. [Ora01b, S. 5-2], 32 Schreibende Zugriffe auf Views sind nicht immer zulässig, wie wir in Kapitel 6 ausgeführt haben. Es gibt aber die Möglichkeit, über INSTEAD OF-Trigger das Verhalten eines UPDATEBefehls so umzudefinieren, dass er die gewünschten Operationen auf Basistabellen ausführt. Vgl. [Ora01b, S. 5-14]. 33 Darüber, was im Endeffekt einfacher ist, können sich nun Anhänger der Objektorientierung und Verfechter des »klassischen« relationalen Ansatzes endlos streiten.

347

Sandini Bib

9 Objektorientierung und SQL

CREATE VIEW ov_kunde OF otyp_KUNDE4view WITH OBJECT IDENTIFIER (kunden_nr) AS SELECT k.kunden_nr, status, name, otyp_adresse(strasse, plz, ort), letzte_bestellung, letzte_werbeaktion, zahlungsart FROM kunde k

Der Objekttyp für Bestellungen enthält nun eine Referenz auf den object view für Kunden. create type otyp_BESTELLUNG4view AS OBJECT ( bestell_nr number(6,0), ref_kunde REF otyp_KUNDE4view, bestelldatum date, lieferdatum date, rechnungsbetrag number(10,2) ) CREATE VIEW ov_bestellung OF otyp_BESTELLUNG4view WITH OBJECT IDENTIFIER (bestell_nr) AS SELECT bestell_nr, REF (k), bestelldatum, lieferdatum, rechnungsbetrag FROM bestellung b, ov_kunde k WHERE b.kunden_nr = k.kunden_nr

Eine Abfrage auf diese Datensicht zeigt uns nunmehr die in relationalen Tabellen gespeicherten Tupel wie Objekte: SELECT bestell_nr, bestelldatum, DEREF (ref_kunde) FROM ov_bestellung; BESTELL_NR BESTELLDATUM ---------- -------DEREF(REF_KUNDE)(KUNDEN_NR, STATUS, NAME, ADRESSE(STRASSE, PLZ, ORT), LETZTE_BESTELLUNG, LETZTE_WERBEAKTION, ZAHLUNGSART) ----------------------------------------------------------------151 28.04.00 OTYP_KUNDE4VIEW(101, 'S', 'Stein, Peter', OTYP_ADRESSE('Moordamm 34', '23863', 'Kayhude'), '28.04.00', '01.12.99', 'B')

348

Sandini Bib

A

Ausgewählte Lösungen zu den Aufgaben

A.0.1 Kapitel 2 Aufgabe 2.1 a) SET NULL: Wenn der Abteilungsleiter ausscheidet, gibt es für eine gewisse Zeit keinen Abteilungsleiter. b) CASCADE: Wenn die Studentendaten nicht mehr benötigt werden, dann auch nicht mehr ihre Prüfungsdaten. c) CASCADE: Wenn die Bestellung storniert wird, dann auch ihre Positionen. d) RESTRICT: Solange nicht bezahlt ist, müssen die Kundendaten ermittelbar sein. Aufgabe 2.2 a) Proj[lagerplatz] (artikel) b) Proj[plz, ort] (kunde) c) Sel[ (artikel_nr = 'G001' ∨ artikel_nr = 'G002' ∨ artikel_nr = 'G003') ∧ liefermenge > 0 ] (position) d) Sel[ (artikel_nr = 'G001' ∨ artikel_nr = 'G002' ∨ artikel_nr = 'G003') ∧ liefermenge > 2 ] (position) e) Sel[artikel_nr≠'G001' ∧ artikel_nr≠'G002' ∧ artikel_nr≠ 'G003'] (position)

f) Proj[kunden_nr, name, ort, status] (Sel[status≠'S'] (kunde)) g) Sel[status ≠ 'S' ∧ ort ≠ 'Husum'] (kunde) h) Sel[bestelldatum ≥ '2000-05-01' ∧ bestelldatum ≤ '2000-05-31'] (bestellung)

i) Sel[artikel_nr = 'K001' ∨ artikel_nr = 'G003'] (position) j) Sel[listenpreis ≥ 6.00 ∧ listenpreis ≤ 15.00] (artikel) k) Grp[mwstsatz | anzahl ::= COUNT(*)] (artikel) l) Grp[status | max_kunden_nr ::= MAX(kunden_nr)] (kunde) m) Grp [lagerplatz | min_preis ::= MIN(Listenpreis), max_preis ::= MAX(Listenpreis), avg_preis ::= AVG(Listenpreis)] (artikel)

349

Sandini Bib

A Ausgewählte Lösungen zu den Aufgaben

n) Grp [plz | anzahl ::= COUNT(*)] (kunde) o) Proj[plz] (Sel[anzahl > 1] (Grp[plz | anzahl ::= COUNT(*)] (kunde))) p) Proj[zahlung] (Sel[anzahl > 2] (Grp[zahlung | anzahl ::= COUNT(*)] (kunde)))

q) Proj[artikel_nr, bezeichnung, prozent] (artikel Join[mwst] mwstsatz) r) Proj[artikel_nr, bezeichnung, brutto ::= listenpreis + listenpreis * prozent ] (artikel Join[mwst] mwstsatz)

s) Proj[bestell_nr, ort] (bestellung Join[kunden_nr] kunde) t) Proj[bestellmenge, bestell_nr, ort] (position Join[bestell_nr] bestellung Join[kunden_nr] kunde )

u) Grp [ort | anzahl ::= SUM(bestellmenge)] (position Join[bestell_nr] bestellung Join[kunden_nr] kunde )

v) Sel[ | listenpreis = MIN(listenpreis; artikel)] (artikel) w) Proj[kunden_nr, name, bestell_nr] (Sel[bestelldatum = MIN(bestelldatum; bestellung)] (bestellung) Join[kunden_nr] (kunde))

x) Proj[bestell_nr, bestelldatum] (bestellung Join[kunden_nr] Sel [ort ≠ 'Kayhude'] (kunde)

y) Sel[listenpreis > MAX(listenpreis; Sel[lagerplatz=7](artikel))] (artikel) Aufgabe 2.3 Adj[späteste_lieferung ::= bestelldatum + 14] (Sel[isNull(Lieferdatum)] (bestellung))

Aufgabe 2.4 a) Proj[artikel_nr, bezeichnung, bestellmenge] (artikel Join*[artikel_nr] (position Join[bestell_nr] bestellung))

b) kunde Join*[kunden_nr] girokonto c) (Proj[kunden_nr](kunde) \ Proj[kunden_nr] (girokonto)) Join[kunden_nr] (kunde)

Aufgabe 2.5 a) Relation, da der Primärschlüssel in der Projektion enthalten ist. b) Keine Relation, da [plz,ort] jeweils mehrfach auftreten können. c) Relation, da der Verbund von Relationen immer eine Relation ist. d) Relation, da bestell_nr Primärschlüssel der Bestell-Relation ist und zu jeder bestell_nr nur ein Kunden-Tupel gehört. e) Keine Relation, da ein Kunde mehrere Bestellungen aufgegeben haben kann.

350

Sandini Bib

A.0.2 Kapitel 3 Aufgabe 3.1 a) n:m-Beziehung: Es gibt Orte mit mehreren Postleitzahlen (z.B. Bremen), jeder Ort hat mindestens eine Postleitzahl. Es gibt Postleitzahlen, die für mehrere Orte gelten (z.B. 23863 für Kayhude und Bargfeld-Stegen). Jede Postleitzahl gilt für mindestens einen Ort – dies gilt allerdings nicht für jede Kombination von fünf Ziffern. b) 1:1-Beziehung: Zu jeder Steuernummer gibt es genau einen Steuerpflichtigen. Jeder Steuerpflichtige hat genau eine Steuernummer. c) n:1-Beziehung d) n:1-Beziehung e) n:2-Beziehung Aufgabe 3.2

Aufgabe 3.3

351

Sandini Bib

A Ausgewählte Lösungen zu den Aufgaben

Aufgabe 3.4 a) Wir stellen hier zwei Lösungen vor, die sich in der Behandlung der Person unterscheiden. In der ersten Lösung gehen wir von einer eigenen Klasse »Person« aus, Ausleiher und Autor sind jeweils Unterklassen. In der zweiten Lösung wird »Ausleiher« und »Autor« jeweils als Rolle gesehen – es werden dafür keine eigenen Klassen angelegt. Die Auswahl zwischen diesen beiden Lösungen hängt davon ab, wie stark sich Autoren und Ausleiher in ihren Attributen und ihrer Verarbeitung unterscheiden.

352

Sandini Bib

Aufgabe 3.5 (Segeltörn)

Aufgabe 3.6 a) Die erste Normalform ist verletzt, da das Feld Autoren für ein Tupel mehrere Werte hat. b) Es sind zwei Relationen in folgender Weise zu erzeugen: ISBN-Nr

Titel

Jahr

Seiten

0-201-14192-2

The Relational Model for Database Management: Version 2

1990

538

3-89319-117-8

Systematischer Einsatz von SQL-Oracle

1989

494

1-55860-245-3

Understanding the new SQL

1993

536

353

Sandini Bib

A Ausgewählte Lösungen zu den Aufgaben

ISBN-Nr

Autor

0-201-14192-2

Date, Ch.

3-89319-117-8

Finkenzeller, H.

3-89319-117-8

Kracke, U.

3-89319-117-8

Unterstein, M.

1-55860-245-3

Melton, J.

1-55860-245-3

Simon, A.

Aufgabe 3.7 a) Der Schlüssel ist aus matrikel_nr und kurs_nr zusammengesetzt. Da es funktionale Abhängigkeiten {matrikel_nr} → {student} und {kurs_nr} → {kurs_titel} gibt, ist die zweite Normalform an zwei Stellen verletzt. b) Ein äquivalentes System in normalisierter Form erhalten wir, indem wir aus den Attributen der rechten funktionalen Abhängigkeiten eine neue Relation erstellen und die rechten Seiten der funktionalen Abhängigkeiten aus der Relation herausziehen: Matrikel

Student

30321

Meyer, J.

30346

Ahrens, H.

30378

Knudsen, K.

Kurs-Nr

Kurs-Titel

715S4

Software-Engineering

713S5

relationale u. funktionale Programmierung

706S6

Datenbanksysteme

Matrikel

Kurs-Nr

Note

30321

706S6

1,0

30321

715S4

1,7

30346

715S4

3,0

30346

706S6

2,0

30346

713S5

1,7

30378

706S6

2,0

354

Sandini Bib

A.0.3 Kapitel 4 Aufgabe 4.1 a) In der Tabelle angestellter werden alle Zeilen geändert, in denen die geänderte Abteilungsnummer als Fremdschlüssel auftritt. Dort wird die neue Abteilungsnummer eingetragen. b) Es wird dort jetzt für die Abteilungsnummer eine Nullmarke eingetragen. c) In der Tabelle abteilung wird der Primärschlüssel nur geändert, wenn kein Tupel der Relation angestellter diese Abteilungsnummer eingetragen hat. Aufgabe 4.2 a) In der Tabelle seminar ist die dritte Normalform verletzt, weil es eine transitive Abhängigkeit dozname von doznr gibt. b) In seminarteilnehmer ist die zweite Normalform verletzt, weil das Attribut tnname von einem Teil des Schlüssels, nämlich tnnr, abhängt. c) Es genügt, die abhängigen Attribute aus den Relationen zu entfernen, da die entsprechenden Relationen (dozent und teilnehmer) schon vorhanden sind. d) Da die Aufgabenstellung hinsichtlich der Wertemengen keine Vorgaben enthält, stellt die folgende Lösung eine von mehreren Möglichkeiten dar. CREATE CREATE CREATE CREATE CREATE CREATE CREATE CREATE

DOMAIN DOMAIN DOMAIN DOMAIN DOMAIN DOMAIN DOMAIN DOMAIN

D_doznr AS INTEGER CHECK (VALUE > 10); D_personenname AS VARCHAR (30); D_tnnr AS INTEGER CHECK (VALUE > 100); D_semnr AS INTEGER CHECK (VALUE > 1000); D_thema AS VARCHAR (30); D_datum AS DATE CHECK (VALUE >= DATE '1996-01-01'); D_preis AS DECIMAL (6,2) CHECK (VALUE > 0); D_bezahlt AS CHAR (1) CHECK (VALUE IN ('J','N'));

e) Da in der Aufgabenstellung hinsichtlich der Verfahrensregeln bei Löschung und Änderung keine Vorgaben enthalten sind, sind auch andere Varianten als die hier vorgeschlagenen denkbar. CREATE TABLE dozent (doznr D_doznr NOT NULL, dozname D_personenname NOT NULL, PRIMARY KEY (doznr)); CREATE TABLE teilnehmer (tnnr D_tnnr NOT NULL, tnname D_personenname NOT NULL, PRIMARY KEY (tnnr)); CREATE TABLE SEMINAR (semnr D_semnr NOT NULL, thema D_thema NOT NULL, datum D_datum, preis D_preis, 355

Sandini Bib

A Ausgewählte Lösungen zu den Aufgaben

doznr D_doznr, PRIMARY KEY (semnr), FOREIGN KEY (doznr) REFERENCES dozent ON DELETE SET NULL ON UPDATE CASCADE); CREATE TABLE SEMINARTEILNEHMER (semnr D_semnr NOT NULL, tnnr D_tnnr NOT NULL, bezahlt D_bezahlt NOT NULL, PRIMARY KEY (semnr, tnnr), FOREIGN KEY (semnr) REFERENCES SEMINAR ON DELETE CASCADE ON UPDATE CASCADE, FOREIGN KEY (tnnr) REFERENCES TEILNEHMER ON DELETE CASCADE ON UPDATE CASCADE)

A.0.4 Kapitel 5 Aufgabe 5.1 INSERT INTO kunde (kunden_nr, status, name, strasse, plz, ort, letzte_bestellung, letzte_werbeaktion, zahlungsart) VALUES (198,'W','Holgerson, Nils', 'Gänseweg 10','28209','Bremen', DATE '1999-11-01', DATE '1999-06-29','N')

Aufgabe 5.2 Es gibt eine Fehlermeldung, da die Kundennummer 198 als Primärschlüssel schon existiert. Aufgabe 5.3 SELECT * FROM kunde; UPDATE kunde SET name = 'Berger-Steiger, Uwe' WHERE kunden_nr = 102; SELECT * FROM kunde; ROLLBACK;

Aufgabe 5.4 SELECT * FROM artikel; UPDATE artikel SET mindestbestand = mindestbestand + 5; SELECT * FROM artikel; 356

Sandini Bib

Aufgabe 5.5 UPDATE artikel SET listenpreis = listenpreis + 1, bestand = bestand + 10 WHERE artikel_nr = 'K003'

Aufgabe 5.6 INSERT INTO artikel (artikel_nr, mwst, bezeichnung, listenpreis, bestand, mindestbestand, verpackung, lagerplatz) VALUES ('X001', 2, 'Dudelsack', 1000, 1, 1, 'Karton', 7); SELECT * FROM artikel; DELETE FROM artikel WHERE

artikel_nr = 'X001';

SELECT * FROM artikel;

Aufgabe 5.7 SELECT bestell_nr, artikel_nr FROM position ORDER BY bestell_nr, artikel_nr;

Aufgabe 5.8 SELECT DISTINCT lagerplatz FROM artikel;

Aufgabe 5.9 SELECT DISTINCT plz, ort FROM kunde;

Aufgabe 5.10 SELECT bestell_nr, artikel_nr FROM position WHERE (artikel_nr = 'G001' OR artikel_nr = 'G002' OR artikel_nr = 'G003') AND liefermenge > 0;

Aufgabe 5.11 SELECT FROM WHERE AND OR OR

bestell_nr, position liefermenge (artikel_nr artikel_nr artikel_nr

artikel_nr > = = =

2 'G001' 'G002' 'G003') AND liefermenge > 2;

357

Sandini Bib

A Ausgewählte Lösungen zu den Aufgaben

Aufgabe 5.12 SELECT bestell_nr, artikel_nr FROM position WHERE NOT (artikel_nr = 'G001' OR artikel_nr = 'G002' OR artikel_nr = 'G003')

oder SELECT bestell_nr, artikel_nr FROM position WHERE artikel_nr 'G001' AND artikel_nr 'G002' AND artikel_nr 'G003')

Aufgabe 5.13 SELECT * FROM position WHERE liefermenge IS NULL

Aufgabe 5.14 SELECT FROM WHERE AND

kunden_nr, name, ort, status kunde status 'S' ort 'Husum';

Aufgabe 5.15 SELECT bestell_Nr, bestelldatum FROM bestellung WHERE bestelldatum BETWEEN '2000-05-01' AND '2000-05-31';

Aufgabe 5.16 SELECT artikel_nr, bezeichnung FROM artikel WHERE bezeichnung LIKE '%kekse%'

Aufgabe 5.17 SELECT artikel_nr, bezeichnung FROM artikel WHERE artikel_nr LIKE 'G%'

Aufgabe 5.18 SELECT artikel_nr, bestell_nr FROM position WHERE artikel_nr IN ('K001', 'G003')

358

Sandini Bib

Aufgabe 5.19 SELECT artikel_nr, bezeichnung, listenpreis FROM artikel WHERE listenpreis BETWEEN 6.00 AND 15.00

Aufgabe 5.20 SELECT

bestell_nr, artikel_nr, liefermenge, gesamtpreis, gesamtpreis/liefermenge AS einzelpreis FROM position ORDER BY bestell_nr, artikel_nr

Aufgabe 5.21 SELECT bestell_nr || ' vom ' || bestelldatum AS "offene Bestellungen" FROM bestellung WHERE lieferdatum IS NULL

Aufgabe 5.22 SELECT bestell_nr || ' vom ' || bestelldatum AS "offene Bestellungen", bestelldatum + 14 AS "späteste Lieferung" FROM bestellung WHERE lieferdatum IS NULL

Aufgabe 5.23 artikel_nr ist der Primärschlüssel der Artikeltabelle und hat deshalb für jede Zeile einen Wert. Wegen der Eindeutigkeit wäre das Ergebnis von COUNT(DISTINCT artikel_nr) ebenfalls identisch.

Aufgabe 5.24 SELECT mwst, COUNT(*) FROM artikel GROUP BY mwst

Aufgabe 5.25 SELECT MAX (kunden_nr) FROM kunde GROUP BY status

Aufgabe 5.26 SELECT lagerplatz, MIN(listenpreis), MAX (listenpreis), AVG(listenpreis) FROM artikel GROUP BY lagerplatz

359

Sandini Bib

A Ausgewählte Lösungen zu den Aufgaben

Aufgabe 5.27 SELECT plz, COUNT(kunden_nr) FROM kunde GROUP BY plz

Aufgabe 5.28 SELECT plz FROM kunde GROUP BY plz HAVING COUNT(*) > 1

Aufgabe 5.29 SELECT lagerplatz, SUM(bestand) FROM artikel GROUP BY lagerplatz HAVING SUM(bestand) < 1000;

Aufgabe 5.30 SELECT artikel_nr, artikel.mwst, prozent FROM artikel KEY JOIN mwstsatz

oder SELECT artikel_nr, artikel.mwst, prozent FROM artikel JOIN mwstsatz ON artikel.mwst = mwstsatz.mwst

Aufgabe 5.31 SELECT artikel_nr, artikel.mwst, prozent, listenpreis * (1 + prozent) AS bruttopreis FROM artikel JOIN mwstsatz ON artikel.mwst = mwstsatz.mwst

Aufgabe 5.32 SELECT bestell_nr, bestelldatum, ort FROM bestellung JOIN kunde USING(kunden_nr);

Es sind auch andere Arten der Verknüpfung möglich. Aufgabe 5.33 SELECT FROM JOIN JOIN

b.bestell_nr, position AS bestellung AS kunde AS

p.artikel_nr, p.bestellmenge, k.ort p b ON b.bestell_nr = p.bestell_nr k ON k.kunden_nr = b.kunden_nr

Es sind auch andere Arten der Verknüpfung möglich.

360

Sandini Bib

Aufgabe 5.34 SELECT k.ort, SUM(p.bestellmenge) FROM position AS p JOIN bestellung AS b ON b.bestell_nr = p.bestell_nr JOIN kunde AS k ON k.kunden_nr = b.kunden_nr GROUP BY k.ort

Es sind auch andere Arten der Verknüpfung möglich. Aufgabe 5.35 SELECT a.artikel_nr, p.bestellmenge FROM artikel AS a LEFT OUTER JOIN position AS p ON a.artikel_nr = p.artikel_nr

Aufgabe 5.36 SELECT k.kunden_nr, k.name, g.blz, g.kontonr FROM kunde AS k LEFT OUTER JOIN girokonto AS g ON k.kunden_nr = g.kunden_nr

Aufgabe 5.37 SELECT artikel_nr, bezeichnung, listenpreis FROM artikel WHERE listenpreis = (SELECT MIN(listenpreis) FROM artikel)

Aufgabe 5.38 SELECT k.kunden_nr, k.name, b.bestell_nr FROM kunde AS k JOIN bestellung AS b ON k.kunden_nr = b.kunden_nr WHERE bestell_nr = (SELECT MAX(bestell_nr) FROM bestellung)

Aufgabe 5.39 SELECT bestell_nr FROM bestellung WHERE kunden_nr IN ( SELECT kunden_nr FROM kunde WHERE ort 'Kayhude');

oder SELECT bestell_nr FROM bestellung WHERE kunden_nr NOT IN ( SELECT kunden_nr FROM kunde WHERE ort = 'Kayhude');

oder SELECT FROM JOIN WHERE

DISTINCT b.bestell_nr bestellung AS b kunde AS k ON b.kunden_nr = b.kunden_nr k.ort 'Kayhude';

361

Sandini Bib

A Ausgewählte Lösungen zu den Aufgaben

Aufgabe 5.40 SELECT artikel_nr, listenpreis FROM artikel WHERE listenpreis > ALL ( SELECT listenpreis FROM artikel WHERE artikel_nr LIKE 'G%')

Aufgabe 5.41 SELECT artikel_nr, bezeichnung FROM artikel AS a WHERE EXISTS (SELECT * from position AS p WHERE a.artikel_nr = p.artikel_nr)

beziehungsweise SELECT artikel_nr, bezeichnung FROM artikel AS a WHERE NOT EXISTS (SELECT * from position AS p WHERE a.artikel_nr = p.artikel_nr)

Aufgabe 5.42 SELECT k.kunden_nr, k.name FROM kunde AS k WHERE NOT EXISTS ( SELECT * FROM girokonto AS g WHERE g.kunden_nr = k.kunden_nr);

Aufgabe 5.43 Vereinigung: SELECT kunden_nr, name, status, ort FROM kunde WHERE status = 'S' UNION SELECT kunden_nr, name, status, ort FROM kunde WHERE ort = 'Kayhude'

Für Durchschnitt bzw. Differenz ersetze UNION durch INTERSECT bzw. MINUS.

A.0.5 Kapitel 8 Zu den Aufgaben aus Kapitel 8 werden keine Lösungen dokumentiert, da diese stark vom verwendeten DBMS abhängen.

362

Sandini Bib

B

Syntaxnotation

Als formale Beschreibung für die Syntax der SQL-Anweisungen werden folgende Konventionen benutzt: Schreibweise

Beispiel

Bedeutung

Großbuchstaben

SELECT

Schlüsselwort – ist so hinzuschreiben (beim Aufschreiben des Schlüsselwortes sind allerdings auch Buchstaben in Kleinschreibung zulässig).

Kleinbuchstaben

Tabelle

Dieser Text ist durch eine entsprechende syntaktische Konstruktion zu ersetzen.

[ ]

DELETE FROM tabelle [WHERE bedingung]

Der Teil in eckigen Klammern kann fehlen.



DISTINCT | ALL

Genau eine der angegebenen Alternativen ist zu nehmen. Es können auch mehr als zwei Alternativen angegeben werden.

{ }

UPDATE tabelle SET spalte = wert {, spalte = wert}

Der Teil in geschweiften Klammern kann fehlen, einmal benutzt oder mehrfach wiederholt werden.

xyz-liste

spaltenliste

Ein Element von xyz oder mehrere Elemente von xyz; Elemente der Liste werden jeweils durch ein Komma getrennt.

Die Konstruktion xyz-liste ist eine Kurzschreibweise für xyz {, xyz}.

363

Sandini Bib

Sandini Bib

C

Beispieldatenbank

C.1 Domänendefinitionen -- Datenbank Versand Version Sybase Adaptive Server Anywhere 6.0 ----------------------------------------------------------------- Definition von allgemeinen Domaenen ----------------------------------------------------------------- natuerliche Zahlen CREATE DOMAIN CARDINAL INTEGER CHECK (@VALUE >= 0); -- logische Werte CREATE DOMAIN BOOLEAN SMALLINT NOT NULL DEFAULT 0 CHECK (@VALUE BETWEEN 0 AND 1); -- Waehrungsbetraege -- Datentyp Money existiert als NUMERIC(19,4) CREATE DOMAIN UD_Money DECIMAL (15,2) DEFAULT 0.00; -- Prozentsaetze mit einer Nachkommastelle, max. 99,9% CREATE DOMAIN Prozentsatz DECIMAL(3,3); CREATE DOMAIN Personenname CHAR(30); CREATE DOMAIN Strassenname CHAR(30); CREATE DOMAIN Postleitzahl CHAR(5); CREATE DOMAIN Ortsname CHAR(25); CREATE DOMAIN Bankleitzahl NUMERIC(8);

365

Sandini Bib

C Beispieldatenbank

CREATE DOMAIN Kontonummer CHAR(10); --------------------------------------------------------------- Definition von spezifischen Schluessel-Domaenen -------------------------------------------------------------CREATE DOMAIN Kunden_key INTEGER CHECK (@VALUE >= 100); -- moegliche Zustaende eines Kunden -'W': Werbemassnahme - noch nicht als Kunde aufgetreten -'G': Gelegenheitskunde -'S': Stammkunde CREATE DOMAIN Kundenstatus CHAR(1) CHECK (@VALUE IN ('W', 'G', 'S')); -- Zahlungsart -'R': Rechnung -'B': Bankeinzug -'N': Nachnahme -'V': Vorkasse -'K': Kreditkarte CREATE DOMAIN Zahlungsart CHAR(1) CHECK (@VALUE IN ('R', 'B', 'N', 'V', 'K')) DEFAULT 'N'; CREATE DOMAIN artikel_key CHAR(4); CREATE DOMAIN Lager SMALLINT CHECK (@VALUE >= 0); CREATE DOMAIN mwst_key SMALLINT CHECK (@VALUE >= 0); CREATE DOMAIN bestell_key INTEGER CHECK (@VALUE >= 0);

366

Sandini Bib

Anlage der Tabellen

C.2 Anlage der Tabellen -- Versand 2000 Anlage der Datenbank in SQLANYWHERE --------------------------------------------------------------- Table : KUNDE-in SQL Anywhere ist NAME ein Schluesselwort, daher hier: kname -------------------------------------------------------------CREATE TABLE kunde( kunden_nr Kunden_Key NOT NULL, status Kundenstatus NOT NULL, kname Personenname NOT NULL, strasse Strassenname NOT NULL, plz Postleitzahl NOT NULL, ort Ortsname NOT NULL, letzte_bestellung DATE, letzte_werbeaktion DATE, zahlungsart Zahlungsart NOT NULL, PRIMARY KEY (kunden_nr) ); --------------------------------------------------------------- Table : MwStSatz -------------------------------------------------------------CREATE TABLE mwstsatz( mwst MwSt_Key NOT NULL, prozent Prozentsatz NOT NULL, beschreibung CHAR(10) NOT NULL, PRIMARY KEY (mwst) ); --------------------------------------------------------------- Table : Bestellung -------------------------------------------------------------CREATE TABLE bestellung( bestell_nr Bestell_Key NOT NULL, kunden_nr Kunden_Key NOT NULL, bestelldatum DATE NOT NULL DEFAULT CURRENT DATE, lieferdatum DATE, rechnungsbetrag UD_Money, PRIMARY KEY (bestell_nr), FOREIGN KEY (kunden_Nr) REFERENCES kunde ON DELETE RESTRICT ON UPDATE CASCADE ); --------------------------------------------------------------- Table : Artikel --------------------------------------------------------------

367

Sandini Bib

C Beispieldatenbank

CREATE TABLE artikel( artikel_nr Artikel_Key NOT NULL, mwst MWSt_Key NOT NULL, bezeichnung CHAR(20) NOT NULL, listenpreis UD_Money NOT NULL, bestand CARDINAL NOT NULL, mindestbestand CARDINAL NOT NULL, verpackung CHAR(10), lagerplatz Lager, kann_wegfallen BOOLEAN, bestellvorschlag TIMESTAMP, nachbestellung TIMESTAMP, nachbestellmenge CARDINAL CHECK (nachbestellmenge > 0), PRIMARY KEY (artikel_nr), FOREIGN KEY (mwst) REFERENCES mwstsatz ON UPDATE CASCADE ON DELETE RESTRICT ); --------------------------------------------------------------- Table : Position -------------------------------------------------------------CREATE TABLE position ( bestell_nr Bestell_key NOT NULL, artikel_nr Artikel_key NOT NULL, mwst Prozentsatz, -- aus Artikeltabelle zu uebernehmen bestellmenge CARDINAL NOT NULL CHECK (bestellmenge >= 1), liefermenge CARDINAL, gesamtpreis UD_Money, PRIMARY KEY (bestell_nr, artikel_nr), FOREIGN KEY (bestell_nr) REFERENCES bestellung ON UPDATE CASCADE ON DELETE CASCADE, FOREIGN KEY (artikel_nr) REFERENCES artikel, CHECK (liefermenge