Datenbankkonzepte in der Praxis - mt-computersysteme.de
Datenbankkonzepte in der Praxis - mt-computersysteme.de
Datenbankkonzepte in der Praxis - mt-computersysteme.de
Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.
YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.
<strong>Datenbankkonzepte</strong> <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>Praxis</strong>
Sönke Cordts<br />
<strong>Datenbankkonzepte</strong> <strong>in</strong><br />
<strong><strong>de</strong>r</strong> <strong>Praxis</strong><br />
Nach <strong>de</strong>m Standard SQL-99<br />
An impr<strong>in</strong>t of Pearson Education<br />
München Boston San Francisco Harlow, England<br />
Don Mills, Ontario Sydney Mexico City<br />
Madrid Amsterdam
Die Deutsche Bibliothek – CIP-E<strong>in</strong>heitsaufnahme<br />
E<strong>in</strong> Titeldatensatz für diese Publikation ist bei<br />
Der Deutschen Bibliothek erhältlich.<br />
Die Informationen <strong>in</strong> diesem Produkt wer<strong>de</strong>n ohne Rücksicht auf e<strong>in</strong>en eventuellen Patentschutz veröffentlicht.<br />
Warennamen wer<strong>de</strong>n ohne Gewährleistung <strong><strong>de</strong>r</strong> freien Verwendbarkeit benutzt. Bei <strong><strong>de</strong>r</strong> Zusammenstellung von<br />
Abbildungen und Texten wur<strong>de</strong> mit größter Sorgfalt vorgegangen. Trotz<strong>de</strong>m können Fehler nicht vollständig ausgeschlossen<br />
wer<strong>de</strong>n. Verlag, Herausgeber und Autoren können für fehlerhafte Angaben und <strong><strong>de</strong>r</strong>en Folgen we<strong><strong>de</strong>r</strong> e<strong>in</strong>e<br />
juristische Verantwortung noch irgen<strong>de</strong><strong>in</strong>e Haftung übernehmen. Für Verbesserungsvorschläge und H<strong>in</strong>weise auf<br />
Fehler s<strong>in</strong>d Verlag und Herausgeber dankbar.<br />
Alle Rechte vorbehalten, auch die <strong><strong>de</strong>r</strong> fotomechanischen Wie<strong><strong>de</strong>r</strong>gabe und <strong><strong>de</strong>r</strong> Speicherung <strong>in</strong> elektronischen Medien.<br />
Die gewerbliche Nutzung <strong><strong>de</strong>r</strong> <strong>in</strong> diesem Produkt gezeigten Mo<strong>de</strong>lle und Arbeiten ist nicht zulässig.<br />
Fast alle Hardware- und Softwarebezeichnungen, die <strong>in</strong> diesem Buch erwähnt wer<strong>de</strong>n, s<strong>in</strong>d gleichzeitig e<strong>in</strong>getragene<br />
Warenzeichen o<strong><strong>de</strong>r</strong> sollten als solche betrachtet wer<strong>de</strong>n.<br />
Umwelth<strong>in</strong>weis:<br />
Dieses Produkt wur<strong>de</strong> auf chlorfrei gebleichtem Papier gedruckt.<br />
Die E<strong>in</strong>schrumpffolie – zum Schutz vor Verschmutzung – ist aus umweltverträglichem<br />
und recycl<strong>in</strong>gfähigem PE-Material.<br />
5 4 3 2 1<br />
05 04 03 02<br />
ISBN 3-8273-1938-2<br />
© 2002 by Addison-Wesley Verlag,<br />
e<strong>in</strong> Impr<strong>in</strong>t <strong><strong>de</strong>r</strong> Pearson Education Deutschland GmbH<br />
Mart<strong>in</strong>-Kollar-Straße 10–12, D-81829 München/Germany<br />
Alle Rechte vorbehalten<br />
E<strong>in</strong>bandgestaltung: Hommer Design, Haar bei München<br />
Lektorat: Mart<strong>in</strong> Asbach, masbach@pearson.<strong>de</strong><br />
Korrektorat: Christ<strong>in</strong>e Depta, Freis<strong>in</strong>g<br />
Herstellung: Philipp Burkart, pburkart@pearson.<strong>de</strong><br />
Satz: reemers publish<strong>in</strong>g services gmbh, Krefeld, www.reemers.<strong>de</strong><br />
Druck und Verarbeitung: Kösel, Kempten<br />
Pr<strong>in</strong>ted <strong>in</strong> Germany
Inhaltsverzeichnis<br />
1 E<strong>in</strong>leitung 11<br />
2 Grundlagen von Datenbanken 15<br />
2.1 Motivation 15<br />
2.2 Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan« 20<br />
2.3 Vom »Bauplan« zur Datenbank 22<br />
2.4 Zusammenfassung 23<br />
2.5 Aufgaben 24<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan« 27<br />
3.1 Motivation 27<br />
3.2 Projektplan versus Phasenkonzept 31<br />
3.3 Konzeptioneller Entwurf (Datenmo<strong>de</strong>llierung) 35<br />
3.3.1 Grundlagen 35<br />
3.3.2 Fallbeispiel 36<br />
3.3.3 Geschäftsobjekte 37<br />
3.3.4 Sub- bzw. Supertypen 39<br />
3.3.5 Attribute und Schlüssel 40<br />
3.3.6 Beziehungen und Beziehungstypen 43<br />
3.4 »Entity-Relationship-Mo<strong>de</strong>ll« nach Chen 49<br />
3.4.1 Grundlagen 49<br />
3.4.2 Geschäftsobjekte 49<br />
3.4.3 Sub- bzw. Supertypen 49<br />
3.4.4 Attribute und Schlüssel 50<br />
3.4.5 Beziehungen und Beziehungstypen 50<br />
3.4.6 Fallbeispiel 52<br />
3.5 »Entity-Relationship-Mo<strong>de</strong>ll« nach Barker 55<br />
3.5.1 Grundlagen 55<br />
3.5.2 Geschäftsobjekte 55<br />
3.5.3 Sub- bzw. Supertypen 55<br />
3.5.4 Attribute und Schlüssel 55<br />
3.5.5 Beziehungen und Beziehungstypen 56<br />
3.5.6 Fallbeispiel 57<br />
3.6 »Unified Mo<strong>de</strong>l<strong>in</strong>g Language« 59<br />
3.6.1 Grundlagen 59<br />
3.6.2 Geschäftsobjekte 60<br />
3.6.3 Sub- bzw. Supertypen 61<br />
3.6.4 Attribute und Schlüssel 61<br />
3.6.5 Beziehungen und Beziehungstypen 62<br />
3.6.6 Fallbeispiel 63<br />
5
6<br />
Inhaltsverzeichnis<br />
3.7 Zusammenfassung 65<br />
3.8 Aufgaben 65<br />
4 Datenbankentwurf – Vom »Bauplan« zur Datenbankstruktur 69<br />
4.1 Motivation 69<br />
4.2 Relationenmo<strong>de</strong>ll 70<br />
4.3 Grundlagen <strong>de</strong>s Relationenmo<strong>de</strong>lls 71<br />
4.4 Umsetzung <strong>de</strong>s ERM <strong>in</strong> das Relationenmo<strong>de</strong>ll 73<br />
4.5 Fallbeispiel 77<br />
4.6 Zusammenfassung 77<br />
4.7 Aufgaben 79<br />
5 Normalisierung – Überprüfung <strong><strong>de</strong>r</strong> Datenbankstruktur 81<br />
5.1 Motivation 81<br />
5.2 Grundlagen <strong><strong>de</strong>r</strong> Normalisierung 82<br />
5.3 1. Normalform 85<br />
5.4 2. Normalform 86<br />
5.5 3. Normalform 87<br />
5.6 Weitere Normalformen 88<br />
5.7 Zusammenfassung 89<br />
5.8 Aufgaben 92<br />
6 SQL – Anlegen <strong><strong>de</strong>r</strong> Datenbankstruktur 95<br />
6.1 Motivation 95<br />
6.2 Grundlagen 95<br />
6.3 Datentypen 97<br />
6.4 Erzeugen und Bearbeiten e<strong>in</strong>er Tabelle 101<br />
6.4.1 Erzeugen e<strong>in</strong>er Tabelle 101<br />
6.4.2 Erstellen e<strong>in</strong>facher benutzer<strong>de</strong>f<strong>in</strong>ierter Datentypen 108<br />
6.4.3 Überprüfungen von Wertebereichen 109<br />
6.4.4 Reihen (Arrays) 110<br />
6.4.5 Än<strong><strong>de</strong>r</strong>n und Löschen 110<br />
6.5 Zusammenfassung 111<br />
6.6 Aufgaben 113<br />
7 E<strong>in</strong>fügen, Än<strong><strong>de</strong>r</strong>n, Löschen von Daten 115<br />
7.1 Motivation 115<br />
7.2 E<strong>in</strong>fügen von Datensätzen 115<br />
7.3 Löschen von Datensätzen 117<br />
7.4 Än<strong><strong>de</strong>r</strong>n von Datensätzen 118<br />
7.5 Zusammenfassung 120<br />
7.6 Aufgaben 120
Inhaltsverzeichnis<br />
8 E<strong>in</strong>e Tabelle abfragen 125<br />
8.1 Motivation 125<br />
8.2 Allgeme<strong>in</strong>er Aufbau e<strong>in</strong>er Abfrage 126<br />
8.3 Spalten auswählen 127<br />
8.4 »Built-<strong>in</strong>« -Funktionen 132<br />
8.4.1 Grundlagen 132<br />
8.4.2 »Numeric Value Functions« 132<br />
8.4.3 »Str<strong>in</strong>g Value Functions« 134<br />
8.4.4 »Datetime Value Functions« 137<br />
8.4.5 NULL-Funktionen und Datentypkonvertierung 137<br />
8.4.6 »Set Functions« 139<br />
8.5 Ausdrücke 142<br />
8.6 Sätze auswählen 143<br />
8.6.1 Grundlagen 143<br />
8.6.2 Vergleichsprädikate und IS NULL 144<br />
8.6.3 LIKE und SIMILAR Prädikat 145<br />
8.6.4 BETWEEN Prädikat 147<br />
8.6.5 IN Prädikat 147<br />
8.6.6 Logische Operatoren 148<br />
8.7 Sätze zusammenfassen 149<br />
8.8 Sätze sortieren 154<br />
8.9 Zusammenfassung 156<br />
8.10 Aufgaben 157<br />
9 Abfragen auf mehrere Tabellen 161<br />
9.1 Motivation 161<br />
9.2 Grundlagen 162<br />
9.3 CROSS JOIN 166<br />
9.4 INNER JOIN 166<br />
9.5 NATURAL JOIN 169<br />
9.6 OUTER JOIN 169<br />
9.7 »Jo<strong>in</strong>s« auf mehrere Tabellen 172<br />
9.8 Zusammenfassung 173<br />
9.9 Aufgaben 173<br />
10 Abfragen mit Unterabfragen 175<br />
10.1 Motivation 175<br />
10.2 Grundlagen 175<br />
10.3 Unterabfragen mit e<strong>in</strong>em Rückgabewert 177<br />
10.4 Unterabfragen mit e<strong>in</strong>er zurückgegebenen Zeile 178<br />
10.5 Unterabfragen mit mehreren zurückgegebenen Zeilen 178<br />
10.5.1 IN 178<br />
10.5.2 EXISTS 178<br />
10.5.3 ANY / SOME / ALL 180<br />
7
8<br />
Inhaltsverzeichnis<br />
10.6 Zusammenfassung 181<br />
10.7 Aufgaben 181<br />
11 Transaktionen 183<br />
11.1 Motivation 183<br />
11.2 Transaktionen 183<br />
11.3 ROLLBACK und COMMIT 184<br />
11.4 SAVEPOINT 186<br />
11.5 Mehrbenutzerbetrieb (»Concurreny Control« ) 187<br />
11.5.1 Grundlagen 187<br />
11.5.2 »Lost Update« 187<br />
11.5.3 »Dirty Read« 188<br />
11.5.4 »Non-repeatable Read« 188<br />
11.5.5 »Phantom Read« 189<br />
11.5.6 Isolationslevel 190<br />
11.6 Zusammenfassung 191<br />
11.7 Aufgaben 191<br />
12 »Stored Procedures« und »Prozedurale Sprachelemente« 193<br />
12.1 Motivation 193<br />
12.2 Rout<strong>in</strong>en 193<br />
12.3 Sprachelemente zur Kontrollsteuerung 197<br />
12.3.1 BEGIN...END 197<br />
12.3.2 IF...THEN...ELSE 198<br />
12.3.3 CASE 198<br />
12.3.4 REPEAT...UNTIL 199<br />
12.3.5 WHILE...DO 200<br />
12.3.6 LEAVE 200<br />
12.4 Beispiel: Bestellung erfassen 201<br />
12.5 Beispiel: Phonetischer Vergleich 202<br />
12.6 Zusammenfassung 205<br />
12.7 Aufgaben 206<br />
13 Trigger 209<br />
13.1 Motivation 209<br />
13.2 »Trigger« 209<br />
13.3 Erzeugen e<strong>in</strong>es »Triggers« 210<br />
13.4 Zusammenfassung 212<br />
13.5 Aufgaben 213<br />
14 »User Def<strong>in</strong>ed Types« (UDT) 215<br />
14.1 Motivation 215<br />
14.2 Objektorientierung 215<br />
14.3 Klassen 220<br />
14.4 Zugriff auf Attribute und Metho<strong>de</strong>n 221
Inhaltsverzeichnis<br />
14.5 Vererbung 222<br />
14.6 Zusammenfassung 223<br />
14.7 Aufgaben 223<br />
Literaturverzeichnis 225<br />
Stichwortverzeichnis 229<br />
9
1 E<strong>in</strong>leitung<br />
Bis En<strong>de</strong> <strong><strong>de</strong>r</strong> 60er Jahre wur<strong>de</strong> für Anwendungen das Dateisystem zum Speichern von<br />
Daten verwen<strong>de</strong>t. Je<strong>de</strong> Anwendung e<strong>in</strong>es Unternehmens speicherte <strong>in</strong> se<strong>in</strong>en eigenen<br />
Dateien die Daten, die es für die Anwendung benötigte. Dies führte zwangsläufig<br />
dazu, dass Daten mehrfach gehalten wur<strong>de</strong>n. Je<strong>de</strong> Anwendung, die z.B. Kun<strong>de</strong>ndaten<br />
benötigte, speicherte diese <strong>in</strong> <strong><strong>de</strong>r</strong> Regel selbständig <strong>in</strong> e<strong>in</strong>er eigenen Datei. Dadurch<br />
entstand e<strong>in</strong> regelrechtes »Datenchaos«, e<strong>in</strong> spezifischer Kun<strong>de</strong> <strong>de</strong>s Unternehmens<br />
wur<strong>de</strong> mehrmals mit <strong><strong>de</strong>r</strong> gleichen Adresse <strong>in</strong> <strong>de</strong>n Dateien gespeichert. Bei e<strong>in</strong>er Än<strong><strong>de</strong>r</strong>ung<br />
<strong><strong>de</strong>r</strong> Adresse mussten alle Dateien gleichzeitig angepasst wer<strong>de</strong>n.<br />
Aufgrund dieser Unzulänglichkeit und <strong>de</strong>s damit hervorgerufenen »Datenchaos« entstan<strong>de</strong>n<br />
En<strong>de</strong> <strong><strong>de</strong>r</strong> 60er Jahre die ersten Datenbanksysteme. Diese sollten zentral alle<br />
Daten e<strong>in</strong>es Unternehmens <strong>in</strong> e<strong>in</strong>er Datenbank speichern. Benötigte e<strong>in</strong>e Anwendung<br />
nun Kun<strong>de</strong>ndaten, so musste sie sich an das Datenbanksystem wen<strong>de</strong>n, um diese zu<br />
erhalten. Die Verwaltung <strong><strong>de</strong>r</strong> Daten wur<strong>de</strong> also <strong>de</strong>m Datenbanksystem übertragen,<br />
genau so wie e<strong>in</strong>e Bank das Geld ihrer Kun<strong>de</strong>n verwaltet.<br />
Diese Datenbanksysteme (hierarchische und Netzwerk-Datenbanksysteme) hatten<br />
jedoch e<strong>in</strong>en entschei<strong>de</strong>n<strong>de</strong>n Nachteil, sie waren aufgrund ihrer Struktur <strong>in</strong> <strong><strong>de</strong>r</strong><br />
Abfrage <strong><strong>de</strong>r</strong> Daten e<strong>in</strong>geschränkt. E<strong>in</strong>e Än<strong><strong>de</strong>r</strong>ung dieser Struktur erfor<strong><strong>de</strong>r</strong>te <strong>in</strong> <strong><strong>de</strong>r</strong><br />
Regel e<strong>in</strong>en erneuten Aufwand <strong>in</strong> <strong><strong>de</strong>r</strong> Programmierung. Noch heute s<strong>in</strong>d, gera<strong>de</strong> im<br />
Großrechnerbereich, hierarchische und auch Netzwerk-Datenbanken im E<strong>in</strong>satz. Das<br />
bekannteste hierarchische Datenbanksystem ist IMS von <strong><strong>de</strong>r</strong> Firma IBM.<br />
1970 konnten Mitglie<strong><strong>de</strong>r</strong> <strong>de</strong>s ACM (»Association for Comput<strong>in</strong>g Mach<strong>in</strong>ery«) im<br />
Datenbankjournal e<strong>in</strong>en Artikel von Dr. E. F. Ted Codd mit <strong>de</strong>m Titel »A Relational<br />
Mo<strong>de</strong>l of Data for Large Shared Data Banks« lesen. Dieser Artikel war die Grundlage<br />
für die Entwicklung <strong><strong>de</strong>r</strong> heute am häufigsten e<strong>in</strong>gesetzten Datenbanksysteme (weltweit<br />
etwa 75%), <strong>de</strong>n relationalen Datenbanksystemen. Das relationale Datenbankmo<strong>de</strong>ll<br />
hatte e<strong>in</strong>en entschei<strong>de</strong>n<strong>de</strong>n Vorteil: Än<strong><strong>de</strong>r</strong>ungen an <strong><strong>de</strong>r</strong> Struktur <strong><strong>de</strong>r</strong> Datenbank<br />
bewirkten nicht zwangläufig auch Modifizierungen an <strong>de</strong>n Anwendungsprogrammen.<br />
Auf Basis <strong>de</strong>s Artikels von Codd entwickelte die Firma IBM bis 1974 e<strong>in</strong>en Prototypen<br />
e<strong>in</strong>es relationalen Datenbanksystems, System/R. Um die Daten <strong>de</strong>s Datenbanksystems<br />
abzufragen, wur<strong>de</strong> e<strong>in</strong>e Datenbankabfragesprache entwickelt, die man SEQUEL<br />
nannte. Diese Sprache war <strong><strong>de</strong>r</strong> Vorläufer <strong>de</strong>s heutigen SQL (Structured Query Language),<br />
das 1999 von <strong>de</strong>n Normungsgremien <strong>de</strong>s »American National Standard Institute«<br />
(ANSI) <strong>in</strong> e<strong>in</strong>er dritten Fassung standardisiert wur<strong>de</strong>. Diese Fassung wird allgeme<strong>in</strong><br />
h<strong>in</strong> als SQL:1999 bzw. SQL-3 bezeichnet. SQL wird heute von allen gängigen relationalen<br />
Datenbankprodukten <strong>in</strong> verschie<strong>de</strong>nen Stufen unterstützt.<br />
Die wesentlichen Aufgaben e<strong>in</strong>es Datenbanksystems bestehen <strong>in</strong> <strong><strong>de</strong>r</strong> Verwaltung und<br />
Strukturierung von Daten. Jedoch gera<strong>de</strong> die zweite Aufgabe, die Strukturierung <strong><strong>de</strong>r</strong><br />
11
12<br />
1 E<strong>in</strong>leitung<br />
Daten, kann <strong>in</strong> <strong><strong>de</strong>r</strong> Regel nicht durch e<strong>in</strong>en Computer vorgenommen wer<strong>de</strong>n, da es<br />
sich um e<strong>in</strong>e analytische Aufgabe han<strong>de</strong>lt. Die Strukturierung <strong><strong>de</strong>r</strong> Daten, also das Entwerfen<br />
e<strong>in</strong>es Datenbankmo<strong>de</strong>lls, ist <strong>de</strong>shalb auch vielmehr e<strong>in</strong>e Aufgabe, die e<strong>in</strong> Analytiker<br />
mit Papier und Stift vornim<strong>mt</strong>. Genau so wie e<strong>in</strong> Architekt e<strong>in</strong>en »Bauplan« entwickeln<br />
muss, bevor er mit <strong>de</strong>m Bau e<strong>in</strong>es Gebäu<strong>de</strong>s beg<strong>in</strong>nt, muss auch <strong><strong>de</strong>r</strong> Architekt<br />
e<strong>in</strong>er Datenbank e<strong>in</strong>en »Bauplan« entwickeln, <strong><strong>de</strong>r</strong> die Struktur <strong><strong>de</strong>r</strong> zukünftigen Datenbank<br />
wi<strong><strong>de</strong>r</strong>spiegelt.<br />
Durch die Verbreitung <strong>de</strong>s Internets seit Anfang <strong><strong>de</strong>r</strong> 90er Jahre, die gekennzeichnet ist<br />
durch die Begriffe <strong>de</strong>s »Datenchaos« bzw. <strong><strong>de</strong>r</strong> »Informationsflut« , kom<strong>mt</strong> gera<strong>de</strong> <strong><strong>de</strong>r</strong><br />
Strukturierung von Daten heute e<strong>in</strong>e wichtige Rolle zu.<br />
Neben <strong>de</strong>m Internet waren die Anfänge <strong><strong>de</strong>r</strong> 90er Jahre geprägt durch die damals neuen<br />
Paradigmen <strong><strong>de</strong>r</strong> objektorientierten Softwareentwicklung. Diese Entwicklung ist gekennzeichnet<br />
durch Begriffe wie Komponenten, »Bus<strong>in</strong>ess Objects« (BO), Mehrschichtenmo<strong>de</strong>ll<br />
etc. Der erste SQL-Standard von 1986 (SQL-1) berücksichtigt diese Programmierparadigmen<br />
nicht.<br />
Vielmehr war SQL <strong>in</strong> <strong><strong>de</strong>r</strong> Anfangsphase u.a. auch als Abfragesprache für Endanwen<strong><strong>de</strong>r</strong><br />
gedacht, die durch E<strong>in</strong>gabe von SQL-Befehlen die gewünschten Daten gesucht<br />
haben. Der Zeit entsprechend war diese Vorgehensweise durchaus benutzerfreundlich.<br />
Mit <strong>de</strong>m Aufkommen grafischer Benutzeroberflächen wur<strong>de</strong>n Anwen<strong><strong>de</strong>r</strong> entsprechend<br />
anspruchsvoller. Heutzutage wird e<strong>in</strong> Anwen<strong><strong>de</strong>r</strong> es sicher zu Recht als Zumutung<br />
empf<strong>in</strong><strong>de</strong>n, SQL-Befehle e<strong>in</strong>geben zu müssen, um z.B. die Rechnungsdaten e<strong>in</strong>es<br />
Kun<strong>de</strong>n zu erhalten.<br />
Daher wird SQL heute vorwiegend <strong>in</strong> <strong><strong>de</strong>r</strong> Softwareentwicklung e<strong>in</strong>gesetzt. Dem wird<br />
entsprechend <strong>de</strong>n neuen Paradigmen <strong>in</strong> <strong><strong>de</strong>r</strong> Softwareentwicklung im zweiten und im<br />
dritten Standard von 1992 und 1999 (SQL-2 und SQL-3) Rechnung getragen. Hier wird<br />
die Leichtigkeit <strong><strong>de</strong>r</strong> Verwendung von SQL eher aus Entwicklersicht, <strong>de</strong>nn aus Anwen<strong><strong>de</strong>r</strong>sicht<br />
betrachtet.<br />
Das vorliegen<strong>de</strong> Buch hat das Ziel, e<strong>in</strong>en praxisorientierten Ansatz zur Beantwortung<br />
<strong><strong>de</strong>r</strong> folgen<strong>de</strong>n Fragen zu geben:<br />
� Wie komme ich von <strong><strong>de</strong>r</strong> Realität zu e<strong>in</strong>er Datenbank?<br />
� Welche grundlegen<strong>de</strong>n Sprachelemente enthält SQL?<br />
� Welche neuen Konzepte von SQL wer<strong>de</strong>n heutzutage <strong>in</strong> <strong><strong>de</strong>r</strong> Anwendungsentwicklung<br />
verwen<strong>de</strong>t?<br />
Der Inhalt dieses Buches baut auf Vorlesungen auf, die ich an <strong><strong>de</strong>r</strong> Fachhochschule<br />
Westküste im Fachbereich Betriebswirtschaftslehre, Schwerpunkt Wirtschafts<strong>in</strong>formatik,<br />
über Datenbanken gehalten habe.<br />
Dementsprechend wen<strong>de</strong>t es sich primär an Personen, die <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>Praxis</strong> e<strong>in</strong> Datenbankmo<strong>de</strong>ll<br />
entwerfen sollen, aber auch an solche, die sich <strong>in</strong>nerhalb <strong><strong>de</strong>r</strong> Anwendungsentwicklung<br />
mit SQL beschäftigen und hierfür e<strong>in</strong>e soli<strong>de</strong> E<strong>in</strong>führung benötigen.<br />
Gera<strong>de</strong> das Thema <strong><strong>de</strong>r</strong> Anwendungsentwicklung soll hierbei e<strong>in</strong> Schwerpunkt bil<strong>de</strong>n,<br />
da viele Erweiterungen im SQL-Standard h<strong>in</strong>zugekommen s<strong>in</strong>d, die Programmierparadigmen<br />
wie »Bus<strong>in</strong>ess Objects« und Mehrschichtenmo<strong>de</strong>ll unterstützen. Dabei
E<strong>in</strong>leitung<br />
gehe ich vorwiegend auf die SQL-Bestandteile »Stored Procedures« , »Trigger« und<br />
benutzer<strong>de</strong>f<strong>in</strong>ierte Datentypen bzw. UDT (»User Def<strong>in</strong>ed Types« ) e<strong>in</strong>. Gera<strong>de</strong> diese<br />
Bestandteile ersche<strong>in</strong>en mir sehr wichtig, da damit e<strong>in</strong>e grundlegen<strong>de</strong> Än<strong><strong>de</strong>r</strong>ung <strong><strong>de</strong>r</strong><br />
Programmierung von Datenbanken e<strong>in</strong>hergeht und dieses Thema <strong>in</strong> <strong><strong>de</strong>r</strong> bisherigen<br />
Datenbank-Literatur nur »stiefmütterlich« o<strong><strong>de</strong>r</strong> gar nicht behan<strong>de</strong>lt wird.<br />
Da SQL-3 und auch SQL-2 nicht vollständig von <strong>de</strong>n heutigen Datenbankprodukten<br />
unterstützt wer<strong>de</strong>n, wird nur auf solche Sprachelemente e<strong>in</strong>gegangen, die <strong>in</strong> <strong>de</strong>n gängigen<br />
relationalen Datenbankprodukten (Oracle, Informix, IBM DB/2, Sybase, Microsoft<br />
SQL Server, Borland InterbaseBase) enthalten s<strong>in</strong>d.<br />
Dieses Buch glie<strong><strong>de</strong>r</strong>t sich damit <strong>in</strong> folgen<strong>de</strong> Kapitel:<br />
� Kapitel 1 gibt e<strong>in</strong>e kurze E<strong>in</strong>leitung und e<strong>in</strong>e Übersicht über das vorliegen<strong>de</strong> Buch.<br />
� Kapitel 2 behan<strong>de</strong>lt die Probleme, die e<strong>in</strong> Datenbanksystem beseitigen soll und gibt<br />
e<strong>in</strong>en ersten Überblick über die Schritte, die von e<strong>in</strong>em realen Problem zu e<strong>in</strong>er<br />
Datenbank führen.<br />
� Kapitel 3 und 4 gehen auf die Datenmo<strong>de</strong>llierung <strong>de</strong>s realen Problems e<strong>in</strong>. Hierbei<br />
wer<strong>de</strong>n das Entity-Relationship-Mo<strong>de</strong>ll (ERM) und das Relationenmo<strong>de</strong>ll behan<strong>de</strong>lt.<br />
In Kapitel 3 wird auch kurz auf unterschiedliche Notationen <strong>de</strong>s Entity-Relationship-Mo<strong>de</strong>lls<br />
und auf die Verwendung <strong><strong>de</strong>r</strong> »Unified Mo<strong>de</strong>l<strong>in</strong>g Language«<br />
(UML) zur Datenmo<strong>de</strong>llierung e<strong>in</strong>gegangen.<br />
� Kapitel 5 behan<strong>de</strong>lt die Überprüfung bzw. Optimierung <strong><strong>de</strong>r</strong> Datenbankstruktur mit<br />
Hilfe <strong><strong>de</strong>r</strong> sogenannten Normalformen.<br />
� Kapitel 6 gibt e<strong>in</strong>e E<strong>in</strong>führung <strong>in</strong> SQL und beschreibt, wie man e<strong>in</strong>e Datenbankstruktur<br />
anlegt bzw. wie<strong><strong>de</strong>r</strong> än<strong><strong>de</strong>r</strong>t und löscht.<br />
� Kapitel 7 geht auf das E<strong>in</strong>fügen, Än<strong><strong>de</strong>r</strong>n und Löschen von Daten <strong>in</strong> SQL e<strong>in</strong>.<br />
� Kapitel 8 behan<strong>de</strong>lt e<strong>in</strong>fache Abfragen <strong>in</strong> SQL.<br />
� Kapitel 9 beschäftigt sich mit Abfragen, bezogen auf mehrere Tabellen.<br />
� Kapitel 10 erläutert Abfragen <strong>in</strong>nerhalb von Abfragen.<br />
� Kapitel 11 beschäftigt sich mit Transaktionen.<br />
� Die Kapitel 12 bis 14 behan<strong>de</strong>ln die Sprachkonstrukte für benutzer<strong>de</strong>f<strong>in</strong>ierte Datentypen<br />
(UDT), »Stored Procedures« und »Trigger« .<br />
Zur Veranschaulichung <strong><strong>de</strong>r</strong> angesprochenen Themen wird <strong>de</strong>n Leser das gesa<strong>mt</strong>e Buch<br />
h<strong>in</strong>durch e<strong>in</strong>e fiktive Firma begleiten, die alle Phasen vom »Datenchaos« bis zur fertigen<br />
Datenbank durchläuft.<br />
Je<strong>de</strong>s Kapitel beg<strong>in</strong>nt mit Fragen, die anschließend beantwortet wer<strong>de</strong>n und en<strong>de</strong>t mit<br />
e<strong>in</strong>er Zusammenfassung sowie problemspezifischen Aufgaben.<br />
Zur praktischen Durchführung <strong><strong>de</strong>r</strong> Aufgaben ab <strong>de</strong>m 6. Kapitel empfehle ich die Nutzung<br />
von Testversionen <strong><strong>de</strong>r</strong> Datenbanksoftware, die von allen gängigen Datenbankherstellern<br />
im Internet zum Download bereitgestellt wer<strong>de</strong>n und die <strong>in</strong> <strong><strong>de</strong>r</strong> Regel bis<br />
zu e<strong>in</strong>em bestim<strong>mt</strong>en Datum lauffähig s<strong>in</strong>d (die Internetadressen hierzu f<strong>in</strong><strong>de</strong>n Sie im<br />
Internet unter »http://www.addison-wesley.<strong>de</strong>/DBMS« ).<br />
13
14<br />
1 E<strong>in</strong>leitung<br />
Das Datenbanksystem mySQL, das <strong>in</strong> e<strong>in</strong>er Version für L<strong>in</strong>ux kostenlos erhältlich ist,<br />
kann ich nur e<strong>in</strong>geschränkt zur Lösung <strong><strong>de</strong>r</strong> Aufgaben empfehlen, da wesentliche Elemente<br />
e<strong>in</strong>es relationalen Datenbanksystems fehlen (Transaktionen nur bed<strong>in</strong>gt, Unterabfragen,<br />
»Stored Procedures« etc.).<br />
Falls Sie noch Fragen, Anregungen o<strong><strong>de</strong>r</strong> Kommentare haben, können Sie mich unter<br />
folgen<strong><strong>de</strong>r</strong> E-Mail-Adresse erreichen: soenke.cordts@addison-wesley.<strong>de</strong>.
2 Grundlagen<br />
von<br />
Datenbanken<br />
In Kapitel 2 sollen folgen<strong>de</strong> Fragen geklärt wer<strong>de</strong>n:<br />
� Wor<strong>in</strong> bestehen die Probleme herkömmlicher Datenspeicherung?<br />
� Warum sollte ich mich mit Datenbanken beschäftigen?<br />
� Wie komme ich von <strong><strong>de</strong>r</strong> Realität zu e<strong>in</strong>em »Bauplan« für me<strong>in</strong>e Datenbank?<br />
� Wie setze ich <strong>de</strong>n »Bauplan« so um, dass ich Daten <strong>in</strong> me<strong>in</strong>er Datenbank speichern<br />
und wie<strong><strong>de</strong>r</strong>f<strong>in</strong><strong>de</strong>n kann?<br />
2.1 Motivation<br />
Um die Probleme herkömmlicher Datenspeicherung zu verstehen, betrachten wir<br />
zunächst unsere fiktive Firma »KartoF<strong>in</strong>ale«, <strong><strong>de</strong>r</strong>en Hauptgeschäftszweck im Verkauf<br />
und <strong>in</strong> <strong><strong>de</strong>r</strong> Abrechnung von E<strong>in</strong>trittskarten besteht.<br />
In <strong><strong>de</strong>r</strong> Firma »KartoF<strong>in</strong>ale« arbeiten verschie<strong>de</strong>ne Personen. Neben <strong>de</strong>m Geschäftsführer,<br />
Herrn Kowalski, existieren die Abteilungen Rechnungswesen, Vertrieb, E<strong>in</strong>kauf<br />
und Technik.<br />
Zum Vertrieb gehören Frau Klug, Herr Kle<strong>in</strong>, die Stu<strong>de</strong>nten Inga und Klaus, die für<br />
<strong>de</strong>n Verkauf <strong><strong>de</strong>r</strong> E<strong>in</strong>trittskarten zuständig s<strong>in</strong>d und als Abteilungsleiter<strong>in</strong> Frau Kart.<br />
Im Rechnungswesen ist Herr Wun<strong><strong>de</strong>r</strong> für das Schreiben <strong><strong>de</strong>r</strong> Rechnungen, die Buchhaltung<br />
usw. eigenverantwortlich zuständig. Schließlich gibt es noch Herrn Münze, <strong><strong>de</strong>r</strong><br />
für die Personalabrechung verantwortlich ist.<br />
Herr Wun<strong><strong>de</strong>r</strong><br />
Frau Klug<br />
Herr Kowalski<br />
Geschäftsführung<br />
Inga und Klaus<br />
Frau Kart<br />
Herr Kle<strong>in</strong><br />
Rechnungswesen Vertrieb<br />
Personal<br />
Abbildung 2.1: Das Unternehmen »KartoF<strong>in</strong>ale«<br />
�<br />
�<br />
Herr Münze<br />
�<br />
15
16<br />
2 Grundlagen von Datenbanken<br />
Da E<strong>in</strong>trittskarten telefonisch verkauft und versen<strong>de</strong>t wer<strong>de</strong>n, muss Herr Wun<strong><strong>de</strong>r</strong><br />
je<strong>de</strong>n Tag Rechnungen schreiben. Dazu verwen<strong>de</strong>t er e<strong>in</strong> Textverarbeitungsprogramm.<br />
Um sich die Arbeit zu erleichtern, hat er sich e<strong>in</strong>e Textdatei angelegt, <strong>in</strong> <strong><strong>de</strong>r</strong> er die<br />
Adressen <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n speichert.<br />
In <strong><strong>de</strong>r</strong> Abteilung »Vertrieb« hat Herr Kle<strong>in</strong> von se<strong>in</strong>er Vorgesetzten, Frau Kart, <strong>de</strong>n<br />
Auftrag bekommen, die Kun<strong>de</strong>n per Postversand über die aktuellen Veranstaltungen<br />
zu benachrichtigen. Kun<strong>de</strong>n mit K<strong>in</strong><strong><strong>de</strong>r</strong>n soll e<strong>in</strong> beson<strong><strong>de</strong>r</strong>er Rabatt gewährt wer<strong>de</strong>n,<br />
<strong>de</strong>mentsprechend sollen Kun<strong>de</strong>n mit K<strong>in</strong><strong><strong>de</strong>r</strong>n natürlich e<strong>in</strong>en an<strong><strong>de</strong>r</strong>en Werbebrief<br />
erhalten.<br />
Da Herr Kle<strong>in</strong> weiß, dass Herr Wun<strong><strong>de</strong>r</strong> die Kun<strong>de</strong>ndaten <strong>in</strong> e<strong>in</strong>er Textdatei gespeichert<br />
hat, holt er sich diese von Herrn Kle<strong>in</strong> und liest sie <strong>in</strong> se<strong>in</strong> Tabellenkalkulationsprogramm<br />
e<strong>in</strong>. Danach ergänzt er die Tabelle um e<strong>in</strong> Feld für die Namen <strong><strong>de</strong>r</strong> K<strong>in</strong><strong><strong>de</strong>r</strong>.<br />
Rechnungswesen<br />
Name Vorname Adresse<br />
Muster Hans Musterweg 12, 22222 Karlstadt<br />
Wegerich Frieda Wan<strong><strong>de</strong>r</strong>str 89, 33333 Rettrich<br />
Bolte Bertram Bahnstr 12, 33333 Rettrich<br />
...<br />
Herr Wun<strong><strong>de</strong>r</strong><br />
Herr Kle<strong>in</strong><br />
Vertrieb<br />
Name Vorname Strasse Ort K<strong>in</strong><strong><strong>de</strong>r</strong><br />
Muster Hans Musterweg 12 22222 Karlstadt -<br />
Wegerich Frieda Wan<strong><strong>de</strong>r</strong>str 89 33333 Rettrich Ursula, Enzo<br />
Bolte Bertram Bahnstr 12 33333 Rettrich Katja, Thomas, Karl<br />
...<br />
Abbildung 2.2: Kun<strong>de</strong>ndaten mehrfach <strong>de</strong>zentral gespeichert<br />
Inzwischen s<strong>in</strong>d drei Tage vergangen und bei Herrn Wun<strong><strong>de</strong>r</strong> kl<strong>in</strong>gelt das Telefon. Herr<br />
Bolte, e<strong>in</strong> wichtiger Kun<strong>de</strong> von »KartoF<strong>in</strong>ale« teilt Herrn Wun<strong><strong>de</strong>r</strong> mit, dass sich se<strong>in</strong>e<br />
Adresse geän<strong><strong>de</strong>r</strong>t hat. Herr Wun<strong><strong>de</strong>r</strong> än<strong><strong>de</strong>r</strong>t die Adressdaten, vergisst aber, Herrn Kle<strong>in</strong><br />
davon zu benachrichtigen.<br />
Ebenso stellt Herr Kle<strong>in</strong> bei <strong><strong>de</strong>r</strong> Durchsicht se<strong>in</strong>er Adressdaten fest, dass <strong><strong>de</strong>r</strong> Name von<br />
Frau Wegerich falsch geschrieben ist, entsprechend korrigiert er <strong>de</strong>n Namen <strong>in</strong> Wiegerich<br />
ohne se<strong>in</strong>erseits Herrn Wun<strong><strong>de</strong>r</strong> davon zu benachrichtigen.<br />
Mit <strong><strong>de</strong>r</strong> Zeit treten mehrere solcher Fälle auf: Kun<strong>de</strong>n wer<strong>de</strong>n neu <strong>in</strong> die Adressdateien<br />
aufgenommen bzw. gelöscht, Adressän<strong><strong>de</strong>r</strong>ungen f<strong>in</strong><strong>de</strong>n statt, ohne dass diese zwischen<br />
<strong>de</strong>n bei<strong>de</strong>n Abteilungen abgeglichen wer<strong>de</strong>n.<br />
Nach zwei Wochen beauftragt Frau Kart Herrn Kle<strong>in</strong> erneut, e<strong>in</strong>e Werbebriefkampagne<br />
zu starten. Da Herr Kle<strong>in</strong> se<strong>in</strong>e eigenen Adressdaten hat, verwen<strong>de</strong>t er diese, um die
Motivation<br />
Briefe zu versen<strong>de</strong>n. Diesmal kommen jedoch Briefe zurück, da Adressen nicht mehr<br />
stimmen. Neue Kun<strong>de</strong>n, die ausschließlich <strong>in</strong> <strong><strong>de</strong>r</strong> Abteilung »Rechnungswesen« <strong>in</strong> die<br />
Adressdatei aufgenommen wur<strong>de</strong>n, wer<strong>de</strong>n gar nicht benachrichtigt.<br />
Um dieses Problem zu lösen, wird <strong>in</strong> e<strong>in</strong>em Meet<strong>in</strong>g zwischen Frau Kart, Herrn Kle<strong>in</strong><br />
und Herrn Wun<strong><strong>de</strong>r</strong> entschie<strong>de</strong>n, dass nur noch e<strong>in</strong>e Adressdatei verwen<strong>de</strong>t wer<strong>de</strong>n<br />
soll. Frau Kart beauftragt Herrn Kle<strong>in</strong>, die bei<strong>de</strong>n Dateien abzugleichen, so dass nur<br />
noch e<strong>in</strong>e Datei verwen<strong>de</strong>t wird. Neben <strong>de</strong>n bisherigen Adressdaten sollen zusätzlich<br />
auch die Rechnungsdaten <strong>in</strong> dieser Datei h<strong>in</strong>terlegt wer<strong>de</strong>n.<br />
Nach zwei Tagen hat Herr Kle<strong>in</strong> die Unstimmigkeiten beseitigt und legt die Datei auf<br />
e<strong>in</strong>em Computer ab, auf <strong>de</strong>n sowohl Herr Kle<strong>in</strong>, als auch Herr Wun<strong><strong>de</strong>r</strong> über das<br />
firmen<strong>in</strong>terne Netzwerk zugreifen können.<br />
Herr Wun<strong><strong>de</strong>r</strong> Herr Kle<strong>in</strong><br />
Rechnungswesen<br />
Vertrieb<br />
Name Vorname Strasse Ort K<strong>in</strong><strong><strong>de</strong>r</strong> Rechnungsnr. Betrag Veranstaltung<br />
Muster<br />
Muster<br />
Muster<br />
Wiegerich<br />
Hans<br />
Hans<br />
Hans<br />
Frieda<br />
Musterweg 12<br />
Muterweg 12<br />
Musterweg 12<br />
Wan<strong><strong>de</strong>r</strong>str 89<br />
22222 Karlstadt<br />
22222 Karlstadt<br />
22222 Karstadt<br />
33333 Rettrich 2<br />
<br />
3<br />
<br />
Ursula, Enzo<br />
21<br />
43<br />
123<br />
33<br />
98,00 DM<br />
214,99 DM<br />
98,00 DM<br />
120,00 DM<br />
Mephisto<br />
Tristan und Isol<strong>de</strong><br />
Mefisto<br />
Tristan/Isol<strong>de</strong><br />
Bolte<br />
...<br />
Bertram Busweg 12 44444 Kohlscheidt Katja, Thomas, Karl ---<br />
Abbildung 2.3: Kun<strong>de</strong>ndaten zentral gespeichert<br />
Dabei s<strong>in</strong>d Herrn Kle<strong>in</strong> e<strong>in</strong>ige Fehler unterlaufen, so hat er gleiche Veranstaltungen<br />
unterschiedlich bezeichnet (1). Pro Rechnung hat Herr Kle<strong>in</strong> e<strong>in</strong>e Zeile <strong>in</strong> <strong><strong>de</strong>r</strong> Datei vorgesehen.<br />
Hat e<strong>in</strong> Kun<strong>de</strong> mehrere Rechnungen erhalten, so wie Herr Muster, so muss<br />
die Adresse <strong>in</strong> je<strong><strong>de</strong>r</strong> Zeile wie<strong><strong>de</strong>r</strong>holt wer<strong>de</strong>n. Auch hierbei s<strong>in</strong>d Herrn Kle<strong>in</strong> Fehler<br />
unterlaufen (2).<br />
Am nächsten Tag schreibt Herr Wun<strong><strong>de</strong>r</strong> e<strong>in</strong>e Rechnung für Frau Wiegerich. Dazu öffnet<br />
er die neue Adressdatei. Zur gleichen Zeit öffnet auch Herr Kle<strong>in</strong> die Datei, da er<br />
die Daten noch e<strong>in</strong>mal überprüfen und ggf. korrigieren möchte.<br />
Nach<strong>de</strong>m Herr Wun<strong><strong>de</strong>r</strong> die Rechnungsdaten für Frau Wiegerich e<strong>in</strong>gegeben hat, speichert<br />
er die Datei. Herr Kle<strong>in</strong> bekom<strong>mt</strong> davon nichts mit, da er die Adressdatei ja vorher<br />
schon geöffnet hatte. Also korrigiert er die Fehler und speichert die Datei danach.<br />
Dabei überschreibt er unwissentlich die von Herrn Wun<strong><strong>de</strong>r</strong> neu e<strong>in</strong>gegebenen Rechnungsdaten.<br />
Herr Kle<strong>in</strong> hat sich <strong>in</strong> <strong><strong>de</strong>r</strong> Zwischenzeit mit <strong><strong>de</strong>r</strong> Serienbrieffunktionalität se<strong>in</strong>es Textverarbeitungsprogrammes<br />
ause<strong>in</strong>an<strong><strong>de</strong>r</strong>gesetzt. Damit kann er nun Serienbriefe an<br />
Adressaten ohne K<strong>in</strong><strong><strong>de</strong>r</strong> erstellen, abhängig davon, ob im Feld zur Angabe <strong><strong>de</strong>r</strong> K<strong>in</strong><strong><strong>de</strong>r</strong><br />
<strong><strong>de</strong>r</strong> Wert »« steht (3). Inzwischen ist jedoch Herr Wun<strong><strong>de</strong>r</strong> auf die I<strong>de</strong>e gekom-<br />
1<br />
17
18<br />
2 Grundlagen von Datenbanken<br />
men, für das Nichtvorhan<strong>de</strong>nse<strong>in</strong> von K<strong>in</strong><strong><strong>de</strong>r</strong>n e<strong>in</strong>en B<strong>in</strong><strong>de</strong>strich zu verwen<strong>de</strong>n. Der<br />
Serienbrief von Herrn Kle<strong>in</strong> für se<strong>in</strong>e Werbekampagne wird damit nicht mehr korrekt<br />
erstellt.<br />
Frau Kart möchte alle Mitarbeiter darüber benachrichtigen, dass auf <strong>de</strong>m zentralen<br />
Computer die Adressen <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n gespeichert s<strong>in</strong>d. Frau Kart weiß, dass Herr<br />
Münze von <strong><strong>de</strong>r</strong> Personalabteilung alle Adressen <strong><strong>de</strong>r</strong> Mitarbeiter <strong>in</strong> e<strong>in</strong>er Datei gespeichert<br />
hat. Sie bittet Herrn Münze <strong>de</strong>shalb, se<strong>in</strong>e Datei auf <strong>de</strong>m zentralen Computer<br />
abzulegen, damit sowohl Herr Münze als auch an<strong><strong>de</strong>r</strong>e Mitarbeiter auf die Mitarbeiteradressen<br />
zugreifen können. Da jedoch auch das Gehalt <strong><strong>de</strong>r</strong> jeweiligen Mitarbeiter <strong>in</strong><br />
dieser Datei steht, kann Herr Münze <strong><strong>de</strong>r</strong> Bitte von Frau Kart nicht nachkommen.<br />
Fassen wir noch e<strong>in</strong>mal die Probleme zusammen, die im obigen Szenario aufgetreten<br />
s<strong>in</strong>d:<br />
� Daten wer<strong>de</strong>n »mehrfach« <strong>de</strong>zentral gespeichert (Datenredundanz).<br />
� Dadurch »laufen« die Daten ause<strong>in</strong>an<strong><strong>de</strong>r</strong> und s<strong>in</strong>d nicht mehr konsistent (Daten<strong>in</strong>tegrität).<br />
� Auch bei zentraler Speicherung wer<strong>de</strong>n Daten trotz<strong>de</strong>m noch »mehrfach« gespeichert<br />
(Datenredundanz),<br />
Beispiel: pro Rechnung wer<strong>de</strong>n die Adressdaten zusätzlich gespeichert.<br />
� Än<strong><strong>de</strong>r</strong>ungen <strong>de</strong>s Datenformates bzw. <strong><strong>de</strong>r</strong> Semantik <strong><strong>de</strong>r</strong> Daten bewirken, dass bestim<strong>mt</strong>e<br />
Programme nicht mehr korrekt funktionieren (Datenabhängigkeit),<br />
Beispiel: Serienbrief.<br />
� Bei gleichzeitigem Zugriff besteht die Gefahr <strong>de</strong>s gegenseitigen Überschreibens von<br />
Daten (Mehrbenutzerbetrieb, Synchronisation).<br />
� Unterschiedliche Sichten auf Daten (Datensicht),<br />
Beispiel: Abteilung Personal und Market<strong>in</strong>g.<br />
� Nicht je<strong><strong>de</strong>r</strong> darf alle Daten sehen (Datensicherheit),<br />
Beispiel: Gehaltsdaten.<br />
Unser erstes Problem war relativ e<strong>in</strong>fach zu beseitigen: Wir mussten unsere Daten zentral<br />
für alle Mitarbeiter zugreifbar machen.<br />
Alle Probleme, die danach auftraten, bestan<strong>de</strong>n <strong>in</strong> <strong><strong>de</strong>r</strong> unzureichen<strong>de</strong>n Kontrollaufsicht<br />
unserer Datei (Um alle Aufgaben korrekt zu erledigen, müsste <strong>in</strong> unserem Beispiel<br />
e<strong>in</strong> e<strong>in</strong>ziger Mitarbeiter alle<strong>in</strong>e für die Datei zuständig se<strong>in</strong>, dort Än<strong><strong>de</strong>r</strong>ungen<br />
vornehmen, Auskünfte geben, Rechnungen schreiben usw.)<br />
Es ist <strong>de</strong>shalb notwendig, unsere Daten unter die »Obhut« e<strong>in</strong>es eigenen Softwareprogrammes<br />
zu geben, das die Daten verwaltet.<br />
Diese Software wird im Allgeme<strong>in</strong>en als Datenbank-Management-System (DBMS)<br />
bezeichnet. Die Aufgaben <strong>de</strong>s DBMS bestehen <strong>in</strong> <strong><strong>de</strong>r</strong> Beseitigung <strong><strong>de</strong>r</strong> oben aufgeführten<br />
Probleme.
7.<br />
Datenunabhängigkeit<br />
6.<br />
Datensicherheit<br />
5.<br />
Datenschutz<br />
Motivation<br />
1.<br />
Redundanzabbau<br />
DBMS<br />
2.<br />
Integrität<br />
4.<br />
Synchronisation<br />
3.<br />
Benutzersichten<br />
Abbildung 2.4: Aufgaben e<strong>in</strong>es Datenbank-Management-Systems<br />
Unter e<strong>in</strong>em Datenbank-Management-System (DBMS) versteht man also e<strong>in</strong>e Software<br />
zur Verwaltung von Datenbanken. E<strong>in</strong>e Datenbank (DB) wie<strong><strong>de</strong>r</strong>um stellt e<strong>in</strong>en zusammengehörigen<br />
Datenbestand dar (z.B. alle Daten <strong><strong>de</strong>r</strong> Abteilung Personal o<strong><strong>de</strong>r</strong> alle<br />
Adressdaten e<strong>in</strong>es Unternehmens). Alle Datenbanken zusammen bil<strong>de</strong>n die gesa<strong>mt</strong>e<br />
Datenbasis e<strong>in</strong>es Datenbank-Management-Systems.<br />
Datenbank-Management-System und Datenbanken bezeichnet man entsprechend als<br />
Datenbanksystem (DBS).<br />
Datenbank-Management-Systeme s<strong>in</strong>d heutzutage allgegenwärtig, auch wenn man als<br />
Anwen<strong><strong>de</strong>r</strong> nicht unmittelbar mit ihnen <strong>in</strong> Berührung kom<strong>mt</strong>. Heben Sie an e<strong>in</strong>em<br />
Bankterm<strong>in</strong>al Geld ab, so steht dah<strong>in</strong>ter immer e<strong>in</strong> Datenbank-Management-System,<br />
das die Kun<strong>de</strong>ndaten abruft, Überprüfungen vornim<strong>mt</strong> und <strong>de</strong>n neuen Kontostand<br />
speichert. Egal, ob Geld am Bankterm<strong>in</strong>al abgehoben wird o<strong><strong>de</strong>r</strong> ob per Onl<strong>in</strong>e-Bank<strong>in</strong>g<br />
Geld bei e<strong>in</strong>er Bank überwiesen wird, e<strong>in</strong> DBMS nim<strong>mt</strong> diese Transaktion vor und<br />
steuert <strong>de</strong>n Ablauf <strong><strong>de</strong>r</strong> Daten.<br />
Ob Dienstleistungen durchgeführt o<strong><strong>de</strong>r</strong> Produkte gefertigt wer<strong>de</strong>n, <strong>in</strong> <strong><strong>de</strong>r</strong> Regel wer<strong>de</strong>n<br />
die dabei anfallen<strong>de</strong>n Daten <strong>in</strong> Datenbanken gespeichert und durch das DBMS<br />
verwaltet.<br />
1998 umfasste <strong><strong>de</strong>r</strong> Umsatz mit Datenbank-Management-Systemen 7,1 Mrd. US $ (vgl.<br />
hierzu [Panny99]). Diese Summe umfasst <strong>de</strong>n re<strong>in</strong>en Verkaufsumsatz von Datenbank-<br />
Management-Systemen. Dar<strong>in</strong> s<strong>in</strong>d nicht enthalten: Betrieb <strong>de</strong>s DBMS, Beratung, Programmierung<br />
usw. Diese Zahl macht <strong>de</strong>utlich, welche zentrale Rolle Datenbank-<br />
Management-Systeme gera<strong>de</strong> im kommerziellen Bereich <strong><strong>de</strong>r</strong> Informationstechnologie<br />
spielen.<br />
19
20<br />
DB<br />
Personal<br />
2 Grundlagen von Datenbanken<br />
Anwen<strong><strong>de</strong>r</strong><br />
Datenbankanfragen<br />
DBMS<br />
Datenbank-Management-System<br />
DB<br />
Rechnungswesen<br />
����������� ����<br />
Datenbanksystem (DBS)<br />
DB<br />
Vertrieb<br />
Abbildung 2.5: DBMS, DB und DBS<br />
2.2 Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
E<strong>in</strong> Architekt erstellt vor <strong>de</strong>m Bau e<strong>in</strong>es Gebäu<strong>de</strong>s <strong>in</strong> <strong><strong>de</strong>r</strong> Regel e<strong>in</strong>en Projektplan, <strong>in</strong><br />
<strong>de</strong>m er festlegt, welche Tätigkeiten <strong>in</strong> welcher Reihenfolge zu erfolgen haben. Kernpunkt<br />
<strong>de</strong>s Projektplanes ist die Bestimmung <strong>de</strong>s eigentlichen Zwecks <strong>de</strong>s Gebäu<strong>de</strong>s.<br />
Ebenso wie <strong><strong>de</strong>r</strong> Architekt muss auch <strong><strong>de</strong>r</strong> Datenbank-Designer geme<strong>in</strong>sam mit <strong>de</strong>m<br />
Kun<strong>de</strong>n zuerst <strong>de</strong>n Zweck <strong><strong>de</strong>r</strong> zu erstellen<strong>de</strong>n Datenbank und zukünftiger Anwendungssoftware<br />
ermitteln, <strong>de</strong>nn die Zweckbestimmung legt letztendlich fest, welche<br />
Daten als relevant anzusehen s<strong>in</strong>d. So ist es sicherlich möglich, <strong>in</strong> e<strong>in</strong>er Datenbank die<br />
Liebl<strong>in</strong>gsspeise e<strong>in</strong>es Kun<strong>de</strong>n zu speichern. Diese Information ist für das eigentliche<br />
Kerngeschäft e<strong>in</strong>es Unternehmens jedoch <strong>in</strong> <strong><strong>de</strong>r</strong> Regel nicht relevant, es sei <strong>de</strong>nn, es<br />
han<strong>de</strong>lt sich um e<strong>in</strong> Fe<strong>in</strong>schmecker-Restaurant o.ä.<br />
Neben <strong><strong>de</strong>r</strong> Zweckbestimmung erstellt <strong><strong>de</strong>r</strong> Datenbankarchitekt e<strong>in</strong>en Projektplan, <strong>in</strong><br />
<strong>de</strong>m er festhält, was, wann, <strong>in</strong> welcher Reihenfolge getan, überprüft und eventuell<br />
noch e<strong>in</strong>mal überarbeitet wer<strong>de</strong>n muss (Phasenkonzept).<br />
Nach <strong>de</strong>m Projektplan benötigt <strong><strong>de</strong>r</strong> Architekt e<strong>in</strong>en »Bauplan« für das Gebäu<strong>de</strong>. Dieser<br />
»Bauplan« dient zum e<strong>in</strong>en als Diskussionsgrundlage mit <strong>de</strong>m Kun<strong>de</strong>n, zum an<strong><strong>de</strong>r</strong>en
Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
als Basis zum Bau <strong>de</strong>s Gebäu<strong>de</strong>s. Der Architekt erstellt <strong>de</strong>shalb e<strong>in</strong>en Grundriss und<br />
die jeweiligen Außenansichten. Der Kun<strong>de</strong> kann dann entsprechend Än<strong><strong>de</strong>r</strong>ungswünsche<br />
äußern, die von <strong>de</strong>m Architekten wie<strong><strong>de</strong>r</strong> übernommen wer<strong>de</strong>n, bis man sich<br />
schließlich auf e<strong>in</strong>en geme<strong>in</strong>samen Bauplan e<strong>in</strong>igt.<br />
E<strong>in</strong> Datenbank-Designer steht vor <strong>de</strong>m gleichen Problem. Er muss <strong>de</strong>m Kun<strong>de</strong>n leicht<br />
verständlich e<strong>in</strong>en »Bauplan« se<strong>in</strong>er späteren Datenbankstruktur vorstellen. Im Gegensatz<br />
zum Architekten, <strong><strong>de</strong>r</strong> immer wie<strong><strong>de</strong>r</strong> die gleiche Tätigkeit durchzuführen hat, nämlich<br />
<strong>de</strong>n Bau e<strong>in</strong>es Gebäu<strong>de</strong>s, muss sich e<strong>in</strong> Datenbank-Designer immer wie<strong><strong>de</strong>r</strong> fachlich<br />
<strong>in</strong> die verschie<strong>de</strong>nsten Tätigkeiten e<strong>in</strong>es Unternehmens e<strong>in</strong>arbeiten, für das e<strong>in</strong>e<br />
Datenbank erstellt wer<strong>de</strong>n soll. Bevor er also e<strong>in</strong>en »Bauplan« entwirft, führt er<br />
Gespräche mit <strong>de</strong>n zukünftigen Endanwen<strong><strong>de</strong>r</strong>n, sichtet Dokumente <strong>de</strong>s Unternehmens,<br />
ermittelt Informationen anhand von Fragebögen u.ä.<br />
Ziel <strong>de</strong>s Datenbank-Designers <strong>in</strong> dieser ersten Phase ist es also, das Geschäftsumfeld<br />
<strong>de</strong>s Kun<strong>de</strong>n mit <strong>de</strong>n jeweiligen Funktionen und anfallen<strong>de</strong>n Daten kennenzulernen.<br />
Danach kann er anfangen, e<strong>in</strong>en ersten »Bauplan« für das zukünftige System zu erstellen.<br />
Er bil<strong>de</strong>t damit die Realität <strong>in</strong> e<strong>in</strong>em sogenannten Datenmo<strong>de</strong>ll ab. Dazu i<strong>de</strong>ntifiziert<br />
er die Daten <strong><strong>de</strong>r</strong> relevanten Geschäftsobjekte, die für das Geschäftsumfeld relevant<br />
s<strong>in</strong>d, und <strong><strong>de</strong>r</strong>en Beziehungen untere<strong>in</strong>an<strong><strong>de</strong>r</strong>. Nehmen wir z.B. das e<strong>in</strong>fache Geschäftsumfeld<br />
»Kun<strong>de</strong> kauft Auto« : Hier stellen »Kun<strong>de</strong>« und »Auto« Geschäftsobjekte dar<br />
und »kauft« beschreibt die Beziehung zwischen diesen bei<strong>de</strong>n Geschäftsobjekten.<br />
Dieser erste Entwurf e<strong>in</strong>es Datenmo<strong>de</strong>lls dient <strong>de</strong>m Datenbank-Designer nun als<br />
Grundlage zur Diskussion mit <strong>de</strong>m Kun<strong>de</strong>n, um fachliche Verständnisprobleme o<strong><strong>de</strong>r</strong><br />
fehlen<strong>de</strong> Daten bzw. Beziehungen zu ermitteln. In Zusammenarbeit mit <strong>de</strong>m Kun<strong>de</strong>n<br />
wird dieses Datenmo<strong>de</strong>ll für alle relevanten Geschäftsobjekte weiter verfe<strong>in</strong>ert. Der<br />
Datenbank-Designer entwirft dieses Datenmo<strong>de</strong>ll auf e<strong>in</strong>em Blatt Papier. Dabei könnte<br />
<strong><strong>de</strong>r</strong> Datenbank-Designer eigene grafische Symbole verwen<strong>de</strong>n, die er <strong>de</strong>m Kun<strong>de</strong>n<br />
erläutert, bevor über das Datenmo<strong>de</strong>ll diskutiert wird, genau so wie e<strong>in</strong> Bauherr die<br />
Symbole auf e<strong>in</strong>em Grundriss verstehen muss.<br />
Beim Datenbankentwurf hat sich jedoch e<strong>in</strong>e bestim<strong>mt</strong>e grafische Notation bzw.<br />
Mo<strong>de</strong>llierung etabliert: das Entity-Relationship-Mo<strong>de</strong>ll (ERM). Das ERM wird heutzutage<br />
<strong>in</strong> <strong><strong>de</strong>r</strong> Regel für <strong>de</strong>n Entwurf e<strong>in</strong>es Datenmo<strong>de</strong>lls verwen<strong>de</strong>t und hat sich <strong>in</strong> <strong><strong>de</strong>r</strong><br />
<strong>Praxis</strong> durchgesetzt, da es ohne viel E<strong>in</strong>arbeitungsaufwand relativ schnell verstan<strong>de</strong>n<br />
wird. Gera<strong>de</strong> dieser Punkt ist wichtig, um sich bei <strong>de</strong>n Gesprächen mit <strong>de</strong>m Kun<strong>de</strong>n<br />
auf die fachspezifischen Inhalte konzentrieren zu können und Missverständnisse bei<br />
<strong>de</strong>n grafischen Notationen zu vermei<strong>de</strong>n.<br />
So ist die aufwendige Notation <strong><strong>de</strong>r</strong> Grund, weshalb sich die Mo<strong>de</strong>llierungssprache<br />
»Unified Mo<strong>de</strong>l<strong>in</strong>g Language« (UML) bisher noch nicht <strong>in</strong> <strong><strong>de</strong>r</strong> Mo<strong>de</strong>llierung von<br />
Datenbankentwürfen als Grundlage für Kun<strong>de</strong>ngespräche durchgesetzt hat.<br />
Im Gegensatz zur UML hat das ERM wie<strong><strong>de</strong>r</strong>um <strong>de</strong>n Nachteil, dass es nicht standardisiert<br />
wur<strong>de</strong>. Dadurch existieren zur Zeit verschie<strong>de</strong>ne »Dialekte« . Auf das ERM und<br />
die verschie<strong>de</strong>nen »Dialekte« (Chen, Barker) und ansatzweise auf die UML wird <strong>in</strong><br />
Kapitel 3 ausführlich e<strong>in</strong>gegangen.<br />
21
22<br />
2 Grundlagen von Datenbanken<br />
Das so im ersten Schritt erstellte Datenmo<strong>de</strong>ll, auch konzeptionelles Mo<strong>de</strong>ll genannt<br />
(siehe Abb. 2.6), muss also so e<strong>in</strong>fach se<strong>in</strong>, dass es als Grundlage <strong><strong>de</strong>r</strong> Gespräche mit<br />
<strong>de</strong>m Kun<strong>de</strong>n dienen kann. Zum an<strong><strong>de</strong>r</strong>en muss es aber auch <strong>de</strong>tailliert genug se<strong>in</strong>,<br />
damit es vom Datenbank-Designer physisch <strong>in</strong> Datenbankstrukturen umgewan<strong>de</strong>lt<br />
wer<strong>de</strong>n kann.<br />
2.3 Vom »Bauplan« zur Datenbank<br />
Das konzeptionelle Datenmo<strong>de</strong>ll, das zur Diskussion mit <strong>de</strong>m Kun<strong>de</strong>n dient, ist unabhängig<br />
von technischen Implementierungen. Es dient dazu, zu beschreiben, was mit<br />
welchen Daten später auf <strong>de</strong>m Computer umgesetzt wer<strong>de</strong>n soll.<br />
So wie e<strong>in</strong> Architekt beim Bau e<strong>in</strong>es Gebäu<strong>de</strong>s für die Handwerker e<strong>in</strong>en eigenen Plan<br />
erstellt, muss auch <strong><strong>de</strong>r</strong> Datenbank-Designer e<strong>in</strong>en eigenen Plan zur Umsetzung <strong>de</strong>s konzeptionellen<br />
Datenmo<strong>de</strong>lls erstellen. Nach <strong>de</strong>m Entwurf <strong>de</strong>s konzeptionellen Datenmo<strong>de</strong>lls<br />
muss also e<strong>in</strong> weiterer »Bauplan« , das so genannte logische Datenmo<strong>de</strong>ll,<br />
erstellt wer<strong>de</strong>n, das die Umsetzung <strong>de</strong>s konzeptionellen Mo<strong>de</strong>lls <strong>in</strong> e<strong>in</strong>e physische<br />
Datenstruktur unterstützt. Das logische Datenmo<strong>de</strong>ll legt fest, wie die im konzeptionellen<br />
Mo<strong>de</strong>ll <strong>de</strong>f<strong>in</strong>ierten Geschäftsobjekte und Beziehungen elektronisch abgebil<strong>de</strong>t wer<strong>de</strong>n<br />
können. In relationalen Datenbanksystemen erfolgt die Speicherung von Geschäftsobjekten<br />
und Beziehungen <strong>in</strong> Form von Tabellen. E<strong>in</strong>e Zeile <strong>in</strong>nerhalb <strong><strong>de</strong>r</strong> Tabelle stellt<br />
dabei e<strong>in</strong> reales Objekt, e<strong>in</strong>e Spalte die Eigenschaft <strong>de</strong>s realen Objektes dar. Man spricht<br />
bei diesem logischen Datenmo<strong>de</strong>ll <strong>de</strong>mentsprechend vom Relationenmo<strong>de</strong>ll. Nach<strong>de</strong>m<br />
dieses entwickelt wur<strong>de</strong>, kann mit Hilfe <strong><strong>de</strong>r</strong> relationalen Datenbanksprache SQL die<br />
Struktur <strong><strong>de</strong>r</strong> Datenbank physikalisch auf <strong>de</strong>m Computer erstellt wer<strong>de</strong>n (siehe Abb. 2.6).<br />
Der Entwurf <strong>de</strong>s logischen Datenmo<strong>de</strong>lls auf Basis <strong>de</strong>s Relationenmo<strong>de</strong>lls wird ausführlich<br />
<strong>in</strong> Kapitel 4 beschrieben, die Erstellung <strong><strong>de</strong>r</strong> Datenbankstruktur mit SQL <strong>in</strong><br />
Kapitel 9.<br />
Da Benutzer unterschiedliche Sichten auf die Daten haben, wird im nächsten Schritt<br />
das so genannte externe Datenmo<strong>de</strong>ll festgelegt. Hierbei wird zum e<strong>in</strong>en bestim<strong>mt</strong>,<br />
welche Benutzer bzw. welche Benutzergruppen, welche Berechtigungen auf bestim<strong>mt</strong>e<br />
Informations<strong>in</strong>halte erhalten. Zum an<strong><strong>de</strong>r</strong>en wer<strong>de</strong>n Sichten auf die Daten erzeugt <strong>in</strong><br />
Abhängigkeit von <strong><strong>de</strong>r</strong> Funktion <strong>de</strong>s jeweiligen Anwendungsprogramms.<br />
Schließlich wird <strong>in</strong> e<strong>in</strong>em physischen Datenmo<strong>de</strong>ll festgelegt, welche Zugriffsmechanismen<br />
und Speicherstrukturen zur Effizienzsteigerung verwen<strong>de</strong>t wer<strong>de</strong>n können. Da<br />
das physische Datenmo<strong>de</strong>ll stark abhängig ist vom jeweils verwen<strong>de</strong>ten RDBMS, wird<br />
hier nicht weiter darauf e<strong>in</strong>gegangen. Hierzu sollte man die Handbücher <strong><strong>de</strong>r</strong> entsprechen<strong>de</strong>n<br />
Datenbankprodukte zu Rate ziehen bzw. Datenbankbücher, die auf Speicherstrukturen<br />
und Zugriffsmechanismen <strong>de</strong>tailliert e<strong>in</strong>gehen (siehe hierzu die Literaturliste).
2.4 Zusammenfassung<br />
Zusammenfassung<br />
In diesem Kapitel haben wir zunächst die Probleme kennen gelernt, die auftreten,<br />
sofern man Daten über e<strong>in</strong> Dateisystem speichert. Die Grün<strong>de</strong> für diese Probleme liegen<br />
vorwiegend <strong>in</strong> <strong><strong>de</strong>r</strong> mangeln<strong>de</strong>n Verwaltung <strong><strong>de</strong>r</strong> Daten durch e<strong>in</strong>e übergeordnete<br />
Instanz. Diese übergeordnete Instanz stellt e<strong>in</strong> so genanntes Datenbank-Management-<br />
System (DBMS) dar, das die Daten unter se<strong>in</strong>er »Obhut« verwaltet. Genau wie <strong><strong>de</strong>r</strong><br />
Manager e<strong>in</strong>er Firma plant und steuert, kontrolliert und organisiert das DBMS die<br />
Daten. Hierdurch können Redundanzen vermie<strong>de</strong>n wer<strong>de</strong>n, die Integrität, Sicherheit<br />
und <strong><strong>de</strong>r</strong> Schutz <strong><strong>de</strong>r</strong> Daten sichergestellt wer<strong>de</strong>n.<br />
E<strong>in</strong> Problem kann jedoch nicht durch e<strong>in</strong> DBMS beseitigt wer<strong>de</strong>n: Redundanzen aufgrund<br />
<strong><strong>de</strong>r</strong> Struktur, <strong>in</strong> <strong><strong>de</strong>r</strong> die Daten gespeichert wur<strong>de</strong>n.<br />
Probleme dieser Art lassen sich durch e<strong>in</strong>e analytische Tätigkeit, <strong>de</strong>n Datenbankentwurf,<br />
vermei<strong>de</strong>n. Der Datenbankentwurf, also die Erstellung e<strong>in</strong>es »Bauplanes« aufgrund<br />
<strong><strong>de</strong>r</strong> Realität, erfolgt <strong>in</strong> mehreren Schritten. Zunächst wird festgelegt, zu welchem<br />
Zweck e<strong>in</strong>e Datenbank entworfen wer<strong>de</strong>n soll. Danach wird <strong>in</strong> Absprache mit<br />
<strong>de</strong>m Kun<strong>de</strong>n e<strong>in</strong> konzeptionelles Datenmo<strong>de</strong>ll erstellt.<br />
Realität<br />
Zweckbestimmung<br />
Zweckbestimmung<br />
konzeptionelles<br />
konzeptionelles<br />
Datenmo<strong>de</strong>ll<br />
Datenmo<strong>de</strong>ll<br />
��� ���� ����������� �������<br />
��� ���� ����������� ���� �������<br />
����<br />
logisches<br />
logisches<br />
Datenmo<strong>de</strong>ll<br />
Datenmo<strong>de</strong>ll<br />
��� ���� ����������� �������<br />
��� ���� �����������������<br />
����������� �������<br />
�����������������<br />
physisches<br />
Datenmo<strong>de</strong>ll<br />
physisches<br />
Datenmo<strong>de</strong>ll<br />
Zweck:<br />
� ����������<br />
�������������<br />
� ������������<br />
������<br />
����<br />
����<br />
Abbildung 2.6: Schritte zur Erstellung e<strong>in</strong>er Datenbank<br />
���<br />
���<br />
23
24<br />
2 Grundlagen von Datenbanken<br />
Nach<strong>de</strong>m das konzeptionelle Datenmo<strong>de</strong>ll so weit fortgeschritten ist, dass es <strong>de</strong>m<br />
Geschäftsumfeld <strong>de</strong>s Kun<strong>de</strong>n entspricht, entwickelt <strong><strong>de</strong>r</strong> Datenbank-Designer das logische<br />
Datenmo<strong>de</strong>ll. Dieses dient <strong>de</strong>m Datenbank-Designer als Grundlage zur Erstellung<br />
e<strong>in</strong>er physischen Datenstruktur. Bei <strong>de</strong>m Entwurf e<strong>in</strong>er relationalen Datenbank wird<br />
hier entsprechend das Relationenmo<strong>de</strong>ll verwen<strong>de</strong>t.<br />
Schließlich wird das Relationenmo<strong>de</strong>ll physikalisch mit <strong><strong>de</strong>r</strong> Datenbanksprache SQL <strong>in</strong><br />
e<strong>in</strong>e physische Datenbankstruktur umgesetzt.<br />
Im folgen<strong>de</strong>n Kapitel wollen wir uns mit Phasenkonzepten und <strong><strong>de</strong>r</strong> Erstellung <strong>de</strong>s<br />
konzeptionellen Datenmo<strong>de</strong>lls beschäftigen.<br />
2.5 Aufgaben<br />
Wie<strong><strong>de</strong>r</strong>holungsfragen<br />
1) Was versteht man unter e<strong>in</strong>em Datenbank-Management-System (DBMS)?<br />
2) Was ist e<strong>in</strong> Datenbanksystem (DBS)?<br />
3) Was ist e<strong>in</strong>e Datenbank (DB)?<br />
4) Welche Aufgaben erfüllt e<strong>in</strong> DBMS?<br />
5) Was versteht man unter »Redundanz von Daten« ?<br />
6) Was versteht man unter »Datenunabhängigkeit« ?<br />
7) Was ist mit »Daten<strong>in</strong>tegrität« geme<strong>in</strong>t?<br />
8) Wor<strong>in</strong> besteht die Hauptaufgabe <strong>de</strong>s Datenbank-Designers?<br />
9) Welche Datenmo<strong>de</strong>llierungstechniken gibt es?<br />
Übungen<br />
1) Herr Kle<strong>in</strong> von <strong><strong>de</strong>r</strong> Firma »KartoF<strong>in</strong>ale« hat se<strong>in</strong>e Datei mit <strong>de</strong>n Kun<strong>de</strong>ndaten noch<br />
e<strong>in</strong>mal geän<strong><strong>de</strong>r</strong>t. Um nicht für je<strong>de</strong> Rechnung die gesa<strong>mt</strong>en Kun<strong>de</strong>ndaten zu wie<strong><strong>de</strong>r</strong>holen,<br />
hat er zwei Dateien erstellt, e<strong>in</strong>e Datei für die Kun<strong>de</strong>ndaten und e<strong>in</strong>e weitere<br />
Datei mit <strong>de</strong>n Rechnungsdaten. Die Dateien sehen wie <strong>in</strong> <strong><strong>de</strong>r</strong> folgen<strong>de</strong>n Abbildung<br />
aus.<br />
Um die Rechnung <strong>de</strong>m jeweiligen Kun<strong>de</strong>n zuzuordnen, hat Herr Kle<strong>in</strong> <strong>de</strong>n Vorund<br />
Nachnamen mit <strong>in</strong> die Rechnungsdatei übernommen. Über <strong>de</strong>n Vor- und<br />
Nachnamen kann er <strong>in</strong> <strong><strong>de</strong>r</strong> Kun<strong>de</strong>ndatei dann die vollständige Adresse <strong>de</strong>s Kun<strong>de</strong>n<br />
ermitteln.<br />
Beschreiben Sie mögliche Probleme dieser Lösung!
Kun<strong>de</strong>ndatei<br />
Aufgaben<br />
Name Vorname Strasse Ort K<strong>in</strong><strong><strong>de</strong>r</strong><br />
������ ���� ��������� �� ����� ��������� �������<br />
��������� ������ ��������� �� ����� �������� ������� ����<br />
�����<br />
���<br />
������� ������ �� ����� ����������� ������ ������� ����<br />
Rechnungsdatei<br />
Name Vorname Rechnungsnr. Betrag Veranstaltung<br />
������ ���� �� ����� �� ��������<br />
������ ���� �� ������ �� ������� ��� ������<br />
������ ���� ��� ����� �� ��������<br />
���������<br />
���<br />
������ �� ������ �� ������� ��� ������<br />
25
3 Datenbankentwurf<br />
– Von<br />
<strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
In Kapitel 3 sollen folgen<strong>de</strong> Fragen geklärt wer<strong>de</strong>n:<br />
� Wie sieht e<strong>in</strong> Projektplan (Phasenkonzept) zum Entwurf e<strong>in</strong>er Datenbank bzw.<br />
e<strong>in</strong>es Anwendungssystems aus?<br />
� Wie wer<strong>de</strong>n die Anfor<strong><strong>de</strong>r</strong>ungen an e<strong>in</strong> zu entwickeln<strong>de</strong>s Anwendungssystem bzw.<br />
die Datenbankstruktur ermittelt?<br />
� Wie wer<strong>de</strong>n die ermittelten Anfor<strong><strong>de</strong>r</strong>ungen formal dargestellt (»Bauplan«), um mit<br />
<strong>de</strong>m Kun<strong>de</strong>n über <strong>de</strong>n Entwurf zu diskutieren?<br />
� Welche formalen Entwurfsmetho<strong>de</strong>n haben sich <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>Praxis</strong> etabliert?<br />
� Welche formalen Entwurfsmetho<strong>de</strong>n wer<strong>de</strong>n zukünftig <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>Praxis</strong> e<strong>in</strong>gesetzt?<br />
3.1 Motivation<br />
Als E<strong>in</strong>stieg betrachten wir wie<strong><strong>de</strong>r</strong> <strong>de</strong>n Verkauf von E<strong>in</strong>trittskarten bei <strong><strong>de</strong>r</strong> Firma »Karto-<br />
F<strong>in</strong>ale«. Wir haben im zweiten Kapitel erfahren, dass durch das Speichern <strong><strong>de</strong>r</strong> Kun<strong>de</strong>nund<br />
Rechnungsdaten zentral <strong>in</strong> e<strong>in</strong>er e<strong>in</strong>zigen Datei verschie<strong>de</strong>ne Probleme auftraten<br />
und diese nur unzureichend gelöst wer<strong>de</strong>n konnten. Als vorbildliche Abteilungsleiter<strong>in</strong><br />
trägt Frau Kart <strong>de</strong>shalb dieses Problem bei <strong><strong>de</strong>r</strong> Geschäftsführung vor. Der Geschäftsführer,<br />
Herr Kowalski, lässt sich die Probleme erklären und kom<strong>mt</strong> zu <strong>de</strong>m Entschluss e<strong>in</strong>e<br />
Unternehmensberatung zu beauftragen, e<strong>in</strong> eigenes Abrechnungssystem für »KartoF<strong>in</strong>ale«<br />
zu entwickeln. Se<strong>in</strong> Nachbar, Herr Warner, ist zufälligerweise Geschäftsführer <strong><strong>de</strong>r</strong><br />
Unternehmensberatung »Software Consult AG«, die sich auf die Analyse und Konzeption<br />
von Anwendungssystemen für <strong>de</strong>n Dienstleistungsbereich spezialisiert hat.<br />
Also beauftragt Herr Kowalski se<strong>in</strong>en Nachbarn, Herrn Warner, zur Erstellung e<strong>in</strong>es<br />
Konzeptes für e<strong>in</strong> EDV-gestütztes Abrechnungssystem. Herr Warner, <strong><strong>de</strong>r</strong> sich Herrn<br />
Kowalski als Nachbar verpflichtet fühlt, setzt se<strong>in</strong>en besten Mitarbeiter, Herrn Dr. Fleissig<br />
für diese Aufgabe e<strong>in</strong>.<br />
Vor e<strong>in</strong>em ersten Gespräch mit Herrn Kowalski, lässt sich Herr Fleissig e<strong>in</strong>e Broschüre<br />
und an<strong><strong>de</strong>r</strong>e Informationen über die Firma »KartoF<strong>in</strong>ale« zusen<strong>de</strong>n, um e<strong>in</strong>en ersten<br />
E<strong>in</strong>druck von <strong>de</strong>n Geschäftsprozessen <strong><strong>de</strong>r</strong> Firma zu erhalten. Er erstellt e<strong>in</strong>en ersten<br />
Fragenkatalog, <strong>de</strong>n er am nächsten Tag mit Herrn Kowalski klären will. Dabei unterschei<strong>de</strong>t<br />
er zwischen fachlichen und re<strong>in</strong> projektspezifischen Fragen.<br />
Fachliche Fragen s<strong>in</strong>d u.a.:<br />
� Wie sieht <strong><strong>de</strong>r</strong> Ablauf <strong>de</strong>s Verkaufes von E<strong>in</strong>trittskarten aus?<br />
� Welche Kun<strong>de</strong>ngruppen existieren beim Verkauf?<br />
27
28<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
� Wird nur an Privatkun<strong>de</strong>n verkauft?<br />
� Wer<strong>de</strong>n auch Abonnementkarten verkauft?<br />
� Wie erfolgt die Bezahlung?<br />
� Aus welchen Abteilungen besteht die Firma »KartoF<strong>in</strong>ale« ? u.a.<br />
Projektspezifische Fragen betreffen dagegen <strong>de</strong>n Ablauf <strong><strong>de</strong>r</strong> Erstellung <strong>de</strong>s EDVgestützten<br />
Abrechnungssystems.<br />
� Gibt es e<strong>in</strong>en vorgegebenen E<strong>in</strong>satzterm<strong>in</strong> für das Abrechnungssystem?<br />
� Welcher Mitarbeiter von »KartoF<strong>in</strong>ale« ist Ansprechpartner <strong>in</strong> organisatorischen<br />
Fragen?<br />
� Bis wann soll das Konzept für das Abrechnungssystem spätestens fertiggestellt<br />
se<strong>in</strong>? u.a.<br />
Nach <strong>de</strong>m Gespräch am nächsten Tag mit Herrn Kowalski hat Herr Fleissig e<strong>in</strong>en ersten<br />
Überblick über die Geschäftstätigkeiten von »KartoF<strong>in</strong>ale« erhalten. Um e<strong>in</strong>zelne<br />
Geschäftsprozesse <strong>de</strong>tailliert zu verstehen, vere<strong>in</strong>bart er Gespräche mit Frau Kart als<br />
Vertriebsleiter<strong>in</strong> und Herrn Wun<strong><strong>de</strong>r</strong> als Leiter <strong>de</strong>s Rechnungswesens. Vor <strong>de</strong>n Gesprächen<br />
erhält er von Herrn Kowalski noch Formulare, die bei <strong><strong>de</strong>r</strong> Abwicklung <strong><strong>de</strong>r</strong> Verkaufes<br />
verwen<strong>de</strong>t wer<strong>de</strong>n und Exemplare von Rechnungen und Mahnungen an die<br />
Kun<strong>de</strong>n.<br />
Im Gespräch mit Frau Kart erfährt Herr Fleissig, dass E<strong>in</strong>trittskarten ausschließlich per<br />
Telefon von Kun<strong>de</strong>n bestellt wer<strong>de</strong>n, e<strong>in</strong>e direkte Vorverkaufsstelle sei nicht vorhan<strong>de</strong>n<br />
und auch nicht geplant. Allerd<strong>in</strong>gs gibt es Überlegungen, E<strong>in</strong>trittskarten auch über<br />
das Internet zu verkaufen. Herr Fleissig bittet Frau Kart zu erläutern, wie <strong><strong>de</strong>r</strong> bisherige<br />
Ablauf <strong><strong>de</strong>r</strong> Kartenbestellung aussieht. Frau Kart erzählt: »Ruft e<strong>in</strong> Kun<strong>de</strong> bei uns an, so<br />
wird er von Inga o<strong><strong>de</strong>r</strong> Klaus, die die e<strong>in</strong>gehen<strong>de</strong>n Telefonate entgegennehmen,<br />
zunächst nach e<strong>in</strong>er Kun<strong>de</strong>nnummer gefragt. Han<strong>de</strong>lt es sich um e<strong>in</strong>en neuen Kun<strong>de</strong>n,<br />
so wird e<strong>in</strong> Formular mit <strong>de</strong>n Adressdaten und <strong><strong>de</strong>r</strong> gewünschten Zahlungsweise ausgefüllt.<br />
Ist er bereits Kun<strong>de</strong>, so wird <strong>in</strong> <strong><strong>de</strong>r</strong> Adressdatei auf unserem zentralen Computer<br />
nach se<strong>in</strong>er Kun<strong>de</strong>nnummer gesucht und die Adressdaten auf e<strong>in</strong> Bestellformular<br />
übertragen. In das Bestellformular trägt Inga o<strong><strong>de</strong>r</strong> Klaus dann die gewünschten E<strong>in</strong>trittskarten<br />
e<strong>in</strong>. Hierzu wird die Bezeichnung <strong><strong>de</strong>r</strong> Veranstaltung, <strong><strong>de</strong>r</strong> Vorstellungsterm<strong>in</strong>,<br />
sowie die Spielstätte und die Anzahl <strong><strong>de</strong>r</strong> gewünschten Karten e<strong>in</strong>getragen.<br />
Danach gibt Inga bzw. Klaus das Bestellformular an Herrn Kle<strong>in</strong> weiter. Herr Kle<strong>in</strong><br />
ergänzt das Formular um die Vorstellungsnummer, die er aus e<strong>in</strong>em Katalog aller verfügbaren<br />
Vorstellungen manuell heraussucht. Anhand <strong><strong>de</strong>r</strong> Vorstellungsnummer geht<br />
er zu unserem Tresor und sucht die gewünschten E<strong>in</strong>trittskarten heraus und gibt sie<br />
zusammen mit <strong>de</strong>m Bestellformular an Herrn Wun<strong><strong>de</strong>r</strong> vom Rechnungswesen weiter.«<br />
Im darauf folgen<strong>de</strong>n Gespräch mit Herrn Wun<strong><strong>de</strong>r</strong> erfährt Herr Fleissig, was danach<br />
mit <strong>de</strong>m Bestellformular passiert. Herr Wun<strong><strong>de</strong>r</strong> erzählt: »Ich nehme das Bestellformular<br />
und suche <strong>in</strong> <strong><strong>de</strong>r</strong> zentralen Kun<strong>de</strong>ndatei nach <strong>de</strong>m Kun<strong>de</strong>n, um die Adressdaten <strong>in</strong><br />
die zu erstellen<strong>de</strong> Rechnung zu übernehmen. Die Rechnung schreibe ich <strong>in</strong> me<strong>in</strong>em<br />
Textverarbeitungsprogramm. Entsprechend führe ich die E<strong>in</strong>zelposten mit <strong>de</strong>n E<strong>in</strong>trittskarten<br />
auf und berechne e<strong>in</strong>e Gesa<strong>mt</strong>summe mit Mehrwertsteuer. Abhängig von<br />
<strong><strong>de</strong>r</strong> Gesa<strong>mt</strong>summe und davon, ob es sich um e<strong>in</strong>en langjährigen Kun<strong>de</strong>n han<strong>de</strong>lt,
Motivation<br />
rechne ich schließlich noch e<strong>in</strong>en Rabatt von 2% bis 4% heraus. Danach drucke ich die<br />
Rechnung zweifach aus und stecke e<strong>in</strong> Exemplar zusammen mit <strong>de</strong>n E<strong>in</strong>trittskarten <strong>in</strong><br />
e<strong>in</strong>en Briefumschlag, <strong><strong>de</strong>r</strong> dann an <strong>de</strong>n Kun<strong>de</strong>n versen<strong>de</strong>t wird. Das zweite Exemplar<br />
geht schließlich an unseren Steuerberater, <strong><strong>de</strong>r</strong> extern die F<strong>in</strong>anzbuchhaltung für<br />
»KartoF<strong>in</strong>ale« durchführt« .<br />
Nach <strong>de</strong>n Gesprächen erstellt Herr Fleissig mit Bleistift und Papier zunächst e<strong>in</strong>en groben<br />
Entwurf über <strong>de</strong>n Ablauf dieses Geschäftsprozesses, um grafisch e<strong>in</strong>en <strong>in</strong>tegrierten<br />
Überblick zu erhalten. Dabei bemerkt er, dass noch Informationen fehlen. So hat<br />
Frau Kart noch nicht erklärt, was mit <strong>de</strong>m Kun<strong>de</strong>nformular für neue Kun<strong>de</strong>n<br />
geschieht. Herr Fleissig geht davon aus, dass Inga bzw. Klaus diese <strong>in</strong> die zentrale Kun<strong>de</strong>ndatei<br />
selbständig e<strong>in</strong>tragen.<br />
Danach gibt Herr Fleissig <strong>de</strong>n ersten Grobentwurf zur Überprüfung noch e<strong>in</strong>mal Frau<br />
Kart und Herrn Wun<strong><strong>de</strong>r</strong> und erfährt, dass neue Kun<strong>de</strong>ndaten nicht von Inga o<strong><strong>de</strong>r</strong><br />
Klaus, son<strong><strong>de</strong>r</strong>n von Herrn Kle<strong>in</strong> <strong>in</strong> die Adressdatei übertragen wer<strong>de</strong>n. Entsprechend<br />
korrigiert er se<strong>in</strong>e Grafik. Herr Fleissig verwen<strong>de</strong>t se<strong>in</strong>e eigene Notation zur grafischen<br />
Darstellung <strong>de</strong>s Geschäftsprozesses, da <strong><strong>de</strong>r</strong> Entwurf nur als vorläufige Skizze dienen<br />
soll, um e<strong>in</strong>en ersten Überblick über diesen Geschäftsprozess zu erhalten.<br />
Kun<strong>de</strong> ruft an<br />
Inga /<br />
Klaus<br />
Neuer Kun<strong>de</strong>?<br />
Ja<br />
Formular „Neuer<br />
Kun<strong>de</strong>“ ausfüllen<br />
Inga /<br />
Klaus<br />
Ne<strong>in</strong><br />
Adressdaten <strong>in</strong><br />
Kun<strong>de</strong>ndatei<br />
übertragen<br />
Herr<br />
Kle<strong>in</strong><br />
Adressdaten von<br />
Kun<strong>de</strong>ndatei auf<br />
Bestellformular<br />
übertragen<br />
Inga /<br />
Klaus<br />
E<strong>in</strong>trittskarten auf<br />
Bestellformular<br />
e<strong>in</strong>tragen<br />
Bestellformular<br />
um Vorstellungsnummer<br />
ergänzen<br />
E<strong>in</strong>trittskarten<br />
heraussuchen und<br />
Bestellformular<br />
beifügen<br />
Adressdaten von<br />
Kun<strong>de</strong>ndatei auf<br />
Rechnung<br />
übertragen<br />
E<strong>in</strong>zelposten<br />
aufführen,<br />
Gesa<strong>mt</strong>summe<br />
und Rabatt<br />
berechnen<br />
Rechnung mit<br />
Karten per Post<br />
versen<strong>de</strong>n<br />
Zweites<br />
Rechnungsexemplar<br />
an<br />
Steuerberater<br />
Abbildung 3.1: Erster Entwurf <strong>de</strong>s Geschäftsprozesses »Kartenbestellung«<br />
Nach <strong>de</strong>n Gesprächen erhält Herr Fleissig noch die Adressdatei <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n. Wie<strong><strong>de</strong>r</strong><br />
zurück <strong>in</strong> <strong><strong>de</strong>r</strong> Firma, beg<strong>in</strong>nt Herr Fleissig, <strong>de</strong>n Zweck <strong>de</strong>s zukünftigen Abrechnungssystems<br />
zu beschreiben. Das zu entwickeln<strong>de</strong> Abrechnungssystem soll <strong>de</strong>n Bestellvorgang<br />
von <strong><strong>de</strong>r</strong> Bestellannahme bis zum Versand <strong><strong>de</strong>r</strong> E<strong>in</strong>trittskarten sowie Teile <strong>de</strong>s<br />
Rechnungswesens, nämlich Fakturierung und Mahnwesen be<strong>in</strong>halten.<br />
Danach stellt Herr Fleissig e<strong>in</strong>en ersten Projektplan auf, <strong><strong>de</strong>r</strong> aus vier Phasen besteht. In<br />
<strong><strong>de</strong>r</strong> ersten Phase, die sechs Wochen dauern soll, wer<strong>de</strong>n <strong>in</strong> Zusammenarbeit mit <strong>de</strong>m<br />
Kun<strong>de</strong>n die Anfor<strong><strong>de</strong>r</strong>ungen an das zu entwickeln<strong>de</strong> Abrechnungssystem <strong>de</strong>f<strong>in</strong>iert. Als<br />
Ergebnis erhält man e<strong>in</strong> konzeptionelles Mo<strong>de</strong>ll, das losgelöst ist von Hardware und<br />
Inga /<br />
Klaus<br />
Herr<br />
Kle<strong>in</strong><br />
Herr<br />
Kle<strong>in</strong><br />
Herr<br />
Wun<strong><strong>de</strong>r</strong><br />
Herr<br />
Wun<strong><strong>de</strong>r</strong><br />
Herr<br />
Wun<strong><strong>de</strong>r</strong><br />
Herr<br />
Wun<strong><strong>de</strong>r</strong><br />
29
30<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
Software. In <strong><strong>de</strong>r</strong> zweiten Phase wird das eigentliche Abrechnungssystem entworfen,<br />
als Ergebnis entsteht e<strong>in</strong> <strong>in</strong> sich logisches Mo<strong>de</strong>ll, das auf <strong>de</strong>n Computer übertragen<br />
wer<strong>de</strong>n kann. Auf Grundlage <strong><strong>de</strong>r</strong> zweiten Phase wird <strong>in</strong> <strong><strong>de</strong>r</strong> dritten Phase das logische<br />
Mo<strong>de</strong>ll auf <strong>de</strong>m Computer umgesetzt. Als Ergebnis entsteht das Abrechnungssystem,<br />
das getestet und schließlich an <strong>de</strong>n Kun<strong>de</strong>n ausgeliefert wird. In <strong><strong>de</strong>r</strong> vierten Phase<br />
wird dann das Abrechnungssystem vom Kun<strong>de</strong>n bewertet, noch etwaige Än<strong><strong>de</strong>r</strong>ungen<br />
vorgenommen und e<strong>in</strong> Support- und Wartungsplan erstellt.<br />
Herr Fleissig beg<strong>in</strong>nt also <strong>in</strong> <strong><strong>de</strong>r</strong> ersten Phase auf Basis <strong><strong>de</strong>r</strong> bisher geführten Gespräche<br />
das konzeptionelle Datenmo<strong>de</strong>ll zu erstellen. Er analysiert, welche Geschäftsobjekte <strong>in</strong><br />
<strong>de</strong>m Geschäftsprozess auftreten:<br />
� Mitarbeiter<br />
� Abteilung<br />
� Kun<strong>de</strong><br />
� E<strong>in</strong>trittskarte<br />
� Rechnung<br />
� E<strong>in</strong>zelposten<br />
Danach überlegt er sich, welche Beziehungen zwischen diesen Geschäftsobjekten<br />
bestehen:<br />
� Mitarbeiter gehört zu Abteilung<br />
� Kun<strong>de</strong> bestellt E<strong>in</strong>trittskarten<br />
� Kun<strong>de</strong> erhält Rechnung<br />
� Rechnung besteht aus E<strong>in</strong>zelposten<br />
Schließlich zeichnet er das Ganze grafisch als »Entity-Relationship-Mo<strong>de</strong>ll« (ERM) auf.<br />
Mitarbeiter<br />
gehört<br />
zu<br />
Kun<strong>de</strong> bestellt E<strong>in</strong>trittkarte<br />
erhält<br />
Rechnung<br />
enthält<br />
E<strong>in</strong>zelposten<br />
Abbildung 3.2: Erstes konzeptionelles Datenbankmo<strong>de</strong>ll<br />
Abteilung
Projektplan versus Phasenkonzept<br />
Am Beispiel <strong><strong>de</strong>r</strong> Firma »KartoF<strong>in</strong>ale« haben wir bis jetzt <strong>de</strong>n Ablauf e<strong>in</strong>es Projektes<br />
vom Projektanstoß über das Kennenlernen <strong>de</strong>s Geschäftsumfel<strong>de</strong>s, das Erstellen e<strong>in</strong>es<br />
Projektplanes bis h<strong>in</strong> zum ersten Entwurf e<strong>in</strong>es Datenmo<strong>de</strong>lls kennen gelernt. Diese<br />
e<strong>in</strong>zelnen Schritte e<strong>in</strong>es Projektablaufs wer<strong>de</strong>n im Folgen<strong>de</strong>n <strong>de</strong>tailliert erläutert.<br />
3.2 Projektplan versus Phasenkonzept<br />
Vor <strong><strong>de</strong>r</strong> eigentlichen Entwicklung e<strong>in</strong>es Anwendungssystems, stellt man e<strong>in</strong>en Plan<br />
auf, <strong>in</strong> <strong>de</strong>m die Tätigkeiten, die zur Erstellung <strong>de</strong>s Anwendungssystems notwendig<br />
s<strong>in</strong>d, aufgeführt wer<strong>de</strong>n. Je<strong><strong>de</strong>r</strong> Tätigkeit wird das zu liefern<strong>de</strong> Ergebnis zugeordnet.<br />
Man teilt also die Entwicklung <strong>de</strong>s Anwendungssystems <strong>in</strong> verschie<strong>de</strong>ne Schritte bzw.<br />
Phasen e<strong>in</strong>.<br />
E<strong>in</strong> Phasenkonzept ist e<strong>in</strong> Vorschlag für e<strong>in</strong>en Entwicklungsprozess zur erfolgreichen<br />
Durchführung e<strong>in</strong>es Softwareprojektes. In <strong><strong>de</strong>r</strong> Literatur existieren verschie<strong>de</strong>ne Phasenkonzepte,<br />
die e<strong>in</strong>en Anhaltspunkt geben sollen, wie <strong><strong>de</strong>r</strong> eigene Projektplan aussehen<br />
könnte. Die Konzeptvorschläge unterschei<strong>de</strong>n sich dabei nur marg<strong>in</strong>al. Lediglich<br />
bei <strong><strong>de</strong>r</strong> Wie<strong><strong>de</strong>r</strong>holhäufigkeit e<strong>in</strong>zelner Phasen, falls die angestrebten Ergebnisse noch<br />
nicht erzielt wur<strong>de</strong>n, gehen die Autorenme<strong>in</strong>ungen ause<strong>in</strong>an<strong><strong>de</strong>r</strong>.<br />
Das folgen<strong>de</strong> hier vorgestellte Phasenkonzept soll als Anregung zur Erstellung e<strong>in</strong>es<br />
eigenen Projektplanes verstan<strong>de</strong>n wer<strong>de</strong>n. Da ke<strong>in</strong> Projekt <strong>de</strong>m an<strong><strong>de</strong>r</strong>en gleicht, müssen<br />
sich auch die Pläne zur Durchführung dieser Projekte im Detail unterschei<strong>de</strong>n. Von<br />
<strong><strong>de</strong>r</strong> »unkritischen« Übertragung e<strong>in</strong>es standardisierten Phasenkonzeptes auf das<br />
eigene Projekt wird daher abgeraten. Vielmehr soll das folgen<strong>de</strong> Phasenkonzept als<br />
»Gerüst« dienen, das je<strong><strong>de</strong>r</strong>zeit an die eigenen Bedürfnisse angepasst wer<strong>de</strong>n kann.<br />
Die Entwicklung e<strong>in</strong>es Anwendungssystems kann man <strong>de</strong>f<strong>in</strong>ieren als das Entwerfen<br />
und Umsetzen von logischen und physikalischen Abläufen und Strukturen, um <strong>de</strong>n<br />
Anfor<strong><strong>de</strong>r</strong>ungen und <strong>de</strong>n Informationsbedarf von Benutzern <strong>in</strong> e<strong>in</strong>er Organisation<br />
gerecht zu wer<strong>de</strong>n. Das Phasenkonzept stellt dabei e<strong>in</strong>e Vorlage für diesen Entwicklungsprozess<br />
dar.<br />
Da e<strong>in</strong> Anwendungssystem im Wesentlichen aus Funktionen und Daten besteht, wer<strong>de</strong>n<br />
<strong>in</strong> je<strong><strong>de</strong>r</strong> Phase sowohl Funktionen als auch Daten entworfen. Je<strong>de</strong> e<strong>in</strong>zelne Phase<br />
hat also zwei Ergebnisse: e<strong>in</strong> Funktionsmo<strong>de</strong>ll und e<strong>in</strong> Datenmo<strong>de</strong>ll. Das Datenmo<strong>de</strong>ll<br />
legt fest, welche Daten benötigt und <strong>in</strong> e<strong>in</strong>er Datenbank gespeichert wer<strong>de</strong>n sollen. Das<br />
Funktionsmo<strong>de</strong>ll bestim<strong>mt</strong> dagegen, wie die dar<strong>in</strong> gespeicherten Daten verarbeitet<br />
wer<strong>de</strong>n.<br />
Obwohl sich dieses Buch vorwiegend mit <strong><strong>de</strong>r</strong> Datenmo<strong>de</strong>llierung und <strong><strong>de</strong>r</strong> Umsetzung<br />
<strong>in</strong> e<strong>in</strong>e Datenbankstruktur beschäftigt, soll im Folgen<strong>de</strong>n auch kurz auf die Funktionsmo<strong>de</strong>llierung<br />
e<strong>in</strong>gegangen wer<strong>de</strong>n, da größere Datenbanksysteme <strong>in</strong>zwischen verbreitet<br />
funktionale Elemente enthalten können.<br />
31
32<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
Verstehen<br />
Entwerfen<br />
Umsetzen<br />
E<strong>in</strong>setzen<br />
Problem<br />
Phase Ergebnis<br />
Phase 1<br />
���������������<br />
���<br />
�������������������<br />
Phase 2<br />
������� ��������<br />
��������� ���<br />
������� ���<br />
�����������������<br />
���������<br />
Phase 3<br />
��������� ������� ���<br />
��� ������������ ���<br />
����� ���<br />
���������������<br />
�������� ���������<br />
Phase 4<br />
��������� �������<br />
������������<br />
��������<br />
�����������������<br />
Phase 5<br />
�������������� �<br />
�������<br />
Konzeptvorschlag bzw.<br />
Anfor<strong><strong>de</strong>r</strong>ungsentwurf<br />
Konzeptioneller Entwurf<br />
Logischer Entwurf<br />
Physischer Entwurf<br />
Abnahmeplan /<br />
Wartungsplan<br />
Abbildung 3.3: Phasenkonzept<br />
Die erste Phase beschäftigt sich mit <strong>de</strong>m groben Kennenlernen <strong>de</strong>s eigentlichen Problems.<br />
In unserem Beispiel klärt Herr Fleissig <strong>in</strong> e<strong>in</strong>em ersten Gespräch mit <strong>de</strong>m<br />
Geschäftsführer von »KartoF<strong>in</strong>ale« , warum e<strong>in</strong> Abrechnungssystem entwickelt wer<strong>de</strong>n<br />
soll, wo die Probleme bestehen und welche wesentlichen Eigenschaften das zu entwickeln<strong>de</strong><br />
Abrechnungssystem enthalten soll. Dabei hat Herr Fleissig nur e<strong>in</strong>e ungenaue<br />
Vorstellung davon, wie das spätere Abrechnungssystem e<strong>in</strong>mal aussehen wird.<br />
Es geht hierbei ausschließlich um e<strong>in</strong>e kurze Abgrenzung <strong>de</strong>s Themas. Als Ergebnis<br />
dieser ersten Phase entsteht e<strong>in</strong> Konzeptvorschlag, <strong><strong>de</strong>r</strong> beschreibt, was eigentlich als<br />
En<strong><strong>de</strong>r</strong>gebnis <strong>de</strong>s Projektes herauskommen und warum dieses Projekt <strong>in</strong> Angriff<br />
genommen wer<strong>de</strong>n soll.<br />
In <strong><strong>de</strong>r</strong> zweiten Phase beschäftigt man sich mit <strong>de</strong>m geschäftlichen Umfeld. Man ermittelt,<br />
� wie Geschäftsprozesse bisher abgewickelt wer<strong>de</strong>n (z.B. Kontoüberweisung bei<br />
e<strong>in</strong>er Bank, Bestellung von E<strong>in</strong>trittskarten),<br />
� welche Geschäftsobjekte mit welchen Informationen es gibt (z.B. Kun<strong>de</strong> mit <strong>de</strong>n<br />
Informationen Name, Vorname, Adresse usw.),<br />
Zweck<br />
Wartung<br />
��<br />
��<br />
���<br />
��<br />
����
Projektplan versus Phasenkonzept<br />
� welche Beziehungen zwischen <strong>de</strong>n Geschäftsobjekten existieren (z.B. Kun<strong>de</strong> erhält<br />
Rechnung, Abteilung besteht aus mehreren Mitarbeitern),<br />
� welche E<strong>in</strong>schränkungen zwischen Geschäftsobjekten bzw. Informationen existieren<br />
(z.B. darf e<strong>in</strong>e E<strong>in</strong>trittskarte für e<strong>in</strong>en bestim<strong>mt</strong>en Sitzplatz nur e<strong>in</strong>mal verkauft<br />
wer<strong>de</strong>n).<br />
Hier arbeitet man mit verschie<strong>de</strong>nen Informationsquellen. Man befragt zukünftige<br />
Benutzer <strong>de</strong>s Anwendungssystems, sichtet Dokumente o<strong><strong>de</strong>r</strong> analysiert e<strong>in</strong> vielleicht<br />
bereits bestehen<strong>de</strong>s Anwendungssystem und lernt so die Organisation und das<br />
Geschäftsumfeld kennen. Ebenso ist es wichtig, <strong>in</strong> Gesprächen mit <strong>de</strong>n zukünftigen<br />
Benutzern <strong>de</strong>s Anwendungssystems Begriffe zu erlernen, die im täglichen Geschäftsumfeld<br />
verwen<strong>de</strong>t wer<strong>de</strong>n. Bei<strong>de</strong> Seiten, <strong><strong>de</strong>r</strong> Analytiker und <strong><strong>de</strong>r</strong> zukünftige Benutzer,<br />
müssen die »gleiche Sprache« sprechen. Benutzer betrachten e<strong>in</strong>en Geschäftsprozess <strong>in</strong><br />
<strong><strong>de</strong>r</strong> Regel nur aus ihrer Sicht, je nach<strong>de</strong>m, welche Funktion sie im Unternehmen <strong>in</strong>nehaben.<br />
Es ist <strong>de</strong>shalb notwendig, von möglichst vielen Benutzern Informationen über<br />
e<strong>in</strong>en Geschäftsprozess zu erhalten, um so zu e<strong>in</strong>er allgeme<strong>in</strong>en Sichtweise zu gelangen.<br />
In dieser zweiten Phase sammelt man e<strong>in</strong>e Menge an Informationen, die teilweise<br />
Lücken enthalten o<strong><strong>de</strong>r</strong> aber auch wi<strong><strong>de</strong>r</strong>sprüchlich s<strong>in</strong>d. Um diese »Flut« an Informationen<br />
zu bewältigen, erstellt man e<strong>in</strong> konzeptionelles Funktions- und Datenmo<strong>de</strong>ll.<br />
Im Funktionsmo<strong>de</strong>ll beschreibt man, wie Geschäftsprozesse ablaufen, im Datenmo<strong>de</strong>ll,<br />
welche Daten dazu benötigt wer<strong>de</strong>n.<br />
Neben <strong><strong>de</strong>r</strong> strukturierten textuellen Beschreibung wer<strong>de</strong>n die konzeptionellen Datenund<br />
Funktionsmo<strong>de</strong>lle zur Veranschaulichung grafisch dargestellt. Für die grafische<br />
Notation <strong>de</strong>s Datenmo<strong>de</strong>lls wird <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>Praxis</strong> vorwiegend das »Entity-Relationship-<br />
Mo<strong>de</strong>ll« (ERM) verwen<strong>de</strong>t (siehe Abschnitt 3.4), für die grafische Notation <strong>de</strong>s Funktionsmo<strong>de</strong>lls<br />
die »Unified Mo<strong>de</strong>l<strong>in</strong>g Language« (UML) (siehe Abschnitt 3.6). Dabei<br />
wird <strong><strong>de</strong>r</strong> UML zukünftig auch <strong>in</strong> <strong><strong>de</strong>r</strong> Datenmo<strong>de</strong>llierung e<strong>in</strong>e höhere Be<strong>de</strong>utung<br />
zukommen. Zum e<strong>in</strong>en, um e<strong>in</strong>e mehr o<strong><strong>de</strong>r</strong> weniger e<strong>in</strong>heitliche Notation zu verwen<strong>de</strong>n,<br />
zum an<strong><strong>de</strong>r</strong>en aber auch, weil immer mehr funktionale Elemente durch das Datenbanksystem<br />
selbst abgebil<strong>de</strong>t wer<strong>de</strong>n.<br />
Das entstan<strong>de</strong>ne konzeptionelle Mo<strong>de</strong>ll wird <strong>in</strong> <strong><strong>de</strong>r</strong> zweiten Phase zur Diskussion mit<br />
<strong>de</strong>m Kun<strong>de</strong>n e<strong>in</strong>gesetzt. Die zukünftigen Endbenutzer überprüfen das Mo<strong>de</strong>ll auf noch<br />
gewünschte Funktionen o<strong><strong>de</strong>r</strong> eventuell vorhan<strong>de</strong>ne Fehler o<strong><strong>de</strong>r</strong> Missverständnisse. Das<br />
konzeptionelle Mo<strong>de</strong>ll dient also als Diskussionsplattform mit <strong>de</strong>m Kun<strong>de</strong>n, genauso<br />
wie e<strong>in</strong> Architekt <strong>de</strong>n »Bauplan« mit <strong>de</strong>m zukünftigen Hausbesitzer durchspricht.<br />
Der fertige konzeptionelle Entwurf dient <strong>in</strong> <strong><strong>de</strong>r</strong> dritten Phase als Grundlage zur Erstellung<br />
e<strong>in</strong>es logischen Entwurfes. Der logische Entwurf setzt das Daten- und Funktionsmo<strong>de</strong>ll<br />
DV-technisch um. Es stellt sozusagen e<strong>in</strong>e »Brücke« zwischen <strong>de</strong>m fachlichen<br />
Konzept und <strong><strong>de</strong>r</strong> eigentlichen Software dar. Die Notation <strong>de</strong>s »Entity Relationship<br />
Mo<strong>de</strong>lls« (ERM) kann nicht direkt <strong>in</strong> e<strong>in</strong>e Datenbankstruktur transformiert wer<strong>de</strong>n.<br />
Schließlich dient das ERM ja vorwiegend dazu, die fachlichen Aspekte <strong>de</strong>s Geschäftsumfel<strong>de</strong>s<br />
mit <strong>de</strong>m Kun<strong>de</strong>n zu klären. Entsprechend ist es von <strong><strong>de</strong>r</strong> Notation sehr e<strong>in</strong>fach<br />
aber auch e<strong>in</strong>gängig gehalten. Es muss also <strong>in</strong> e<strong>in</strong> logisches Mo<strong>de</strong>ll überführt wer<strong>de</strong>n.<br />
In <strong><strong>de</strong>r</strong> <strong>Praxis</strong> für relationale Datenbanken hat sich hier das Relationenmo<strong>de</strong>ll<br />
etabliert. E<strong>in</strong>e Überführung vom ERM <strong>in</strong> das Relationenmo<strong>de</strong>ll ist relativ e<strong>in</strong>fach und<br />
33
34<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
kann nach bestim<strong>mt</strong>en Transformationsregeln vorgenommen wer<strong>de</strong>n. Das Relationenmo<strong>de</strong>ll<br />
wird <strong>de</strong>tailliert im Kapitel 4 beschrieben.<br />
Im Gegensatz zum Datenmo<strong>de</strong>ll wird beim Funktionsmo<strong>de</strong>ll <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>Praxis</strong> nach <strong>de</strong>m<br />
konzeptionellen auch das logische Mo<strong>de</strong>ll mit <strong><strong>de</strong>r</strong> UML entworfen.<br />
Phase 4 stellt die eigentliche Implementierung <strong>de</strong>s Anwendungssystems dar. Nach<strong>de</strong>m<br />
e<strong>in</strong> Mo<strong>de</strong>ll <strong>in</strong> <strong><strong>de</strong>r</strong> dritten Phase erstellt wur<strong>de</strong>, das formal DV-technisch abbildbar ist,<br />
beg<strong>in</strong>nt man <strong>in</strong> <strong><strong>de</strong>r</strong> vierten Phase mit <strong><strong>de</strong>r</strong> Programmierung und <strong><strong>de</strong>r</strong> DV-technischen<br />
Umsetzung <strong><strong>de</strong>r</strong> Datenbankstruktur. Dafür wird bei relationalen Datenbanken die<br />
»Structured Query Language« (SQL) verwen<strong>de</strong>t, die wir genauer ab Kapitel 6 kennen<br />
lernen wer<strong>de</strong>n. Die Umsetzung <strong>de</strong>s Funktionsmo<strong>de</strong>lls erfolgt mit gängigen Programmiersprachen<br />
wie C++, Java, Visual Basic o<strong><strong>de</strong>r</strong> C#, aber auch mit SQL. Seit <strong><strong>de</strong>r</strong> Verabschiedung<br />
<strong>de</strong>s zweiten SQL-Standards im Jahr 1992 enthält SQL Sprachelemente prozeduraler<br />
Programmiersprachen. Im dritten Standard 1999 wur<strong>de</strong> SQL <strong>in</strong> dieser<br />
H<strong>in</strong>sicht noch e<strong>in</strong>mal erweitert. Es ist <strong>de</strong>shalb heutzutage üblich, mit dieser Sprache<br />
nicht nur die Datenbankstrukturen und Datenbankabfragen zu realisieren, son<strong><strong>de</strong>r</strong>n<br />
auch e<strong>in</strong>en Großteil von Funktionen abzubil<strong>de</strong>n. Hierauf wer<strong>de</strong>n wir genauer <strong>in</strong> <strong>de</strong>n<br />
Kapiteln 12 bis 14 e<strong>in</strong>gehen.<br />
Als Ergebnis <strong><strong>de</strong>r</strong> vierten Phase entsteht die eigentliche Software, die zu diesem Zeitpunkt<br />
immer wie<strong><strong>de</strong>r</strong> getestet und mit <strong>de</strong>m Kun<strong>de</strong>n auch auf fachliche Korrektheit<br />
überprüft wer<strong>de</strong>n sollte.<br />
In <strong><strong>de</strong>r</strong> fünften Phase wird das getestete Anwendungssystem beim Kun<strong>de</strong>n e<strong>in</strong>geführt<br />
und entsprechend e<strong>in</strong>em vorher <strong>de</strong>f<strong>in</strong>ierten Plan vom Kun<strong>de</strong>n abgenommen. E<strong>in</strong><br />
Abnahmeplan sollte vorher festgelegte Szenarien enthalten, die die DV-technisch abgebil<strong>de</strong>ten<br />
Geschäftsprozesse auf korrekte Funktionalität überprüfen. Wur<strong>de</strong> das<br />
Anwendungssystem vom Kun<strong>de</strong>n abgenommen, so muss es gewartet wer<strong>de</strong>n, d.h. es<br />
muss Mitarbeiter geben, die die Computer warten, die Endbenutzer betreuen und<br />
eventuell schulen sowie die gesa<strong>mt</strong>e DV-Umgebung überwachen.<br />
Das vorgestellte Phasenkonzept sollte generell niemals als e<strong>in</strong> durchgehen<strong><strong>de</strong>r</strong> Prozess<br />
betrachtet wer<strong>de</strong>n. Gera<strong>de</strong> zwischen <strong>de</strong>n Phasen 2 und 4 wird es oft wie<strong><strong>de</strong>r</strong> Rücksprünge<br />
geben, da fachliche o<strong><strong>de</strong>r</strong> technische Aspekte nicht <strong>in</strong> e<strong>in</strong>er vorherigen Phase<br />
berücksichtigt wur<strong>de</strong>n. Nehmen wir unser Beispiel <strong><strong>de</strong>r</strong> Firma »KartoF<strong>in</strong>ale« . Dort<br />
wur<strong>de</strong> <strong><strong>de</strong>r</strong> Bezahlvorgang nach Rechnungsversand bisher noch gar nicht berücksichtigt.<br />
Wür<strong>de</strong> das Projekt nun beg<strong>in</strong>nen und erst bei <strong><strong>de</strong>r</strong> Umsetzung <strong>de</strong>s Anwendungssystems<br />
<strong>in</strong> Phase 4 die Nichtberücksichtigung <strong>de</strong>s Bezahlvorgangs bemerkt wer<strong>de</strong>n,<br />
e<strong>in</strong>e DV-technische Umsetzung aber vom Kun<strong>de</strong>n gewünscht ist, so muss entsprechend<br />
zur Phase 2 zurückgesprungen und das konzeptionelle und logische Mo<strong>de</strong>ll<br />
geän<strong><strong>de</strong>r</strong>t wer<strong>de</strong>n. Natürlich sollten wichtige Punkte e<strong>in</strong>es Geschäftsprozesses wie <strong><strong>de</strong>r</strong><br />
Bezahlvorgang von e<strong>in</strong>em Analytiker bereits vorher berücksichtigt wer<strong>de</strong>n. Häufig<br />
s<strong>in</strong>d es <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>Praxis</strong> aber auch Kle<strong>in</strong>igkeiten o<strong><strong>de</strong>r</strong> technische Restriktionen, die zu<br />
e<strong>in</strong>em Rücksprung führen. Generell gilt es jedoch, <strong>in</strong> <strong>de</strong>n Phasen 1 bis 3 das Anwendungssystem<br />
so weit zu entwerfen, dass solche unliebsamen »Überraschungen« erst<br />
gar nicht auftreten. Dementsprechend sollte man diese Phasen nicht unterschätzen und<br />
hier ausreichend Zeit und Sorgfalt <strong>in</strong>vestieren. Gera<strong>de</strong> die Vernachlässigung dieser<br />
Phasen führt immer wie<strong><strong>de</strong>r</strong> zum Scheitern von Softwareprojekten.
Konzeptioneller Entwurf (Datenmo<strong>de</strong>llierung)<br />
3.3 Konzeptioneller Entwurf<br />
(Datenmo<strong>de</strong>llierung)<br />
3.3.1 Grundlagen<br />
Im letzten Abschnitt haben wir kennen gelernt, wie e<strong>in</strong> komplettes Softwareprojekt<br />
vom Projektanstoß bis zum eigentlichen E<strong>in</strong>satz umgesetzt wird. Wir haben gesehen,<br />
dass die Datenmo<strong>de</strong>llierung selbst nur e<strong>in</strong> Teil <strong>de</strong>s gesa<strong>mt</strong>en Entwicklungsprozesses<br />
ausmacht und von <strong><strong>de</strong>r</strong> Funktionsmo<strong>de</strong>llierung getrennt wird. Diese Trennung ist s<strong>in</strong>nvoll,<br />
da e<strong>in</strong> Datenmo<strong>de</strong>ll nicht so sehr an e<strong>in</strong> bestim<strong>mt</strong>es Anwendungssystem angelehnt<br />
und abstrakter betrachtet wer<strong>de</strong>n sollte. Stellen Sie sich vor, Sie müssten für Ihre<br />
Firma e<strong>in</strong> Personalabrechnungssystem entwickeln. Wür<strong>de</strong>n Sie das Datenmo<strong>de</strong>ll nur<br />
für e<strong>in</strong> Personalabrechnungssystem erstellen, wür<strong>de</strong>n Beziehungen zu an<strong><strong>de</strong>r</strong>en wichtigen<br />
Geschäftsobjekten <strong><strong>de</strong>r</strong> Firma verloren gehen. Sie hätten e<strong>in</strong>e Insellösung entwickelt,<br />
die ausschließlich für die Personalabrechnung funktioniert. Anwendungssysteme<br />
für weitere Geschäftsprozesse z.B. zur Kun<strong>de</strong>nbetreuung müssten entwe<strong><strong>de</strong>r</strong> e<strong>in</strong>e<br />
eigene Datenbank erhalten o<strong><strong>de</strong>r</strong> die Datenbankstruktur <strong><strong>de</strong>r</strong> Personalabrechnung<br />
müsste <strong>in</strong> größerem Maße geän<strong><strong>de</strong>r</strong>t wer<strong>de</strong>n. Die erste Lösung hätte wie<strong><strong>de</strong>r</strong> <strong>de</strong>n uns<br />
bereits bekannten Nachteil <strong><strong>de</strong>r</strong> Datenredundanz: Mitarbeiterdaten wür<strong>de</strong>n <strong>in</strong> <strong><strong>de</strong>r</strong><br />
Firma mehrfach gespeichert wer<strong>de</strong>n. Die zweite Lösung dagegen wür<strong>de</strong> für je<strong>de</strong>s neu<br />
zu entwickeln<strong>de</strong> Anwendungssystem e<strong>in</strong>en »Rattenschwanz« von Än<strong><strong>de</strong>r</strong>ungen <strong>in</strong><br />
bereits bestehen<strong>de</strong>n Anwendungssystemen nach sich ziehen.<br />
Man geht heute <strong>de</strong>shalb dazu über, so genannte unternehmensweite Datenmo<strong>de</strong>lle<br />
(UDM) zu entwerfen, die e<strong>in</strong> Datenmo<strong>de</strong>ll und damit e<strong>in</strong>e e<strong>in</strong>zige Datenbasis für e<strong>in</strong><br />
gesa<strong>mt</strong>es Unternehmen abbil<strong>de</strong>n. Auf Grundlage dieser Datenbasis sollten dann beliebige<br />
Anwendungssysteme für das Unternehmen entwickelt wer<strong>de</strong>n können, ohne die<br />
grundlegen<strong>de</strong> Struktur <strong><strong>de</strong>r</strong> Datenbank <strong>in</strong> größerem Ausmaß zu än<strong><strong>de</strong>r</strong>n.<br />
Daneben existieren Referenzmo<strong>de</strong>lle bestim<strong>mt</strong>er Branchen. Es ist also möglich, so e<strong>in</strong><br />
Daten-Referenzmo<strong>de</strong>ll zu nehmen und es an die eigenen Bedürfnisse <strong>de</strong>s Unternehmens<br />
anzupassen.<br />
Doch zurück zum eigentlichen konzeptionellen Datenbankentwurf. Dieser wird für<br />
zwei Personengruppen erstellt. Zum e<strong>in</strong>en für <strong>de</strong>n Analytiker, <strong><strong>de</strong>r</strong> ihn als »Bauplan«<br />
zur Absprache mit <strong>de</strong>m Kun<strong>de</strong>n verwen<strong>de</strong>t. Zum an<strong><strong>de</strong>r</strong>en für <strong>de</strong>n Datenbank<strong>de</strong>signer,<br />
<strong><strong>de</strong>r</strong> <strong>de</strong>n konzeptionellen Entwurf als Basis für die Umsetzung <strong>in</strong> e<strong>in</strong>en logischen und<br />
schließlich <strong>in</strong> e<strong>in</strong>en physischen Entwurf verwen<strong>de</strong>t.<br />
Bei<strong>de</strong> Personengruppen haben entsprechend unterschiedliche Wünsche an e<strong>in</strong> Datenmo<strong>de</strong>ll.<br />
Für <strong>de</strong>n Analytiker und <strong>de</strong>n Kun<strong>de</strong>n soll das Datenmo<strong>de</strong>ll möglichst leicht<br />
verständlich se<strong>in</strong>. Dies heißt jedoch auch, dass es weniger <strong>de</strong>tailliert ist. Demgegenüber<br />
wünscht sich <strong><strong>de</strong>r</strong> Datenbank<strong>de</strong>signer e<strong>in</strong> Datenmo<strong>de</strong>ll, das möglichst <strong>de</strong>tailliert und<br />
komplett ist. Dieses geht jedoch <strong>in</strong> <strong><strong>de</strong>r</strong> Regel zu Lasten <strong><strong>de</strong>r</strong> Übersichtlichkeit und Verständlichkeit.<br />
35
36<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
Generell lässt sich zusammenfassen, dass es <strong>in</strong> <strong><strong>de</strong>r</strong> Datenmo<strong>de</strong>llierung um das I<strong>de</strong>ntifizieren<br />
und Klassifizieren von Geschäftsobjekten <strong>de</strong>s Geschäftsumfel<strong>de</strong>s und <strong><strong>de</strong>r</strong>en<br />
kennzeichnen<strong>de</strong>n Merkmale sowie <strong><strong>de</strong>r</strong> Beziehungen zwischen ihnen geht.<br />
E<strong>in</strong> Datenmo<strong>de</strong>ll besteht aus:<br />
� strukturiertem Text,<br />
� grafischer Notation.<br />
Der strukturierte Text beschreibt <strong>de</strong>tailliert die i<strong>de</strong>ntifizierten und klassifizierten<br />
Geschäftsobjekte und <strong><strong>de</strong>r</strong>en Beziehungen, sowie vorhan<strong>de</strong>ne Regeln bzw. E<strong>in</strong>schränkungen.<br />
Der strukturierte Text dient vorwiegend <strong>de</strong>m Datenbank<strong>de</strong>signer zum Entwurf<br />
<strong>de</strong>s logischen und physischen Datenmo<strong>de</strong>lls.<br />
Die grafische Notation dient <strong><strong>de</strong>r</strong> Übersicht und vor allem <strong>de</strong>m Verständnis <strong><strong>de</strong>r</strong><br />
Geschäftsobjekte und <strong><strong>de</strong>r</strong>en Beziehungen, da grafische Mo<strong>de</strong>lle vom Menschen ganzheitlich<br />
besser aufgenommen wer<strong>de</strong>n können. An<strong><strong>de</strong>r</strong>erseits verzichten grafische<br />
Mo<strong>de</strong>lle auf Details.<br />
Da es um Geschäftsobjekte und <strong><strong>de</strong>r</strong>en Beziehungen geht, gibt es verschie<strong>de</strong>ne grafische<br />
Elemente für:<br />
1) Geschäftsobjekte,<br />
2) Attribute,<br />
3) E<strong>in</strong><strong>de</strong>utige I<strong>de</strong>ntifizierer (Schlüssel),<br />
4) Beziehungen,<br />
5) Beziehungstypen,<br />
6) Sub- bzw. Supertypen.<br />
Im Folgen<strong>de</strong>n wollen wir uns mit drei grafischen Notationen bzw. Mo<strong>de</strong>llen, die <strong>in</strong> <strong><strong>de</strong>r</strong><br />
<strong>Praxis</strong> relevant s<strong>in</strong>d, ause<strong>in</strong>an<strong><strong>de</strong>r</strong>setzen, <strong>de</strong>m »Entity-Relationship-Mo<strong>de</strong>ll« (ERM) nach<br />
Chen, <strong>de</strong>m »Entity-Relationship-Mo<strong>de</strong>ll« (ERM) nach Barker und <strong><strong>de</strong>r</strong> »Unified Mo<strong>de</strong>l<strong>in</strong>g<br />
Language« (UML). Zum Schluss je<strong>de</strong>s vorgestellten Mo<strong>de</strong>lls, wird anhand <strong>de</strong>s praxisorientierten<br />
Fallbeispiels e<strong>in</strong> Datenmo<strong>de</strong>ll mit <strong><strong>de</strong>r</strong> jeweiligen Notation erstellt, um<br />
die Unterschie<strong>de</strong> zwischen diesen grafischen Notationen kennen zu lernen.<br />
Bevor wir uns jedoch mit <strong>de</strong>n drei grafischen Notationen ause<strong>in</strong>an<strong><strong>de</strong>r</strong>setzen, wollen<br />
wir erst e<strong>in</strong>mal unser Fallbeispiel beschreiben, die oben aufgeführten sechs Elemente<br />
<strong>de</strong>f<strong>in</strong>ieren und schließlich betrachten, wie man aus <strong><strong>de</strong>r</strong> Beschreibung e<strong>in</strong>es Geschäftsumfel<strong>de</strong>s<br />
diese Elemente i<strong>de</strong>ntifizieren kann.<br />
3.3.2 Fallbeispiel<br />
Herr Dr. Fleissig von <strong><strong>de</strong>r</strong> Unternehmensberatung »Software Consult AG« hat <strong>in</strong>zwischen<br />
verschie<strong>de</strong>ne Dokumente und Formulare gesichtet und sich mit <strong>de</strong>n meisten<br />
relevanten Mitarbeitern von »KartoF<strong>in</strong>ale« unterhalten. Zunächst berichtet er se<strong>in</strong>em<br />
Geschäftsführer von <strong>de</strong>n Kun<strong>de</strong>n und <strong>de</strong>n Artikeln, die »KartoF<strong>in</strong>ale« verkauft:<br />
»E<strong>in</strong> Artikel kann entwe<strong><strong>de</strong>r</strong> e<strong>in</strong>e E<strong>in</strong>trittskarte o<strong><strong>de</strong>r</strong> e<strong>in</strong> Werbeartikel zu e<strong>in</strong>er Veranstaltung<br />
se<strong>in</strong>. Zu e<strong>in</strong>er Veranstaltung kann es mehrere Werbeartikel geben, e<strong>in</strong> Werbe-
Konzeptioneller Entwurf (Datenmo<strong>de</strong>llierung)<br />
artikel ist immer genau e<strong>in</strong>er Veranstaltung zugeordnet (z.B. »Cats T-Shirt« ist Veranstaltung<br />
»Cats« zugeordnet). Es gibt also ke<strong>in</strong>en Werbeartikel, <strong><strong>de</strong>r</strong> für verschie<strong>de</strong>ne<br />
Veranstaltungen verkauft wird. E<strong>in</strong>e Veranstaltung besteht aus mehreren Vorstellungsterm<strong>in</strong>en,<br />
zu <strong>de</strong>nen die Veranstaltung stattf<strong>in</strong><strong>de</strong>t. E<strong>in</strong>e Vorstellung f<strong>in</strong><strong>de</strong>t <strong>in</strong> e<strong>in</strong>er<br />
bestim<strong>mt</strong>en Spielstätte statt. Nehmen wir e<strong>in</strong>mal e<strong>in</strong> Beispiel: Zu <strong><strong>de</strong>r</strong> Veranstaltung<br />
»Don Giovanni von Mozart« gibt es drei Vorstellungen, und zwar am 1., 8. und 15.<br />
Oktober jeweils um 20 Uhr. Die Vorstellungen am 1. und 8. Oktober f<strong>in</strong><strong>de</strong>n <strong>in</strong> <strong><strong>de</strong>r</strong> Spielstätte<br />
»Deutsche Staatsoper« <strong>in</strong> Hamburg statt, die Vorstellung am 15. Oktober im<br />
»Hamburger Operettenhaus« .<br />
E<strong>in</strong> Kun<strong>de</strong> kann mehrere Artikel kaufen und e<strong>in</strong> bestim<strong>mt</strong>er Artikel kann von mehreren<br />
Kun<strong>de</strong>n gekauft wer<strong>de</strong>n. Der Werbeartikel »Cats T-Shirt« kann von mehreren Kun<strong>de</strong>n<br />
gekauft wer<strong>de</strong>n, da er mehr als e<strong>in</strong>mal bei »KartoF<strong>in</strong>ale« vorrätig ist. Entsprechend<br />
kann e<strong>in</strong> Kun<strong>de</strong> mehrere Werbeartikel kaufen, z.B. das »Cats T-Shirt« und auch das<br />
Plakat zu dieser Veranstaltung.<br />
Bestellt <strong><strong>de</strong>r</strong> Kun<strong>de</strong> Artikel, so nim<strong>mt</strong> e<strong>in</strong> bestim<strong>mt</strong>er Mitarbeiter die Bestellung telefonisch<br />
entgegen. E<strong>in</strong> Mitarbeiter bearbeitet mehrere Bestellungen, an<strong><strong>de</strong>r</strong>erseits wird<br />
e<strong>in</strong>e bestim<strong>mt</strong>e Bestellung genau von e<strong>in</strong>em Mitarbeiter bearbeitet.<br />
Je<strong>de</strong> Abteilung von »KartoF<strong>in</strong>ale« besteht aus mehreren Mitarbeitern. E<strong>in</strong> Mitarbeiter<br />
ist immer genau e<strong>in</strong>er Abteilung zugeordnet.<br />
3.3.3 Geschäftsobjekte<br />
E<strong>in</strong> Geschäftsobjekt, o<strong><strong>de</strong>r</strong> allgeme<strong>in</strong>er e<strong>in</strong> Objekt, ist e<strong>in</strong> Element, das e<strong>in</strong><strong>de</strong>utig i<strong>de</strong>ntifiziert<br />
und von an<strong><strong>de</strong>r</strong>en Objekten anhand se<strong>in</strong>er Eigenschaften unterschie<strong>de</strong>n wer<strong>de</strong>n<br />
kann. Es stellt sozusagen e<strong>in</strong>e »Schablone« dar, um gleichartige D<strong>in</strong>ge und <strong><strong>de</strong>r</strong>en<br />
Informationen zusammenzufassen. E<strong>in</strong> Objekt kann entwe<strong><strong>de</strong>r</strong> se<strong>in</strong><br />
� etwas real Existieren<strong>de</strong>s (z.B. Person, Flugzeug, Buch),<br />
� e<strong>in</strong> Ereignis (z.B. »Artikel bestellen« , »Tee tr<strong>in</strong>ken« , »Gespräch führen« , »Rechnung<br />
zahlen« ),<br />
� e<strong>in</strong>e Rolle o<strong><strong>de</strong>r</strong> Person (z.B. Arzt, Patient, Richter, Kun<strong>de</strong>, Staatspräsi<strong>de</strong>nt),<br />
� e<strong>in</strong>e Organisation (z.B. Firma, Abteilung, Behör<strong>de</strong>n),<br />
� e<strong>in</strong> Konzept (z.B. Projekt, Mo<strong>de</strong>llbeschreibung) o<strong><strong>de</strong>r</strong><br />
� e<strong>in</strong>e Transaktion (z.B. Kaufvertrag).<br />
Entsprechend fassen wir unter e<strong>in</strong>em Objekttyp o<strong><strong>de</strong>r</strong> e<strong>in</strong>er Objektklasse also D<strong>in</strong>ge<br />
zusammen, die durch gleichartige Merkmale beschrieben wer<strong>de</strong>n können und <strong><strong>de</strong>r</strong>en<br />
Merkmale je<strong>de</strong>s Element e<strong>in</strong><strong>de</strong>utig i<strong>de</strong>ntifizieren.<br />
Betrachten wir hierzu e<strong>in</strong>mal unser Fallbeispiel: Die Firma »KartoF<strong>in</strong>ale« hat mehrere<br />
Mitarbeiter und diese Mitarbeiter haben Merkmale, die sie vone<strong>in</strong>an<strong><strong>de</strong>r</strong> unterschei<strong>de</strong>n.<br />
In <strong>de</strong>n Merkmalstypen stimmen die Mitarbeiter zwar übere<strong>in</strong> (Name, Abteilung, Personalnummer,<br />
Adresse), aber nicht <strong>in</strong> <strong>de</strong>n jeweiligen Ausprägungen.<br />
37
38<br />
Wun<strong><strong>de</strong>r</strong>, Hans<br />
Rechnungswesen<br />
10<br />
Kohlweg 1<br />
12345 Kohlsen<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
Name<br />
Abteilung<br />
Personalnummer<br />
Strasse<br />
Plz/Ort<br />
Klug, Frieda<br />
Market<strong>in</strong>g<br />
8<br />
Musterweg 110<br />
22222 Hamburg<br />
Objekttyp / Klasse<br />
Abbildung 3.4: Objekte und <strong><strong>de</strong>r</strong>en kennzeichnen<strong>de</strong> Merkmale<br />
Objekttypen bzw. Objektklassen kann man <strong>in</strong> e<strong>in</strong>er Textbeschreibung grammatikalisch<br />
häufig als Substantive ausmachen. Jedoch s<strong>in</strong>d nicht alle im Text vorkommen<strong>de</strong>n Substantive<br />
gleichzeitig auch Objekttypen. Je<strong>de</strong>s Objekt dieses Objekttyps muss über se<strong>in</strong>e<br />
Merkmale e<strong>in</strong><strong>de</strong>utig i<strong>de</strong>ntifizierbar se<strong>in</strong>. Entsprechend sollte es mehr als e<strong>in</strong> beschreiben<strong>de</strong>s<br />
Merkmal besitzen und natürlich e<strong>in</strong>en <strong>de</strong>f<strong>in</strong>ierten Geschäftszweck besitzen. So<br />
sche<strong>in</strong>t es auf <strong>de</strong>n ersten Blick so, als sei »E<strong>in</strong>trittskarte« prä<strong>de</strong>st<strong>in</strong>iert als Objekttyp, da<br />
es sche<strong>in</strong>bar e<strong>in</strong>en wichtigen Geschäftszweck erfüllt. Überlegen wir uns jedoch, welche<br />
Merkmale e<strong>in</strong>e E<strong>in</strong>trittskarte besitzt. Dazu ist es s<strong>in</strong>nvoll, zunächst anhand e<strong>in</strong>es Beispiels<br />
vorzugehen. Betrachten wir e<strong>in</strong>e E<strong>in</strong>trittskarte für »Don Giovanni« am 1. Oktober<br />
um 20 Uhr. Neben diesen Informationen ist auf <strong><strong>de</strong>r</strong> E<strong>in</strong>trittskarte noch <strong><strong>de</strong>r</strong> Sitzplatz<br />
vermerkt. Überlegen wir, welchen Objekten diese Merkmale zugeordnet wer<strong>de</strong>n. Die<br />
Bezeichnung »Don Giovanni« ist primär e<strong>in</strong>e Eigenschaft <strong><strong>de</strong>r</strong> Veranstaltung, <strong><strong>de</strong>r</strong> Term<strong>in</strong><br />
e<strong>in</strong>e Eigenschaft <strong><strong>de</strong>r</strong> Vorstellung und <strong><strong>de</strong>r</strong> Sitzplatz e<strong>in</strong>e Eigenschaft <strong><strong>de</strong>r</strong> Spielstätte<br />
und damit <strong>in</strong>direkt <strong><strong>de</strong>r</strong> Vorstellung. E<strong>in</strong>trittskarte ist also ke<strong>in</strong> Objekt, da es ke<strong>in</strong>e<br />
Informationen be<strong>in</strong>haltet. Indirekt stellt die E<strong>in</strong>trittskarte e<strong>in</strong> Synonym für e<strong>in</strong>en Sitzplatz<br />
dar. E<strong>in</strong> Kun<strong>de</strong> kauft also abstrakt betrachtet, e<strong>in</strong>en Sitzplatz für e<strong>in</strong>e Vorstellung<br />
und ke<strong>in</strong>e E<strong>in</strong>trittskarte. Damit ist die E<strong>in</strong>trittskarte nur e<strong>in</strong> Beleg, um e<strong>in</strong>en Sitzplatz<br />
zu e<strong>in</strong>em bestim<strong>mt</strong>en Term<strong>in</strong> <strong>in</strong> e<strong>in</strong>er Spielstätte zu »mieten« .<br />
Solche Erkenntnisse s<strong>in</strong>d manchmal schwer zu durchschauen, weshalb gera<strong>de</strong> das<br />
Interview unterschiedlicher Personen zu <strong>de</strong>m jeweiligen Geschäftsumfeld wichtig ist.<br />
�<br />
�<br />
Münze, Egon<br />
E<strong>in</strong>kauf<br />
3<br />
�<br />
Geldstr. 10<br />
22343 Reichtum<br />
Objekt / Instanz
Konzeptioneller Entwurf (Datenmo<strong>de</strong>llierung)<br />
In unserem Fallbeispiel ergeben sich folgen<strong>de</strong> Objekttypen bzw. Objektklassen:<br />
� Abteilung,<br />
� Mitarbeiter,<br />
� Kun<strong>de</strong>,<br />
� Artikel,<br />
� Werbeartikel,<br />
� Vorstellung,<br />
� Veranstaltung,<br />
� Spielstätte,<br />
� Sitzplatz.<br />
3.3.4 Sub- bzw. Supertypen<br />
E<strong>in</strong> Subtyp ist e<strong>in</strong>e Untermenge von übergeordneten Objekten e<strong>in</strong>es Supertyps. Subbzw.<br />
Supertypen stellen <strong>de</strong>shalb e<strong>in</strong>e Beson<strong><strong>de</strong>r</strong>heit von Objekttypen dar, um Informationen<br />
hierarchisch abzubil<strong>de</strong>n.<br />
Betrachten wir hierzu wie<strong><strong>de</strong>r</strong>um unser Fallbeispiel. E<strong>in</strong> Kun<strong>de</strong> kauft e<strong>in</strong>en Artikel. E<strong>in</strong><br />
Artikel stellt im obigen S<strong>in</strong>ne e<strong>in</strong>en Objekttyp dar, da er durch verschie<strong>de</strong>ne Merkmale<br />
wie Preis, Bezeichnung usw. charakterisiert wird. An<strong><strong>de</strong>r</strong>erseits verkauft »KartoF<strong>in</strong>ale«<br />
zwei unterschiedliche Arten von Artikeln: Sitzplätze und Werbeartikel. Geme<strong>in</strong> ist<br />
Sitzplätzen und Werbeartikeln e<strong>in</strong>e Artikelbezeichnung und e<strong>in</strong>e Artikelnummer.<br />
Dagegen hat e<strong>in</strong> bestim<strong>mt</strong>er Werbeartikel immer <strong>de</strong>n gleichen Preis, e<strong>in</strong> Sitzplatz<br />
jedoch unterschiedliche Preise.<br />
Es ist <strong>de</strong>shalb s<strong>in</strong>nvoll, e<strong>in</strong>en übergeordneten Objekttyp (Supertyp) zu <strong>de</strong>f<strong>in</strong>ieren, <strong>in</strong><br />
diesem Fall Artikel, <strong><strong>de</strong>r</strong> die geme<strong>in</strong>samen Merkmale be<strong>in</strong>haltet. Daneben entwirft man<br />
zwei weitere untergeordnete Objekttypen (Subtypen) für Werbeartikel und Sitzplatz,<br />
die vom Supertyp die Merkmale sozusagen erben. Aufgrund <strong><strong>de</strong>r</strong> Über- bzw. Unterordnung<br />
von Sub- und Supertypen spricht man auch von Hierarchisierung, Generalisierung<br />
und Spezialisierung. Spezialisierung bezieht sich <strong>in</strong> diesem Fall auf <strong>de</strong>n Subtypen,<br />
<strong><strong>de</strong>r</strong> aufgrund zusätzlicher Attribute genauer spezifiziert wird. Generalisierung<br />
bezieht sich auf <strong>de</strong>n Supertypen, <strong><strong>de</strong>r</strong> die geme<strong>in</strong>samen allgeme<strong>in</strong>en Attribute <strong><strong>de</strong>r</strong><br />
untergeordneten Objekttypen enthält und Hierarchisierung auf die entstehen<strong>de</strong> Struktur,<br />
die e<strong>in</strong>e Hierarchie abbil<strong>de</strong>t. Die Abbildung 3.5 ver<strong>de</strong>utlicht diesen Zusammenhang<br />
noch e<strong>in</strong>mal am Beispiel von Gebäu<strong>de</strong>n.<br />
Der Objekttyp »Gebäu<strong>de</strong>« ist dabei Supertyp von »Hochhaus« , »E<strong>in</strong>familienhaus« und<br />
auch von »Reihenhaus« und »Doppelhaushälfte« . Der Objekttyp »E<strong>in</strong>familienhaus« ist<br />
Supertyp von »Reihenhaus« und »Doppelhaushälfte« . »E<strong>in</strong>familienhaus« erbt also z.B.<br />
die Attribute »Baujahr« und »Architekt« von se<strong>in</strong>em Supertyp »Gebäu<strong>de</strong>« , »Doppelhaushälfte«<br />
erbt zusätzlich zu <strong>de</strong>n Attributen »Baujahr« und »Architekt« die Attribute<br />
»Dachform« , »Anzahl Zimmer« und »Größe« .<br />
39
40<br />
Spezialisierung<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
Hochhaus<br />
������ ������ Hochhaus<br />
������ ������ ��������� ������<br />
������ ���������<br />
Gebäu<strong>de</strong><br />
������� Gebäu<strong>de</strong><br />
��������� �������<br />
���������<br />
ist e<strong>in</strong><br />
3.3.5 Attribute und Schlüssel<br />
E<strong>in</strong>familienhaus<br />
�������� E<strong>in</strong>familienhaus<br />
������ �������� ������<br />
����� ������ ������<br />
�����<br />
ist e<strong>in</strong>(e)<br />
Reihenhaus<br />
��� �������������� Reihenhaus �����<br />
������ ��� �������������� ������������ �����<br />
������ ������������<br />
Abbildung 3.5: Beispiel für Super- und Subtypen<br />
Doppelhaushälfte<br />
������������ Doppelhaushälfte<br />
���������<br />
������������ ���������<br />
Attribute s<strong>in</strong>d Informationsobjekte, die Objekttypen beschreiben o<strong><strong>de</strong>r</strong> i<strong>de</strong>ntifizieren.<br />
Attribute, die e<strong>in</strong>en Objekttyp e<strong>in</strong><strong>de</strong>utig i<strong>de</strong>ntifizieren bezeichnet man als Schlüssel<br />
bzw. Schlüsselattribut.<br />
Attribute sollten vollständig für e<strong>in</strong>en Objekttyp aufgeführt wer<strong>de</strong>n, soweit sie für <strong>de</strong>n<br />
Geschäftszweck notwendig s<strong>in</strong>d. Sie sollten atomar und unabhängig vone<strong>in</strong>an<strong><strong>de</strong>r</strong> se<strong>in</strong>.<br />
So setzt sich z.B. <strong><strong>de</strong>r</strong> Name e<strong>in</strong>er Person aus zwei Attributen zusammen, <strong>de</strong>m Vornamen<br />
und <strong>de</strong>m Nachnamen. Wür<strong>de</strong> man nur e<strong>in</strong> Attribut Name für Vor- und Nachname<br />
<strong>de</strong>f<strong>in</strong>ieren, so wäre dieses Attribut nicht mehr atomar, da es ja aus zwei Attributen<br />
besteht.<br />
Die Werte von Attributen müssen unabhängig vone<strong>in</strong>an<strong><strong>de</strong>r</strong> se<strong>in</strong>. Wür<strong>de</strong> man für e<strong>in</strong>en<br />
Objekttyp »Rechnung« zwei Attribute »Rabattprozentsatz« und »Rabattbetrag« <strong>de</strong>f<strong>in</strong>ieren,<br />
so müsste bei e<strong>in</strong>er Än<strong><strong>de</strong>r</strong>ung <strong>de</strong>s Rabattprozentsatzes auch <strong><strong>de</strong>r</strong> Rabattbetrag<br />
geän<strong><strong>de</strong>r</strong>t wer<strong>de</strong>n. Der Rabattbetrag ist jedoch e<strong>in</strong> abgeleiteter Attributwert, da es e<strong>in</strong><br />
prozentual berechneter Anteil vom Rechnungsbetrag ist, so dass auf das Attribut<br />
»Rabattbetrag« verzichtet wer<strong>de</strong>n kann. Hierbei kom<strong>mt</strong> es aber auch auf die Sichtweise<br />
an. Angenommen, e<strong>in</strong>em Objekttyp »Mitarbeiter« wur<strong>de</strong> das Attribut »Anzahl K<strong>in</strong><strong><strong>de</strong>r</strong>«<br />
zugewiesen. Das Attribut »Anzahl K<strong>in</strong><strong><strong>de</strong>r</strong>« ist nur dann s<strong>in</strong>nvoll, wenn es nicht<br />
gleichzeitig e<strong>in</strong>en Objekttyp »K<strong>in</strong><strong><strong>de</strong>r</strong>« gibt, <strong>in</strong> <strong>de</strong>m die Namen <strong><strong>de</strong>r</strong> K<strong>in</strong><strong><strong>de</strong>r</strong> <strong><strong>de</strong>r</strong> Mitarbeiter<br />
gespeichert wer<strong>de</strong>n. Wäre dies <strong><strong>de</strong>r</strong> Fall, so könnte die Anzahl <strong><strong>de</strong>r</strong> K<strong>in</strong><strong><strong>de</strong>r</strong> ja berechnet<br />
wer<strong>de</strong>n, wodurch dann die Information über die Anzahl <strong><strong>de</strong>r</strong> K<strong>in</strong><strong><strong>de</strong>r</strong> doppelt<br />
gespeichert wer<strong>de</strong>n wür<strong>de</strong>, e<strong>in</strong>mal im Objekttyp »Mitarbeiter« und e<strong>in</strong> zweites Mal<br />
<strong>in</strong>direkt im Objekttyp »K<strong>in</strong><strong><strong>de</strong>r</strong>« .<br />
Generalisierung
Konzeptioneller Entwurf (Datenmo<strong>de</strong>llierung)<br />
Schließlich wird e<strong>in</strong> Attribut durch e<strong>in</strong>en bestim<strong>mt</strong>en Wertebereich gekennzeichnet.<br />
E<strong>in</strong>e Personalnummer ist <strong>in</strong> <strong><strong>de</strong>r</strong> Regel e<strong>in</strong>e Zahl. E<strong>in</strong> Attribut »Geschlecht« dürfte nur<br />
zwei mögliche Werte be<strong>in</strong>halten, weiblich und männlich. Das Attribut »Zustand« <strong>de</strong>s<br />
Objekttyps »Sitzplatz« kann z.B. nur die Werte für »belegt« , »frei« o<strong><strong>de</strong>r</strong> »reserviert«<br />
annehmen. Man spricht hier von Wertebereich o<strong><strong>de</strong>r</strong> Domäne (Doma<strong>in</strong>).<br />
Attribute von Objekttypen f<strong>in</strong><strong>de</strong>t man am besten, <strong>in</strong><strong>de</strong>m man überlegt, welche Eigenschaften<br />
Objekte e<strong>in</strong>es Objekttyps geme<strong>in</strong>sam haben bzw. welche Objekteigenschaften<br />
man benötigt, um sagen zu können, um welchen Objekttyp es sich han<strong>de</strong>lt. So reichen<br />
die bei<strong>de</strong>n Attribute Name und Vorname nicht aus, um z.B. sagen zu können, ob »Egon<br />
Münze« e<strong>in</strong> Objekt <strong>de</strong>s Objekttyps »Mitarbeiter« o<strong><strong>de</strong>r</strong> »Kun<strong>de</strong>« ist.<br />
In unserem Fallbeispiel ergeben sich folgen<strong>de</strong> Attribute für die jeweiligen Objekttypen:<br />
Objekttyp Attribute<br />
Abteilung Abteilungsbezeichnung, Abteilungsnummer, Abteilungsleiter<br />
Mitarbeiter Name, Vorname, Strasse, Plz, Ort<br />
Ehepartner Name, Vorname, Alter<br />
Kun<strong>de</strong> Name, Vorname, Strasse, Plz, Ort<br />
Artikel Artikelnummer, Artikelbezeichnung<br />
Werbeartikel Beschreibung, Preis, Lagerbestand<br />
Vorstellung Datum, Uhrzeit<br />
Veranstaltung Bezeichnung, Autor<br />
Spielstätte Haus, Strasse, Plz, Ort<br />
Sitzplatz Reihe, Sitz, Bereich, Preis, Zustand<br />
Nach<strong>de</strong>m wir die Attribute für unsere Objekttypen <strong>de</strong>f<strong>in</strong>iert haben, müssen wir überlegen,<br />
welche Attribute bzw. Attributkomb<strong>in</strong>ationen notwendig s<strong>in</strong>d, um e<strong>in</strong> bestim<strong>mt</strong>es<br />
Objekt e<strong>in</strong>es Objekttyps e<strong>in</strong><strong>de</strong>utig zu i<strong>de</strong>ntifizieren. Dieses i<strong>de</strong>ntifizieren<strong>de</strong> Attribut<br />
bezeichnet man als Schlüssel. Gibt es mehrere Schlüssel, so spricht man von Schlüsselkandidaten.<br />
In diesem Falle muss e<strong>in</strong> Schlüsselkandidat ausgewählt wer<strong>de</strong>n, <strong><strong>de</strong>r</strong> als so<br />
genannter Primärschlüssel fungieren soll und über <strong>de</strong>n e<strong>in</strong> Objekt e<strong>in</strong>es Objekttyps<br />
immer e<strong>in</strong><strong>de</strong>utig i<strong>de</strong>ntifiziert wird. E<strong>in</strong> Schlüssel kann auch aus mehreren Attributen<br />
zusammengesetzt se<strong>in</strong>, generell gilt jedoch, dass e<strong>in</strong> Primärschlüssel e<strong>in</strong>e m<strong>in</strong>imale<br />
Anzahl von Attributen enthalten sollte.<br />
Betrachten wir unseren Objekttyp »Abteilung« . Sowohl die Abteilungsnummer als<br />
auch die Abteilungsbezeichnung i<strong>de</strong>ntifizieren e<strong>in</strong><strong>de</strong>utig e<strong>in</strong>e Abteilung. Wir haben<br />
also zwei Schlüsselkandidaten und entschei<strong>de</strong>n uns für die Abteilungsbezeichnung als<br />
Primärschlüssel.<br />
Betrachten wir nun, welches Attribut bzw. welche Attributkomb<strong>in</strong>ation für Kun<strong>de</strong> als<br />
Schlüssel <strong>in</strong> Frage kom<strong>mt</strong>. Da Namen wie »Hans Meier« mehr als e<strong>in</strong>mal vorkommen<br />
können, ist die Komb<strong>in</strong>ation aus Vorname und Name nicht als Schlüssel geeignet.<br />
41
42<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
Auch die Wahrsche<strong>in</strong>lichkeit, dass <strong>in</strong> e<strong>in</strong>em Hochhaus <strong>in</strong> <strong><strong>de</strong>r</strong> gleichen Strasse und im<br />
gleichen Ort zwei Kun<strong>de</strong>n mit gleichem Namen vorkommen können, ist möglich.<br />
Zwar können wir die Etage bei <strong><strong>de</strong>r</strong> Postadresse mit aufführen, müssten dann jedoch als<br />
Primärschlüssel alle vorhan<strong>de</strong>nen Attribute nehmen. Das ist zwar möglich, aber nicht<br />
beson<strong><strong>de</strong>r</strong>s praktikabel. In e<strong>in</strong>em solchen Fall wird <strong>in</strong> <strong><strong>de</strong>r</strong> Regel e<strong>in</strong> künstlicher Schlüssel<br />
<strong>de</strong>f<strong>in</strong>iert. Wir wollen dieses Attribut als Kun<strong>de</strong>nnummer bezeichnen und <strong>de</strong>f<strong>in</strong>ieren<br />
diese als Primärschlüssel. Wir können zwar auch e<strong>in</strong>en Schlüssel aus Nachname und<br />
Kun<strong>de</strong>nnummer festlegen, dieses wür<strong>de</strong> jedoch <strong>de</strong>m oben erwähnten Pr<strong>in</strong>zip <strong><strong>de</strong>r</strong><br />
M<strong>in</strong>imalität e<strong>in</strong>es Primärschlüssels wi<strong><strong>de</strong>r</strong>sprechen.<br />
In Abschnitt 3.3.3 haben wir kennen gelernt, dass die Objekttypen »Werbeartikel« und<br />
»Vorstellung« Subtypen von Artikel s<strong>in</strong>d. Dadurch wer<strong>de</strong>n diese bei<strong>de</strong>n Objekttypen<br />
<strong>in</strong>direkt durch <strong>de</strong>n Primärschlüssel <strong>de</strong>s Artikels e<strong>in</strong><strong>de</strong>utig i<strong>de</strong>ntifiziert.<br />
Betrachten wir exemplarisch noch unseren Objekttypen »Sitzplatz« . Um e<strong>in</strong>en Sitzplatz<br />
<strong>in</strong>nerhalb e<strong>in</strong>er Spielstätte e<strong>in</strong><strong>de</strong>utig zu i<strong>de</strong>ntifizieren, müssen <strong>in</strong> diesem Fall drei<br />
Attribute mite<strong>in</strong>an<strong><strong>de</strong>r</strong> komb<strong>in</strong>iert wer<strong>de</strong>n. E<strong>in</strong> Sitz wird e<strong>in</strong><strong>de</strong>utig <strong>in</strong> e<strong>in</strong>er Reihe<br />
bestim<strong>mt</strong>, e<strong>in</strong>e Reihe wie<strong><strong>de</strong>r</strong>um e<strong>in</strong><strong>de</strong>utig <strong>in</strong>nerhalb e<strong>in</strong>es Bereiches (Parkett, Rang<br />
usw.). Damit ergibt sich als Primärschlüssel für Sitzplatz die Attributkomb<strong>in</strong>ation aus<br />
Bereich, Reihe und Sitz o<strong><strong>de</strong>r</strong> umgekehrt. Wenn für e<strong>in</strong>e Vorstellung <strong><strong>de</strong>r</strong> Bereich, die<br />
Reihe und <strong><strong>de</strong>r</strong> Sitz bekannt s<strong>in</strong>d, so kann das Objekt und damit auch se<strong>in</strong>e Eigenschaften<br />
e<strong>in</strong><strong>de</strong>utig gefun<strong>de</strong>n wer<strong>de</strong>n. In diesem Fall auf <strong>de</strong>n Preis und <strong>de</strong>n Zustand für diesen<br />
Sitzplatz.<br />
Für unser Beispiel ergeben sich folgen<strong>de</strong> Primärschlüssel (jeweils unterstrichen dargestellt):<br />
Objekttyp Attribute<br />
Abteilung Abteilungsbezeichnung, Abteilungsnummer, Abteilungsleiter<br />
Mitarbeiter Personalnummer, Name, Vorname, Strasse, Plz, Ort<br />
Ehepartner Name, Vorname, Alter<br />
Kun<strong>de</strong> Kun<strong>de</strong>nnummer, Name, Vorname, Strasse, Plz, Ort<br />
Artikel Artikelnummer, Artikelbezeichnung<br />
Werbeartikel Artikelnummer, Beschreibung, Preis, Lagerbestand<br />
Vorstellung Vorstellungsnummer, Datum, Uhrzeit<br />
Veranstaltung Veranstaltungsnummer, Bezeichnung, Autor<br />
Spielstätte Haus, Strasse, Plz, Ort<br />
Sitzplatz Reihe, Sitz, Bereich, Preis, Zustand<br />
E<strong>in</strong> Problem haben wir hierbei allerd<strong>in</strong>gs noch: Betrachten wir e<strong>in</strong>mal <strong>de</strong>n Primärschlüssel<br />
vom Objekttyp »Sitzplatz« . Ist Bereich, Reihe und Sitz bekannt, so muss man<br />
zusätzlich noch wissen, <strong>in</strong> welcher Spielstätte und für welche Vorstellung diese<br />
Informationen gedacht s<strong>in</strong>d. Entsprechen<strong>de</strong>s gilt für Mitarbeiter und Ehepartner. Ohne<br />
die Personalnummer <strong>de</strong>s Mitarbeiters kann <strong><strong>de</strong>r</strong> Ehepartner nicht ermittelt wer<strong>de</strong>n. Um
Konzeptioneller Entwurf (Datenmo<strong>de</strong>llierung)<br />
dieses Problem <strong>in</strong> e<strong>in</strong>em Datenmo<strong>de</strong>ll zu berücksichtigen, müssen wir uns mit <strong>de</strong>n<br />
Beziehungen zwischen Objekttypen ause<strong>in</strong>an<strong><strong>de</strong>r</strong>setzen.<br />
3.3.6 Beziehungen und Beziehungstypen<br />
Beziehungen s<strong>in</strong>d Assoziationen zwischen Objekttypen und können grammatikalisch<br />
<strong>in</strong> <strong><strong>de</strong>r</strong> Regel durch Verben <strong>in</strong> e<strong>in</strong>er Textbeschreibung ausgemacht wer<strong>de</strong>n. Die wohl<br />
bekannteste Beziehung ist die zwischen Mann und Frau. Da Beziehungen gegenseitiger<br />
Natur s<strong>in</strong>d, ist die Beziehungsrichtung bei <strong><strong>de</strong>r</strong> Betrachtung von Be<strong>de</strong>utung. Aus<br />
<strong><strong>de</strong>r</strong> Sicht <strong>de</strong>s Mitarbeiters besteht die Beziehung »Mitarbeiter gehört zu Abteilung« ,<br />
aus <strong><strong>de</strong>r</strong> Sicht <strong><strong>de</strong>r</strong> Abteilung lautet die Beziehung dagegen »Abteilung besteht aus Mitarbeitern«<br />
.<br />
Bezogen auf unser Fallbeispiel ergeben sich z.B. folgen<strong>de</strong> Beziehungen:<br />
Beziehungsrichtung 1 Beziehungsrichtung 2<br />
Mitarbeiter gehört zu Abteilung Abteilung besteht aus Mitarbeitern<br />
Mitarbeiter ist verheiratet mit Ehepartner Ehepartner ist verheiratet mit Mitarbeiter<br />
Mitarbeiter hat Vorgesetzten Vorgesetzter hat Mitarbeiter<br />
Kun<strong>de</strong> bestellt Artikel Artikel wird von Kun<strong>de</strong> bestellt<br />
Werbeartikel ist für Veranstaltung Veranstaltung bietet Werbeartikel<br />
Veranstaltung besteht aus Vorstellungen Vorstellung gehört zu Veranstaltung<br />
Vorstellung hat Sitzplätze Sitzplatz gehört zeitlich zu Vorstellung<br />
Spielstätte führt Vorstellungen auf<br />
Artikel ist e<strong>in</strong> Werbeartikel o<strong><strong>de</strong>r</strong> e<strong>in</strong> Sitzplatz<br />
Vorstellung f<strong>in</strong><strong>de</strong>t <strong>in</strong> Spielstätte statt<br />
Die letzte Beziehung stellt ke<strong>in</strong>e typische Beziehung dar, son<strong><strong>de</strong>r</strong>n besteht, wie bereits<br />
oben erwähnt, aus e<strong>in</strong>em Supertyp und zwei Subtypen. Die Beziehung »ist e<strong>in</strong>« gibt <strong>in</strong><br />
<strong><strong>de</strong>r</strong> Regel e<strong>in</strong>en H<strong>in</strong>weis, dass es sich bei e<strong>in</strong>er Beziehung um Super- und Subtypen<br />
han<strong>de</strong>lt. Diese Beziehung wird entsprechend <strong><strong>de</strong>r</strong> englischen Übersetzung von »ist e<strong>in</strong>«<br />
häufig auch als »is a« -Beziehung bezeichnet.<br />
Beziehungen zwischen Objekttypen enthalten unterschiedliche Merkmale wie Kard<strong>in</strong>alität<br />
und Optionalität. Kard<strong>in</strong>alität legt fest, wie viele Objekte <strong>de</strong>s e<strong>in</strong>en Objekttyps<br />
<strong>in</strong> Beziehung zu e<strong>in</strong>em Objekt <strong>de</strong>s an<strong><strong>de</strong>r</strong>en Objekttyps stehen und umgekehrt. Optionalität<br />
legt fest, ob e<strong>in</strong> Objekt e<strong>in</strong>es Objekttyps immer <strong>in</strong> Beziehung zu e<strong>in</strong>em an<strong><strong>de</strong>r</strong>en<br />
Objekt stehen muss, o<strong><strong>de</strong>r</strong> ob es optional ist. Bei <strong><strong>de</strong>r</strong> Beziehung zwischen Mitarbeiter<br />
und Ehepartner sollte genau e<strong>in</strong> Mitarbeiter e<strong>in</strong>e Beziehung zu e<strong>in</strong>em Ehepartner<br />
haben (Kard<strong>in</strong>alität von 1:1). Dennoch gibt es auch Mitarbeiter ohne Ehepartner, d.h.<br />
die Beziehung zwischen Mitarbeiter und Ehepartner ist nicht zw<strong>in</strong>gend, nicht je<strong><strong>de</strong>r</strong><br />
Mitarbeiter hat e<strong>in</strong>e Beziehung zu e<strong>in</strong>em Ehepartner, die Beziehung ist also optional<br />
(Optionalität). Die Kard<strong>in</strong>alität kann also bei Ehepartner auch Null se<strong>in</strong>.<br />
43
44<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
Dazu e<strong>in</strong> weiteres Beispiel: E<strong>in</strong>e Abteilung besteht aus mehreren Mitarbeitern und e<strong>in</strong><br />
Mitarbeiter gehört zu e<strong>in</strong>er Abteilung. Betrachten wir das Ganze e<strong>in</strong>mal grafisch für<br />
unser Fallbeispiel:<br />
Menge <strong><strong>de</strong>r</strong> Objekte<br />
Mitarbeiter<br />
Wun<strong><strong>de</strong>r</strong>, Hans<br />
Klug, Frieda<br />
Herr Kle<strong>in</strong><br />
Herr Kowalski<br />
���<br />
Münze, Egon<br />
Inga Klaus<br />
Frau Kart<br />
Menge <strong><strong>de</strong>r</strong> Objekte<br />
Abteilung<br />
Rechnungswesen<br />
Personal<br />
Vertrieb<br />
Abbildung 3.6: 1:N-Beziehung zwischen »Mitarbeiter« und »Abteilung«<br />
Die Abteilung »Personal« besteht aus e<strong>in</strong>em Mitarbeiter, Herrn Münze, und Herr<br />
Münze ist auch nur dieser Abteilung zugeordnet. Auf dieses Objekt bezogen haben wir<br />
also e<strong>in</strong>e Kard<strong>in</strong>alität von 1:1. Betrachten wir nun jedoch <strong>de</strong>n Vertrieb, so erkennen wir,<br />
dass <strong><strong>de</strong>r</strong> Vertrieb aus fünf Mitarbeitern besteht. Umgekehrt ist je<strong><strong>de</strong>r</strong> dieser fünf Mitarbeiter<br />
auch nur dieser Abteilung zugeordnet. Es gibt also ke<strong>in</strong>en Vertriebsmitarbeiter,<br />
<strong><strong>de</strong>r</strong> eventuell auch noch <strong><strong>de</strong>r</strong> Abteilung Rechnungswesen zugeordnet ist. Wir erkennen<br />
also e<strong>in</strong>e Kard<strong>in</strong>alität von 1:5 bzw. allgeme<strong>in</strong>er von 1:N, wobei N e<strong>in</strong>e beliebige Ganzzahl<br />
ist. Betrachten wir nun Herrn Kowalski. Als Geschäftsführer gehört er zwar zu<br />
<strong>de</strong>m Objekttyp <strong><strong>de</strong>r</strong> Mitarbeiter, ist aber ke<strong>in</strong>er Abteilung zugeordnet, d.h. e<strong>in</strong>e Zuordnung<br />
von e<strong>in</strong>em Mitarbeiter zu e<strong>in</strong>er Abteilung ist optional. E<strong>in</strong> Mitarbeiter kann also<br />
e<strong>in</strong>er o<strong><strong>de</strong>r</strong> auch ke<strong>in</strong>er Abteilung angehören (max. 1 Abteilung) und e<strong>in</strong>e Abteilung<br />
kann e<strong>in</strong>en o<strong><strong>de</strong>r</strong> mehrere Mitarbeiter haben (max. N Mitarbeiter).
Konzeptioneller Entwurf (Datenmo<strong>de</strong>llierung)<br />
Wir sprechen <strong>de</strong>shalb bei <strong><strong>de</strong>r</strong> Beziehung von Mitarbeiter zu Abteilung von e<strong>in</strong>em 1:N-<br />
Beziehungstyp. Neben <strong>de</strong>m 1:N-Beziehungstyp gibt es noch zwei weitere Beziehungstypen,<br />
<strong>de</strong>n 1:1-Beziehungstyp und <strong>de</strong>n N:M-Beziehungstyp. Bei e<strong>in</strong>em 1:1-Beziehungstyp<br />
steht immer genau e<strong>in</strong> Objekt <strong>de</strong>s e<strong>in</strong>en Objekttyps <strong>in</strong> Beziehung zu genau<br />
e<strong>in</strong>em Objekt <strong>de</strong>s an<strong><strong>de</strong>r</strong>en Objekttyps. So ist z.B. Mitarbeiter »Hans Wun<strong><strong>de</strong>r</strong>« mit<br />
genau e<strong>in</strong>em Ehepartner, nämlich »Karla Wun<strong><strong>de</strong>r</strong>« , verheiratet.<br />
Um die Kard<strong>in</strong>alität von Objekttypen zue<strong>in</strong>an<strong><strong>de</strong>r</strong> festzulegen, geht man am besten<br />
zunächst von e<strong>in</strong>em Objekt aus und überlegt, ob es zu e<strong>in</strong>em o<strong><strong>de</strong>r</strong> mehreren Objekten<br />
<strong>de</strong>s an<strong><strong>de</strong>r</strong>en Objekttyps e<strong>in</strong>e Beziehung hat. Diesen Vorgang kehrt man danach entsprechend<br />
um und überlegt dieses aus <strong><strong>de</strong>r</strong> Sicht <strong>de</strong>s an<strong><strong>de</strong>r</strong>en Objekttyps.<br />
In unserem Beispiel hat je<strong><strong>de</strong>r</strong> Mitarbeiter genau e<strong>in</strong>en Ehepartner o<strong><strong>de</strong>r</strong> ke<strong>in</strong>en bzw. umgekehrt<br />
ist je<strong><strong>de</strong>r</strong> Ehepartner mit genau e<strong>in</strong>em Mitarbeiter verheiratet (Kard<strong>in</strong>alität 1:1).<br />
Menge <strong><strong>de</strong>r</strong> Objekte<br />
Mitarbeiter<br />
Wun<strong><strong>de</strong>r</strong>, Hans<br />
Klug, Frieda<br />
Herr Kle<strong>in</strong><br />
Herr Kowalski<br />
���<br />
Münze, Egon<br />
Inga Klaus<br />
Frau Kart<br />
Menge <strong><strong>de</strong>r</strong> Objekte<br />
Ehepartner<br />
Münze, Maja<br />
Wun<strong><strong>de</strong>r</strong>, Karla<br />
Kle<strong>in</strong>, Bertha<br />
Klug, Helmut<br />
Kowalski, Marie<br />
Abbildung 3.7: 1:1-Beziehung zwischen »Mitarbeiter« und »Ehepartner«<br />
Vier Mitarbeiter s<strong>in</strong>d verheiratet, die an<strong><strong>de</strong>r</strong>en Mitarbeiter nicht, entsprechend ist die<br />
Beziehung von Seiten <strong>de</strong>s Mitarbeiters optional, von Seiten <strong>de</strong>s Ehepartners jedoch<br />
nicht.<br />
45
46<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
Bei e<strong>in</strong>em N:M-Beziehungstyp stehen beliebig viele Objekte <strong>de</strong>s e<strong>in</strong>en Objekttyps <strong>in</strong><br />
Beziehung zu beliebig vielen Objekten <strong>de</strong>s an<strong><strong>de</strong>r</strong>en Beziehungstyps. In unserem Fallbeispiel<br />
f<strong>in</strong><strong>de</strong>n wir so e<strong>in</strong>e Beziehung zwischen Kun<strong>de</strong> und Artikel. Je<strong><strong>de</strong>r</strong> Kun<strong>de</strong> kann<br />
beliebig viele Artikel kaufen bzw. je<strong><strong>de</strong>r</strong> Artikel kann von unterschiedlichen Kun<strong>de</strong>n<br />
gekauft wer<strong>de</strong>n.<br />
Die Kund<strong>in</strong> »Frieda Wiegerich« kauft drei unterschiedliche Artikel. Der Artikel »Don<br />
Giovanni« wird z.B. von zwei unterschiedlichen Kun<strong>de</strong>n gekauft.<br />
Menge <strong><strong>de</strong>r</strong> Objekte<br />
Kun<strong>de</strong><br />
Muster, Hans<br />
Wiegerich, Frieda<br />
Bolte, Bertram<br />
Menge <strong><strong>de</strong>r</strong> Objekte<br />
Artikel<br />
„Don Giovanni“<br />
Programmheft<br />
„Don Giovanni“<br />
Plakat „Cats“<br />
Abbildung 3.8: N:M-Beziehung zwischen »Kun<strong>de</strong>« und »Artikel«<br />
Zum Schluss dieses Abschnitts wollen wir noch e<strong>in</strong>e Beson<strong><strong>de</strong>r</strong>heit bei Beziehungen<br />
betrachten: Die Beziehung von Objekten e<strong>in</strong>es Objekttyps zu Objekten <strong>de</strong>s gleichen<br />
Objekttyps. Man spricht hier auch von rekursiven Beziehungen.<br />
Betrachten wir wie<strong><strong>de</strong>r</strong> unser Fallbeispiel: E<strong>in</strong> Mitarbeiter hat genau e<strong>in</strong>en Vorgesetzten<br />
und e<strong>in</strong> Vorgesetzter hat mehrere Mitarbeiter. E<strong>in</strong> Vorgesetzter ist jedoch auch e<strong>in</strong><br />
Objekt <strong>de</strong>s Objekttyps Mitarbeiter. Um nun diese Beziehung abzubil<strong>de</strong>n, stellt man<br />
e<strong>in</strong>en Verweis auf <strong>de</strong>n Objekttyp selber her. So ist »Herr Kowalski« direkter Vorgesetzter<br />
von <strong>de</strong>n Abteilungsleitern »Hans Wun<strong><strong>de</strong>r</strong>« , »Egon Münze« und »Frau Kart« . Frau<br />
Kart wie<strong><strong>de</strong>r</strong>um ist direkte Vorgesetzte von ihren vier Mitarbeitern, d.h. sie ist <strong>in</strong> <strong><strong>de</strong>r</strong><br />
e<strong>in</strong>en Beziehung Mitarbeiter und <strong>in</strong> e<strong>in</strong>er an<strong><strong>de</strong>r</strong>en Beziehung Vorgesetzte.<br />
„Cats“<br />
T-Shirt „Cats“
Konzeptioneller Entwurf (Datenmo<strong>de</strong>llierung)<br />
Rekursive Beziehungen treten selten auf und wenn, dann meistens als Beziehungstyp<br />
1:N, so wie es auch <strong>in</strong> unserem Beispiel <strong><strong>de</strong>r</strong> Fall ist. Dabei s<strong>in</strong>d sie bei <strong><strong>de</strong>r</strong> Darstellung<br />
bzw. Umsetzung nicht schwieriger o<strong><strong>de</strong>r</strong> an<strong><strong>de</strong>r</strong>s zu handhaben als Beziehungstypen<br />
zwischen zwei unterschiedlichen Objekttypen, da je<strong>de</strong> Beziehung für sich getrennt<br />
betrachtet wird.<br />
Menge <strong><strong>de</strong>r</strong> Objekte<br />
Mitarbeiter /<br />
Vorgesetzter<br />
Herr Kowalski<br />
Wun<strong><strong>de</strong>r</strong>, Hans Klug, Frieda<br />
�<br />
��<br />
Münze, Egon<br />
Frau Kart<br />
Herr Kle<strong>in</strong><br />
Inga Klaus<br />
Abbildung 3.9: rekursive 1:N-Beziehung zwischen »Mitarbeitern« und »Vorgesetzten«<br />
Für unser Fallbeispiel ergeben sich folgen<strong>de</strong> Beziehungen und Beziehungstypen:<br />
E<strong>in</strong> Mitarbeiter gehört zu e<strong>in</strong>er Abteilung 1:1<br />
E<strong>in</strong>e Abteilung besteht aus mehreren Mitarbeitern 1:N<br />
Abteilung – Mitarbeiter 1:N-Beziehung<br />
E<strong>in</strong> Mitarbeiter ist verheiratet mit e<strong>in</strong>em Ehepartner 1:1<br />
E<strong>in</strong> Ehepartner ist verheiratet mit e<strong>in</strong>em Mitarbeiter 1:1<br />
Mitarbeiter – Ehepartner 1:1-Beziehung<br />
E<strong>in</strong> Mitarbeiter hat genau e<strong>in</strong>en Vorgesetzten 1:1<br />
E<strong>in</strong> Vorgesetzter hat mehrere Mitarbeiter 1:N<br />
Vorgesetzter- Mitarbeiter 1:N-Beziehung<br />
47
48<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
E<strong>in</strong> Kun<strong>de</strong> bestellt mehrere Artikel 1:N<br />
Mehrere Artikel wer<strong>de</strong>n von e<strong>in</strong>em Kun<strong>de</strong>n bestellt N:1<br />
Kun<strong>de</strong> – Artikel N:M-Beziehung<br />
E<strong>in</strong> Werbeartikel ist für e<strong>in</strong>e bestim<strong>mt</strong>e Veranstaltung 1:1<br />
E<strong>in</strong>e Veranstaltung bietet mehrere Werbeartikel 1:N<br />
Werbeartikel – Veranstaltung 1:N-Beziehung<br />
E<strong>in</strong>e Vorstellung gehört zu e<strong>in</strong>er Veranstaltung 1:1<br />
E<strong>in</strong>e Veranstaltung enthält mehrere Vorstellungen 1:N<br />
Veranstaltung – Vorstellung 1:N-Beziehung<br />
E<strong>in</strong> Sitzplatz gehört zeitlich zu e<strong>in</strong>er Vorstellung 1:1<br />
E<strong>in</strong>e Vorstellung hat mehrere Sitzplätze 1:N<br />
Vorstellung – Sitzplatz 1:N-Beziehung<br />
E<strong>in</strong>e Vorstellung f<strong>in</strong><strong>de</strong>t <strong>in</strong> e<strong>in</strong>er Spielstätte statt 1:1<br />
E<strong>in</strong>e Spielstätte führt mehrere Vorstellungen auf 1:N<br />
Spielstätte – Vorstellung 1:N-Beziehung<br />
E<strong>in</strong> Artikel ist e<strong>in</strong> Werbeartikel 1:1<br />
Artikel – Werbeartikel 1:1-Beziehung<br />
E<strong>in</strong> Artikel ist e<strong>in</strong> Sitzplatz 1:1<br />
Artikel – Sitzplatz 1:1-Beziehung<br />
Nach<strong>de</strong>m wir uns mit <strong>de</strong>n grafischen Elementen e<strong>in</strong>er Notation für e<strong>in</strong> Datenmo<strong>de</strong>ll<br />
ause<strong>in</strong>an<strong><strong>de</strong>r</strong>gesetzt haben, wollen wir uns im Folgen<strong>de</strong>n mit <strong>de</strong>n drei praxisrelevanten<br />
grafischen Notationen ause<strong>in</strong>an<strong><strong>de</strong>r</strong>setzen.
»Entity-Relationship-Mo<strong>de</strong>ll« nach Chen<br />
3.4 »Entity-Relationship-Mo<strong>de</strong>ll« nach Chen<br />
3.4.1 Grundlagen<br />
Das heute am weitesten verbreitete Datenmo<strong>de</strong>ll ist das »Entity-Relationship-Mo<strong>de</strong>ll«<br />
(ERM) bzw. »Entity-Relationship-Diagramm« (ERD). Es basiert auf e<strong>in</strong>em Artikel von<br />
Peter P<strong>in</strong>-Shan Chen aus <strong>de</strong>m Jahre 1976 im »ACM – Transactions on Database Systems«<br />
-Journal.<br />
Das Mo<strong>de</strong>ll von Chen ist leicht zu verstehen, begnügt sich mit <strong>de</strong>n wichtigsten grafischen<br />
Elementen und hat sich gera<strong>de</strong> <strong>de</strong>shalb <strong>in</strong> <strong><strong>de</strong>r</strong> Kommunikation mit <strong>de</strong>m Kun<strong>de</strong>n<br />
durchgesetzt. Außer<strong>de</strong>m ist es auch leicht <strong>in</strong> e<strong>in</strong> logisches Mo<strong>de</strong>ll für relationale Datenbanken,<br />
<strong>de</strong>m Relationenmo<strong>de</strong>ll von E.F. Codd, umzusetzen. Die Umsetzung e<strong>in</strong>es ERM<br />
<strong>in</strong> das Relationenmo<strong>de</strong>ll von Codd betrachten wir <strong>de</strong>tailliert im Kapitel 4.<br />
Mit <strong>de</strong>n Jahren hat es von verschie<strong>de</strong>nen Personen Än<strong><strong>de</strong>r</strong>ungen und Erweiterungen an<br />
<strong>de</strong>m »Entity-Relationship-Mo<strong>de</strong>ll« gegeben, die sich u.a. auch auf die grafischen Symbole<br />
bezogen. Dies führte dazu, dass es heute ke<strong>in</strong>en e<strong>in</strong>heitlichen Standard gibt, was die<br />
grafischen Symbole und die Mo<strong>de</strong>llelemente betrifft. Die ursprüngliche I<strong>de</strong>e ist jedoch <strong>in</strong><br />
<strong>de</strong>n verän<strong><strong>de</strong>r</strong>ten Mo<strong>de</strong>llen erhalten geblieben. Wir wollen zunächst das ERM nach Chen<br />
betrachten, das allerd<strong>in</strong>gs heute nicht mehr so oft <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>Praxis</strong> e<strong>in</strong>gesetzt wird. Danach<br />
schauen wir uns das ERM nach Barker an, das vor allem aufgrund se<strong>in</strong>er leichteren Lesbarkeit<br />
und Übersichtlichkeit heute <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>Praxis</strong> am weitesten verbreitet ist.<br />
3.4.2 Geschäftsobjekte<br />
Geschäftsobjekte wer<strong>de</strong>n im ERM als Entity bezeichnet, daher spricht man hier auch<br />
nicht von Objekttypen, son<strong><strong>de</strong>r</strong>n von Entitytypen.<br />
Entitytypen wer<strong>de</strong>n nach Chen <strong>in</strong> e<strong>in</strong>em Rechteck dargestellt.<br />
Abteilung Mitarbeiter Ehepartner<br />
3.4.3 Sub- bzw. Supertypen<br />
Abbildung 3.10: Darstellung von Entitytypen<br />
In <strong><strong>de</strong>r</strong> ursprünglichen Notation von Chen gab es ke<strong>in</strong>e grafische Notation für Sub- und<br />
Supertypen. Sie wur<strong>de</strong>n jedoch <strong>in</strong> <strong><strong>de</strong>r</strong> Folgezeit von Robert Brown und Mat Flav<strong>in</strong> (vgl.<br />
hierzu [Hay99]) h<strong>in</strong>zugefügt. Dabei wird für je<strong>de</strong>n Subtypen und Supertypen e<strong>in</strong> eigenes<br />
Rechteck verwen<strong>de</strong>t. Die »ist e<strong>in</strong>« -Beziehung o<strong><strong>de</strong>r</strong> auf englisch »is a« -Beziehung<br />
wird über das grafische Symbol e<strong>in</strong>er Raute dargestellt. Der kle<strong>in</strong>e Querstrich vor <strong>de</strong>m<br />
Subtypen soll kennzeichnen, dass <strong><strong>de</strong>r</strong> Entitytyp »Sitzplatz« ohne se<strong>in</strong>en Supertypen<br />
»Artikel« nicht existieren kann.<br />
49
50<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
3.4.4 Attribute und Schlüssel<br />
Attribute wer<strong>de</strong>n <strong>in</strong> Form e<strong>in</strong>es Kreises an <strong>de</strong>n jeweiligen Entitytyp angehängt. Primärschlüssel<br />
wer<strong>de</strong>n dabei nicht geson<strong><strong>de</strong>r</strong>t dargestellt, so dass man aus <strong><strong>de</strong>r</strong> Grafik<br />
nicht unmittelbar erkennen kann, ob es sich bei e<strong>in</strong>em Attribut um e<strong>in</strong>en Schlüssel han<strong>de</strong>lt.<br />
Allerd<strong>in</strong>gs ist es heutzutage üblich, <strong>de</strong>n Primärschlüssel unterstrichen darzustellen,<br />
weshalb wir uns dieser Konvention auch anschließen wollen.<br />
Abteilungsbezeichnung<br />
Abteilungsnummer<br />
Artikel<br />
Werbeartikel Sitzplatz<br />
Abbildung 3.11: Darstellung von Sub- bzw. Supertypen<br />
Abteilungsleiter<br />
Personalnummer<br />
is a<br />
Name<br />
Vorname<br />
Abbildung 3.12: Darstellung von Attributen<br />
3.4.5 Beziehungen und Beziehungstypen<br />
Beziehungen wer<strong>de</strong>n, wie bereits oben erwähnt, über das grafische Symbol e<strong>in</strong>er Raute<br />
dargestellt, wobei auch Beziehungen Attribute zugeordnet wer<strong>de</strong>n können. Z.B. kann<br />
man <strong><strong>de</strong>r</strong> Beziehung »Mitarbeiter heiratet Ehepartner« das zusätzliche Attribut<br />
»Datum« mitgeben (siehe Abb. 3.13). E<strong>in</strong>e Raute wird für die Darstellung <strong><strong>de</strong>r</strong> Beziehung<br />
über L<strong>in</strong>ien mit <strong>de</strong>n <strong>in</strong> Beziehung stehen<strong>de</strong>n Entitytypen verbun<strong>de</strong>n. Die Beziehung<br />
wird bei Chen durch e<strong>in</strong> Substantiv anstelle e<strong>in</strong>es Verbs bezeichnet, z.B. »Heirat«<br />
anstelle <strong>de</strong>s Verbs »heiratet« , da e<strong>in</strong> Substantiv wie »Heirat« e<strong>in</strong> Vorgang ist, <strong><strong>de</strong>r</strong> eigene<br />
Attribute wie e<strong>in</strong> Datum, e<strong>in</strong>en Ort usw. besitzen kann. Die Kard<strong>in</strong>alitäten e<strong>in</strong>er Beziehung<br />
wer<strong>de</strong>n durch die Zeichen 1, N und M gekennzeichnet.<br />
Strasse<br />
Plz<br />
Ort<br />
Alter<br />
Name<br />
Vorname<br />
Abteilung Mitarbeiter Ehepartner
Abteilungsleiter<br />
Personalnummer<br />
1<br />
Vorgesetzter<br />
Abteilungsbezeichnung<br />
Name<br />
Abteilungsnummer<br />
1<br />
»Entity-Relationship-Mo<strong>de</strong>ll« nach Chen<br />
Vorname<br />
Strasse<br />
Plz<br />
Ort<br />
Abbildung 3.13: Darstellung von Beziehungen und Beziehungstypen<br />
E<strong>in</strong>en Son<strong><strong>de</strong>r</strong>fall bei Beziehungen stellen N:M-Beziehungen dar, da diese nicht ohne<br />
weiteres später <strong>in</strong> e<strong>in</strong> logisches Relationenmo<strong>de</strong>ll transformiert wer<strong>de</strong>n können. E<strong>in</strong><br />
N:M-Beziehungstyp stellt <strong>in</strong> <strong><strong>de</strong>r</strong> Regel e<strong>in</strong>en weiteren Entitytypen dar. Meistens wird<br />
mit so e<strong>in</strong>er Beziehung e<strong>in</strong> Konzept (z.B. e<strong>in</strong> Projekt, e<strong>in</strong> Konto) o<strong><strong>de</strong>r</strong> e<strong>in</strong>e Transaktion<br />
(z.B. e<strong>in</strong> Kaufvertrag, e<strong>in</strong>e Bestellung) dargestellt.<br />
Dementsprechend müssen N:M-Beziehungen <strong>in</strong> zwei 1:N-Beziehungen um<strong>de</strong>f<strong>in</strong>iert<br />
wer<strong>de</strong>n. Dies geschieht grafisch, <strong>in</strong><strong>de</strong>m man e<strong>in</strong>fach um die Beziehungsraute e<strong>in</strong><br />
Rechteck zeichnet. Dadurch wird erkennbar, dass es sich nun um e<strong>in</strong>en Entitytypen<br />
han<strong>de</strong>lt, <strong><strong>de</strong>r</strong> aus e<strong>in</strong>er N:M-Beziehung hervorgegangen ist.<br />
Betrachten wir als Beispiel hierzu die Beziehung zwischen Kun<strong>de</strong> und Artikel, bei <strong><strong>de</strong>r</strong><br />
es sich um e<strong>in</strong>e N:M-Beziehung han<strong>de</strong>lt. Im ersten Schritt wird diese Beziehung grafisch<br />
als N:M-Beziehung dargestellt. In e<strong>in</strong>em zweiten Schritt erfolgt die Um<strong>de</strong>f<strong>in</strong>ition<br />
<strong><strong>de</strong>r</strong> Beziehung <strong>in</strong> e<strong>in</strong>en Entitytyp.<br />
Name<br />
Vorname<br />
Mitarbeiter Heirat<br />
1 1 Ehepartner<br />
N<br />
Zugehörigkeit<br />
1<br />
Abteilung<br />
Datum<br />
Alter<br />
51
3.4.6 Fallbeispiel<br />
52<br />
Erster<br />
Grobentwurf<br />
Kun<strong>de</strong><br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
N<br />
Bestellung<br />
M<br />
Artikel<br />
Verfe<strong>in</strong>erter<br />
Entwurf<br />
Kun<strong>de</strong><br />
Bestellung<br />
Artikel<br />
Kun<strong>de</strong>nnummer<br />
Abbildung 3.14: Um<strong>de</strong>f<strong>in</strong>ition von N:M-Beziehungen<br />
Wir haben alle grafischen Elemente <strong>de</strong>s ERM nach Chen kennengelernt und wollen uns<br />
nun ansehen, wie man von <strong><strong>de</strong>r</strong> Analyse <strong>de</strong>s Textbeispiels zu e<strong>in</strong>em grafischen ERM<br />
kom<strong>mt</strong>. In <strong><strong>de</strong>r</strong> Regel geht man <strong>in</strong> sechs Schritten vor:<br />
1) I<strong>de</strong>ntifizieren <strong><strong>de</strong>r</strong> Entitytypen und Beziehungen;<br />
2) erster Grobentwurf mit Entitytypen und Beziehungen;<br />
3) Super-, Subtypen mo<strong>de</strong>llieren;<br />
4) Entwurf durch Um<strong>de</strong>f<strong>in</strong>ition von N:M-Beziehung verfe<strong>in</strong>ern und auf eventuell zusätzliche<br />
Beziehungen überprüfen (siehe Beziehung Bestellung zwischen Kun<strong>de</strong><br />
und Artikel, Abb. 3.14);<br />
5) Attribute h<strong>in</strong>zufügen;<br />
6) Schlüsselattribute festlegen bzw. ggf. neue Schlüsselattribute h<strong>in</strong>zufügen.<br />
Im ersten und zweiten Schritt wer<strong>de</strong>n Entitytypen und Beziehungen nur grob skizziert,<br />
um vor allem die Beziehungen zwischen Entitytypen zu erkennen und mit <strong>de</strong>m Kun<strong>de</strong>n<br />
durchzusprechen. Nach<strong>de</strong>m <strong><strong>de</strong>r</strong> erste Entwurf als korrekt bewertet wur<strong>de</strong>, wird<br />
das Mo<strong>de</strong>ll zunächst auf mögliche Super- bzw. Subtypen analysiert. Danach wer<strong>de</strong>n<br />
alle N:M-Beziehungen <strong>in</strong> jeweils zwei 1:N-Beziehungen um<strong>de</strong>f<strong>in</strong>iert und für die Beziehung<br />
e<strong>in</strong> Entitytyp gebil<strong>de</strong>t. Im fünften Schritt überlegt man, welche Attribute <strong>de</strong>n<br />
1<br />
N<br />
N<br />
1<br />
Ort<br />
Datum<br />
Artikelnummer<br />
Name<br />
Plz<br />
Vorname<br />
Strasse<br />
Bezeichnung
»Entity-Relationship-Mo<strong>de</strong>ll« nach Chen<br />
jeweiligen Entitytypen beschreiben und im sechsten Schritt, welche dieser Attribute als<br />
Schlüssel <strong>in</strong> Frage kommen o<strong><strong>de</strong>r</strong> ob eventuell e<strong>in</strong> künstlicher Schlüssel verwen<strong>de</strong>t wer<strong>de</strong>n<br />
soll.<br />
Die folgen<strong>de</strong> Grafik zeigt noch e<strong>in</strong>mal die e<strong>in</strong>zelnen Schritte auf. Zur besseren Übersicht<br />
wer<strong>de</strong>n im Folgen<strong>de</strong>n nicht alle Entitytypen und Beziehungen unseres Beispiels<br />
dargestellt.<br />
Schritt 1 und 2<br />
Kun<strong>de</strong><br />
N<br />
Bestellung<br />
M<br />
Werbeartikel Sitzplatz<br />
Veranstaltung<br />
1<br />
Besitz<br />
N<br />
N<br />
Schritt 4<br />
Kun<strong>de</strong><br />
1<br />
N<br />
Bestellung<br />
N<br />
1<br />
Artikel<br />
is a<br />
Bestellung<br />
N<br />
Zuordnung<br />
1<br />
M<br />
Vorstellung<br />
Schritt 3<br />
Kun<strong>de</strong><br />
Bestellung<br />
Abbildung 3.15: Sechs Schritte bis zum ERM nach Chen<br />
N<br />
M<br />
Artikel<br />
is a<br />
Werbeartikel Sitzplatz<br />
Schritt 5 und 6<br />
Kun<strong>de</strong><br />
1<br />
N<br />
Bestellung<br />
N<br />
1<br />
Artikel<br />
is a<br />
N<br />
Kun<strong>de</strong>nnummer<br />
Name<br />
Ort<br />
Datum<br />
Plz<br />
Artikelnummer<br />
1<br />
Vorname<br />
Strasse<br />
Bezeichnung<br />
53
54<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
Damit sieht das komplette ERM nach Chen für unser Fallbeispiel wie folgt aus:<br />
Personalnummer<br />
Vorgesetzt<br />
Abteilungsleiter<br />
1<br />
Abteilungsbezeichnung<br />
Name<br />
Abteilungsnummer<br />
Vorname<br />
Strasse<br />
Veranstaltung<br />
Plz<br />
Ort<br />
Kun<strong>de</strong><br />
Artikel<br />
is a<br />
Name<br />
Vorname<br />
Mitarbeiter Heirat<br />
1 1<br />
Ehepartner<br />
1<br />
Beschreibung<br />
Preis<br />
Lagerbestand<br />
Bezeichnung<br />
N<br />
Zugehörigkeit<br />
1<br />
Abteilung<br />
Autor<br />
1<br />
Betreuung<br />
Datum<br />
Bestellung<br />
Werbeartikel Sitzplatz<br />
Besitz<br />
1 N<br />
Veranstaltungsnummer<br />
N<br />
N<br />
M<br />
Alter<br />
Vorstellungsnummer<br />
Kun<strong>de</strong>nnummer<br />
Name<br />
Zuordnung<br />
Vorstellung<br />
Vorname<br />
Strasse<br />
Abbildung 3.16: ERM nach Chen für unser Fallbeispiel<br />
Ort<br />
Bestellnummer<br />
Menge<br />
Datum<br />
Artikelnummer<br />
Datum<br />
Plz<br />
Positionsnummer<br />
Bezeichnung<br />
N<br />
1<br />
Uhrzeit<br />
Zustand<br />
N<br />
Bereich<br />
Preis<br />
Reihe<br />
Sitznummer<br />
Spielstätte<br />
1<br />
Aufführung<br />
Bezeichnung<br />
Ort<br />
Plz<br />
Strasse
»Entity-Relationship-Mo<strong>de</strong>ll« nach Barker<br />
3.5 »Entity-Relationship-Mo<strong>de</strong>ll« nach Barker<br />
3.5.1 Grundlagen<br />
Das ERM nach Barker stam<strong>mt</strong> ursprünglich von <strong><strong>de</strong>r</strong> britischen Unternehmensberatung<br />
CACI und wur<strong>de</strong> von Richard Barker (vgl. hierzu [Barker90]) weiterentwickelt. Gegenüber<br />
<strong>de</strong>m ERM von Chen ist es übersichtlicher und teilweise aussagekräftiger. Dass es<br />
heute <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>Praxis</strong> so weit verbreitet ist, liegt u.a. an <strong><strong>de</strong>r</strong> DV-technischen Unterstützung<br />
durch die Firma Oracle mit <strong><strong>de</strong>r</strong>en CASE-Tool.<br />
3.5.2 Geschäftsobjekte<br />
Geschäftsobjekte bzw. Entitytypen wer<strong>de</strong>n im ERM nach Barker durch abgerun<strong>de</strong>te<br />
Rechtecke dargestellt.<br />
Abteilung Mitarbeiter Ehepartner<br />
3.5.3 Sub- bzw. Supertypen<br />
Subtypen wer<strong>de</strong>n <strong>in</strong>nerhalb e<strong>in</strong>es Supertyps als abgerun<strong>de</strong>tes Recheck dargestellt.<br />
3.5.4 Attribute und Schlüssel<br />
Abbildung 3.17: Darstellung von Entitytypen<br />
Artikel<br />
Werbeartikel<br />
Sitzplatz<br />
Abbildung 3.18: Darstellung von Sub- bzw. Supertypen<br />
Attribute wer<strong>de</strong>n <strong>in</strong>nerhalb <strong>de</strong>s Rechtecks für <strong>de</strong>n Entitytypen dargestellt. Ist <strong><strong>de</strong>r</strong> Wert<br />
e<strong>in</strong>es Attributes für e<strong>in</strong> Entity optional, so wird dies durch e<strong>in</strong>en offenen Kreis vor <strong>de</strong>m<br />
Attributnamen angezeigt. Ist das Attribut dagegen obligatorisch (engl. mandatory), so<br />
ist <strong><strong>de</strong>r</strong> Kreis geschlossen. Um Attribute als Teil <strong>de</strong>s Primärschlüssels zu kennzeichnen,<br />
55
56<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
ersche<strong>in</strong>t vor <strong>de</strong>m Attributnamen das Nummernzeichen (#). Da <strong><strong>de</strong>r</strong> Primärschlüssel<br />
niemals optional se<strong>in</strong> kann, son<strong><strong>de</strong>r</strong>n immer angegeben wer<strong>de</strong>n muss, wird hier auf<br />
e<strong>in</strong>en geschlossenen Kreis verzichtet.<br />
Anstelle e<strong>in</strong>es offenes Kreises wird häufig auch <strong><strong>de</strong>r</strong> Buchstabe 'o', anstatt e<strong>in</strong>es<br />
geschlossenen Kreises das Zeichen '*' verwen<strong>de</strong>t. Im Folgen<strong>de</strong>n schließen wir uns dieser<br />
Konvention an.<br />
Abteilung<br />
� ���������������������<br />
� ����������������<br />
� ����������������<br />
Abbildung 3.19: Darstellung von Attributen<br />
3.5.5 Beziehungen und Beziehungstypen<br />
Beziehungen wer<strong>de</strong>n ausschließlich durch Verb<strong>in</strong>dungsl<strong>in</strong>ien dargestellt. Dabei wird<br />
die L<strong>in</strong>ie als zweigeteilt betrachtet. Je nach<strong>de</strong>m, <strong>in</strong> welchem Entitytyp die L<strong>in</strong>ie en<strong>de</strong>t,<br />
wird sie gestrichelt o<strong><strong>de</strong>r</strong> als geschlossene L<strong>in</strong>ie gezeichnet. E<strong>in</strong>e gestrichelte L<strong>in</strong>ie zwischen<br />
zwei Entitytypen zeigt an, dass die Kard<strong>in</strong>alität dort optional ist, wo die gestrichelte<br />
L<strong>in</strong>ie en<strong>de</strong>t. So genannte »Krähenfüsse« (»Crows foot« ) an e<strong>in</strong>em Entitytyp<br />
kennzeichnen die Kard<strong>in</strong>alität für »viele« . E<strong>in</strong>e e<strong>in</strong>fache L<strong>in</strong>ie gibt die Kard<strong>in</strong>alität für<br />
»genau e<strong>in</strong>s« an. Im Gegensatz zum Mo<strong>de</strong>ll von Chen hat Barker sich ausführlich mit<br />
<strong><strong>de</strong>r</strong> Vergabe von Namenskonventionen ause<strong>in</strong>an<strong><strong>de</strong>r</strong>gesetzt. Die Bezeichnung e<strong>in</strong>er<br />
Beziehung wird aus <strong><strong>de</strong>r</strong> Sichtweise je<strong>de</strong>s Entitytyps zweimal dargestellt, entsprechend<br />
wer<strong>de</strong>n hier Verben statt Substantive verwen<strong>de</strong>t.<br />
besteht<br />
aus<br />
Mitarbeiter<br />
� ��������������<br />
� ����<br />
� �������<br />
� �������<br />
� ���<br />
� ���<br />
Ehepartner<br />
� ����<br />
� �������<br />
� �����<br />
Abteilung Mitarbeiter Ehepartner<br />
gehört<br />
zu<br />
verheiratet<br />
mit<br />
Abbildung 3.20: Darstellung von Beziehungen und Beziehungstypen<br />
Für die Vergabe <strong><strong>de</strong>r</strong> Beziehungen hat Barker sich e<strong>in</strong>e bestim<strong>mt</strong>e Systematik überlegt,<br />
die zur sprachlichen Überprüfung <strong><strong>de</strong>r</strong> Beziehung herangezogen wer<strong>de</strong>n kann. Die allgeme<strong>in</strong>e<br />
Satzstruktur für e<strong>in</strong>e Beziehung wird ausgedrückt durch:<br />
Je<strong><strong>de</strong>r</strong> A (muss | kann) (genau e<strong>in</strong>em B | e<strong>in</strong>en o<strong><strong>de</strong>r</strong> mehreren B) R,<br />
wobei A und B die Bezeichnung <strong><strong>de</strong>r</strong> Entitytypen darstellen und R die Beschreibung <strong><strong>de</strong>r</strong><br />
Beziehung. Das Wort »muss« wird bei e<strong>in</strong>er durchgezogenen L<strong>in</strong>ie, also bei e<strong>in</strong>er obligatorischen<br />
Beziehung, das Wort »kann« bei e<strong>in</strong>er gestrichelten L<strong>in</strong>ie, also e<strong>in</strong>er optionalen<br />
Beziehung verwen<strong>de</strong>t. Die Phrase »genau e<strong>in</strong>em B« wird bei e<strong>in</strong>er e<strong>in</strong>zigen L<strong>in</strong>ie,<br />
die Phrase »e<strong>in</strong>en o<strong><strong>de</strong>r</strong> mehreren B« bei <strong>de</strong>n Krähenfüssen verwen<strong>de</strong>t.<br />
von
»Entity-Relationship-Mo<strong>de</strong>ll« nach Barker<br />
Betrachten wir hierzu das Beispiel <strong><strong>de</strong>r</strong> Beziehung zwischen Abteilung zu Mitarbeiter,<br />
so ergibt sich:<br />
Je<strong>de</strong> Abteilung muss aus e<strong>in</strong>em o<strong><strong>de</strong>r</strong> mehreren Mitarbeitern bestehen.<br />
Je<strong><strong>de</strong>r</strong> Mitarbeiter kann zu genau e<strong>in</strong>er Abteilung gehören.<br />
Dabei muss <strong><strong>de</strong>r</strong> Satz natürlich noch e<strong>in</strong>mal grammatikalisch angepasst wer<strong>de</strong>n. Lei<strong><strong>de</strong>r</strong><br />
ist aufgrund <strong><strong>de</strong>r</strong> Grammatik <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>de</strong>utschen Sprache die Verwendung dieser Satzstruktur<br />
nicht systematisch anwendbar, <strong>de</strong>nnoch kann sie zur Validierung von Beziehungen<br />
dienen.<br />
Daneben kennt das ERM nach Barker das Konzept <strong><strong>de</strong>r</strong> Aggregation. Aggregation<br />
beschreibt Beziehungen <strong><strong>de</strong>r</strong> Form »besteht aus« . Um solche Zusammenhänge grafisch<br />
darzustellen, ersche<strong>in</strong>t e<strong>in</strong> kle<strong>in</strong>er senkrechter Strich vor <strong>de</strong>m Entitytypen, <strong><strong>de</strong>r</strong> <strong>de</strong>n Primärschlüssel<br />
übernehmen soll. In unserem Beispiel haben wir e<strong>in</strong>e Aggregation zwischen<br />
Veranstaltung und Vorstellung vorliegen. E<strong>in</strong>e Vorstellung existiert nicht ohne<br />
e<strong>in</strong>e Veranstaltung, entsprechend haben wir hier die Beziehung »besteht aus« vorliegen.<br />
E<strong>in</strong> Entitytyp stellt e<strong>in</strong>e Aggregation <strong>de</strong>s an<strong><strong>de</strong>r</strong>en Entitytypen dar, wenn dieser<br />
ohne <strong>de</strong>n an<strong><strong>de</strong>r</strong>en Entitytypen nicht existieren kann (Vorstellung kann nicht ohne e<strong>in</strong>e<br />
Veranstaltung existieren).<br />
Bezogen auf unser Beispiel von Abb. 3.19 sieht das Ergebnis damit wie folgt aus:<br />
3.5.6 Fallbeispiel<br />
besteht<br />
aus<br />
Abteilung Mitarbeiter Ehepartner<br />
gehört<br />
zu<br />
verheiratet<br />
mit<br />
Abbildung 3.21: Berücksichtigung <strong><strong>de</strong>r</strong> Primärschlüssel bei 1:1- und 1:N-Beziehungen<br />
Wir haben alle grafischen Elemente <strong>de</strong>s ERM nach Barker kennen gelernt und wollen<br />
uns nun ansehen, wie man von <strong><strong>de</strong>r</strong> Analyse <strong>de</strong>s Textbeispiels zu e<strong>in</strong>em grafischen ERM<br />
kom<strong>mt</strong>. In <strong><strong>de</strong>r</strong> Regel geht man <strong>in</strong> sechs Schritten vor:<br />
1) I<strong>de</strong>ntifizieren <strong><strong>de</strong>r</strong> Entitytypen und Beziehungen;<br />
2) ersten Grobentwurf mit Entitytypen und Beziehungen erstellen;<br />
3) Super-, Subtypen mo<strong>de</strong>llieren;<br />
4) Entwurf durch Um<strong>de</strong>f<strong>in</strong>ition von N:M-Beziehung verfe<strong>in</strong>ern und auf eventuell zusätzliche<br />
Beziehungen überprüfen (siehe Beziehung Kun<strong>de</strong> – Artikel);<br />
5) Aggregationen mo<strong>de</strong>llieren;<br />
6) Attribute h<strong>in</strong>zufügen und festlegen, ob Attribut optional o<strong><strong>de</strong>r</strong> obligatorisch;<br />
7) Schlüsselattribute festlegen o<strong><strong>de</strong>r</strong> h<strong>in</strong>zufügen.<br />
Gegenüber <strong><strong>de</strong>r</strong> Vorgehensweise <strong>de</strong>s ERM nach Chen muss bei <strong>de</strong>m ERM nach Barker<br />
zusätzlich festgelegt wer<strong>de</strong>n, wo <strong><strong>de</strong>r</strong> Primärschlüssel e<strong>in</strong>es Entitytyps <strong>de</strong>m Primärschlüssel<br />
<strong>de</strong>s an<strong><strong>de</strong>r</strong>en Entitytyps zugeordnet wird. Daneben ist festzulegen, <strong>in</strong>wiefern<br />
<strong><strong>de</strong>r</strong> Wert e<strong>in</strong>es Attributes für e<strong>in</strong> Entitytyp zw<strong>in</strong>gend vorhan<strong>de</strong>n se<strong>in</strong> muss o<strong><strong>de</strong>r</strong> nicht<br />
(Schritt 6).<br />
von<br />
57
58<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
Die folgen<strong>de</strong> Grafik zeigt noch e<strong>in</strong>mal die e<strong>in</strong>zelnen Schritte auf. Zur besseren Übersicht<br />
wer<strong>de</strong>n im Folgen<strong>de</strong>n nicht alle Entitytypen und Beziehungen unseres Beispiels<br />
dargestellt.<br />
Schritt 1 und 2 Schritt 3<br />
Kun<strong>de</strong><br />
Werbeartikel Sitzplatz<br />
Veranstaltung<br />
Vorstellung<br />
Kun<strong>de</strong><br />
Artikel<br />
Werbeartikel<br />
Sitzplatz<br />
Schritt 4 und 5 Schritt 5 und 6<br />
Kun<strong>de</strong><br />
Bestellung<br />
Artikel<br />
Werbeartikel<br />
Sitzplatz<br />
Veranstaltung<br />
Vorstellung<br />
Kun<strong>de</strong><br />
� ������������<br />
� ����<br />
� �������<br />
� �������<br />
� ���<br />
� � ��<br />
Bestellung<br />
� �������������<br />
� ���������������<br />
� �����<br />
� �����<br />
Artikel<br />
� �������������<br />
� �����������<br />
Werbeartikel<br />
� �����������<br />
� �����<br />
� ������������<br />
Sitzplatz<br />
� �������<br />
� �����<br />
� ����<br />
� �����<br />
� �������<br />
Abbildung 3.22: Sieben Schritte bis zum ERM nach Barker<br />
Veranstaltung<br />
Vorstellung<br />
Veranstaltung<br />
� ��������������������<br />
� �����������<br />
� �����<br />
Vorstellung<br />
� ������������������<br />
� �����<br />
� �������
»Unified Mo<strong>de</strong>l<strong>in</strong>g Language«<br />
Damit sieht das komplette ERM nach Barker für unser Fallbeispiel wie folgt aus:<br />
Abteilung<br />
� ���������������������<br />
� ����������������<br />
� ����������������<br />
Kun<strong>de</strong><br />
� ������������<br />
� ����<br />
� �������<br />
� �������<br />
� ���<br />
� ���<br />
gehört<br />
zu<br />
Bestellung<br />
� �������������<br />
� ���������������<br />
� �����<br />
� �����<br />
ist auf<br />
gibt<br />
auf<br />
enthält<br />
Artikel<br />
� �������������<br />
� �����������<br />
Werbeartikel<br />
� ������������<br />
� �����<br />
� ������������<br />
Sitzplatz<br />
� �������<br />
� �����<br />
� ����<br />
� �����<br />
� �������<br />
ist für<br />
3.6 »Unified Mo<strong>de</strong>l<strong>in</strong>g Language«<br />
3.6.1 Grundlagen<br />
besteht<br />
aus<br />
ist Untegebener von<br />
wird<br />
bearbeitet<br />
von<br />
Mitarbeiter<br />
� ��������������<br />
gehört � ����<br />
zu � �������<br />
� �������<br />
� ���<br />
� ���<br />
ist<br />
Vorgesetzter<br />
von<br />
Veranstaltung<br />
� ��������������������<br />
� �����������<br />
� �����<br />
besteht<br />
aus<br />
basiert<br />
auf<br />
Vorstellung<br />
� ������������������<br />
� �����<br />
� �������<br />
verheiratet<br />
mit<br />
bearbeitet<br />
Abbildung 3.23: ERM nach Barker für unser Fallbeispiel<br />
Ehepartner<br />
� ����<br />
� �������<br />
� �����<br />
Die »Unfied Mo<strong>de</strong>l<strong>in</strong>g Language« (UML) ist primär ke<strong>in</strong>e grafische Notation zur<br />
Datenmo<strong>de</strong>llierung. Eigentlich dient sie zur »Objektmo<strong>de</strong>llierung« und damit hauptsächlich<br />
zur Mo<strong>de</strong>llierung von Anwendungen bzw. Funktionsmo<strong>de</strong>llen. E<strong>in</strong> Objekt<br />
von<br />
präsentiert Spielstätte<br />
� ����<br />
f<strong>in</strong><strong>de</strong>t statt<br />
� �������<br />
� ���<br />
� ���<br />
59
60<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
be<strong>in</strong>haltet neben se<strong>in</strong>en Attributen, und damit <strong>de</strong>n Daten, die es beschreibt, auch e<strong>in</strong><br />
Verhalten <strong>in</strong> Form von Metho<strong>de</strong>n. So könnte e<strong>in</strong> Objekt <strong>de</strong>s Objekttyps »Sitzplatz«<br />
neben se<strong>in</strong>en Attributen auch Metho<strong>de</strong>n zum Bearbeiten e<strong>in</strong>es Sitzplatzes be<strong>in</strong>halten,<br />
z.B. ReservierePlatz, StornierePlatz usw.<br />
Die UML besteht aus unterschiedlichen Diagram<strong>mt</strong>ypen. So be<strong>in</strong>haltet e<strong>in</strong>e grafische<br />
Notation <strong><strong>de</strong>r</strong> UML so genannte »Anwendungsfälle« (»Use Cases« ). Diese dienen dazu,<br />
e<strong>in</strong>en funktionalen Überblick über e<strong>in</strong> Geschäftsumfeld zu erhalten und s<strong>in</strong>d <strong>in</strong>nerhalb<br />
<strong>de</strong>s Phasenkonzeptes <strong><strong>de</strong>r</strong> 1. und teilweise <strong><strong>de</strong>r</strong> 2. Phase zuzuordnen.<br />
Der wichtigste Diagram<strong>mt</strong>yp <strong><strong>de</strong>r</strong> UML ist jedoch das Klassenmo<strong>de</strong>ll (»Class Mo<strong>de</strong>ll« ),<br />
um die logische Struktur e<strong>in</strong>es Anwendungssystems zu mo<strong>de</strong>llieren. Zur Erstellung<br />
e<strong>in</strong>es Datenmo<strong>de</strong>lls auf Basis <strong><strong>de</strong>r</strong> UML beschäftigen wir uns hier <strong>de</strong>shalb nur mit<br />
e<strong>in</strong>em Teil <strong><strong>de</strong>r</strong> grafischen Notation e<strong>in</strong>es Klassenmo<strong>de</strong>lls.<br />
Die UML hat sich heutzutage als Standard zur objektorientierten Mo<strong>de</strong>llierung von<br />
Anwendungssystemen durchgesetzt. Bevor die UML als Standard von <strong><strong>de</strong>r</strong> »Object<br />
Management Group« (OMG) 1997 verabschie<strong>de</strong>t wur<strong>de</strong>, gab es im Bereich <strong><strong>de</strong>r</strong> objektorientierten<br />
Mo<strong>de</strong>llierung drei sich ähneln<strong>de</strong> Notationen zur Mo<strong>de</strong>llierung von James<br />
Rumbaugh, Grady Booch und Ivar Jacobson. Um ihre Notationen zu vere<strong>in</strong>heitlichen<br />
und e<strong>in</strong>en Standard zu schaffen, entwickelten die drei »Amigos« (wie sie von <strong><strong>de</strong>r</strong><br />
objektorientierten »Geme<strong>in</strong><strong>de</strong>« bezeichnet wer<strong>de</strong>n) die UML. Heute arbeiten Rumbaugh,<br />
Booch und Jacobsen bei <strong><strong>de</strong>r</strong> Firma Rational Rose, die Software-Tools zur Mo<strong>de</strong>llierung<br />
von Anwendungen mit <strong><strong>de</strong>r</strong> UML erstellt. Inzwischen gibt es e<strong>in</strong>en weiteren<br />
Vorschlag <strong><strong>de</strong>r</strong> drei »Amigos« zur Erweiterung <strong><strong>de</strong>r</strong> UML um grafische Notationen an<br />
die OMG. Diese Erweiterung betrifft vor allem die Umsetzung e<strong>in</strong>es Klassenmo<strong>de</strong>lls <strong>in</strong><br />
e<strong>in</strong> logisches Mo<strong>de</strong>ll als Voraussetzung zur Erstellung e<strong>in</strong>er relationalen Datenbank.<br />
Wir wollen uns hier nicht mit dieser Erweiterung beschäftigen, son<strong><strong>de</strong>r</strong>n betrachten<br />
Klassenmo<strong>de</strong>lle so, wie sie zur Mo<strong>de</strong>llierung von Anwendungssystemen verwen<strong>de</strong>t<br />
wer<strong>de</strong>n. Dabei geht es nicht so sehr um die Vollständigkeit <strong><strong>de</strong>r</strong> Notation, son<strong><strong>de</strong>r</strong>n vielmehr<br />
um e<strong>in</strong> Kennenlernen <strong><strong>de</strong>r</strong> UML, bezogen auf die Datenmo<strong>de</strong>llierung. Literaturh<strong>in</strong>weise<br />
zur UML s<strong>in</strong>d im Anhang aufgeführt.<br />
3.6.2 Geschäftsobjekte<br />
Die UML dient zur Objektmo<strong>de</strong>llierung. Entsprechend wer<strong>de</strong>n Geschäftsobjekte als<br />
Objekte bezeichnet und Objekttypen als Klassen. E<strong>in</strong>e Klasse ist also e<strong>in</strong>e »Schablone«<br />
für e<strong>in</strong> Objekt, genau wie e<strong>in</strong> Entitytyp. Im Gegensatz zum Entitytypen <strong>de</strong>f<strong>in</strong>iert e<strong>in</strong>e<br />
Klasse jedoch nicht nur die Attribute e<strong>in</strong>es Objektes, son<strong><strong>de</strong>r</strong>n auch das Verhalten <strong>de</strong>s<br />
Objektes <strong>in</strong> Form von Metho<strong>de</strong>n. Klassen wer<strong>de</strong>n <strong>de</strong>shalb <strong>in</strong> <strong><strong>de</strong>r</strong> UML durch e<strong>in</strong> Rechteck<br />
repräsentiert, das dreigeteilt ist. Im oberen Bereich steht <strong><strong>de</strong>r</strong> Name <strong><strong>de</strong>r</strong> Klasse, im<br />
mittleren Teil die Attribute und im unteren Bereich die Metho<strong>de</strong>n <strong><strong>de</strong>r</strong> Klasse. E<strong>in</strong>e<br />
Klasse hat private Attribute und Metho<strong>de</strong>n, auf die nur die Klasse selbst zugreifen darf<br />
und öffentliche Attribute, auf die auch an<strong><strong>de</strong>r</strong>e Klassen zugreifen können. Die Bezeichner<br />
von Klassen und Attributen dürfen ke<strong>in</strong>e Leerzeichen enthalten. So ist »Leiter <strong><strong>de</strong>r</strong><br />
Abteilung« ke<strong>in</strong> korrekter Bezeichner, statt <strong>de</strong>ssen müsste man diese Klasse »Leiter-<br />
DerAbteilung« o<strong><strong>de</strong>r</strong> besser »Abteilungsleiter« nennen.
»Unified Mo<strong>de</strong>l<strong>in</strong>g Language«<br />
Abteilung Mitarbeiter Ehepartner<br />
3.6.3 Sub- bzw. Supertypen<br />
Supertypen und Subtypen wer<strong>de</strong>n jeweils als Klasse dargestellt. Die Beziehung e<strong>in</strong>es<br />
Supertyps zu se<strong>in</strong>en Subtypen durch e<strong>in</strong>e »ist e<strong>in</strong>« -Beziehung wird <strong>in</strong> Form e<strong>in</strong>es Dreiecks<br />
dargestellt.<br />
Werbeartikel<br />
3.6.4 Attribute und Schlüssel<br />
Abbildung 3.24: Darstellung von Klassen<br />
Artikel<br />
Sitzplatz<br />
Abbildung 3.25: Darstellung von Sub- bzw. Supertypen<br />
Attribute wer<strong>de</strong>n <strong>in</strong>nerhalb <strong>de</strong>s Rechtecks e<strong>in</strong>er Klasse unterhalb <strong>de</strong>s Klassenbezeichners<br />
aufgeführt. Das relationale Datenmo<strong>de</strong>ll sieht es nicht vor, Attribute als privat<br />
o<strong><strong>de</strong>r</strong> öffentlich zu kennzeichnen. Da die UML jedoch zur objektorientierten Mo<strong>de</strong>llierung<br />
dient, können hier die Attribute <strong>in</strong> <strong><strong>de</strong>r</strong> UML als nach außen sichtbar (public), nur<br />
sichtbar für Subtypen (protected) o<strong><strong>de</strong>r</strong> versteckt (private) gekennzeichnet wer<strong>de</strong>n.<br />
»public« -Attribute o<strong><strong>de</strong>r</strong> Metho<strong>de</strong>n erhalten e<strong>in</strong> »+« -Zeichen vor ihrer Bezeichnung,<br />
»private« -Elemente e<strong>in</strong> »-« -Zeichen und »protected« -Elemente das »#« -Zeichen.<br />
Schlüssel existieren <strong>in</strong> <strong><strong>de</strong>r</strong> UML nicht, da <strong>in</strong> <strong><strong>de</strong>r</strong> UML e<strong>in</strong> Objekt bzw. e<strong>in</strong>e Instanz e<strong>in</strong><strong>de</strong>utig<br />
durch ihre Beziehungen zu an<strong><strong>de</strong>r</strong>en Objekten i<strong>de</strong>ntifiziert wer<strong>de</strong>n kann. Dennoch<br />
ist es möglich, durch so genannte Sterotype anzugeben, welche Attribute als<br />
Schlüssel <strong>in</strong>nerhalb e<strong>in</strong>er relationalen Datenbank gelten sollen.<br />
Sterotype dienen dazu, die Sprachelemente <strong><strong>de</strong>r</strong> UML zu erweitern, <strong>in</strong><strong>de</strong>m man e<strong>in</strong>fach<br />
bestim<strong>mt</strong>en Begriffen <strong>in</strong>nerhalb e<strong>in</strong>es Diagramms e<strong>in</strong>e Semantik zuweist. Diese<br />
Begriffe wer<strong>de</strong>n durch Guillemets (französische Anführungszeichen), »« ,<br />
begrenzt. Für e<strong>in</strong>en Primärschlüssel <strong>de</strong>f<strong>in</strong>ieren wir <strong>de</strong>shalb <strong>de</strong>n Sterotyp »« ,<br />
<strong><strong>de</strong>r</strong> dazu dienen soll, Attribute als Primärschlüssel (»Primary Key« ) zu kennzeichnen.<br />
61
62<br />
Abteilung<br />
-Abteilungsbezeichnung<br />
-Abteilungsnummer<br />
-Abteilungsleiter<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
Mitarbeiter<br />
-Personalnummer : Ganzzahl<br />
-Name : Zeichenkette<br />
-Vorname : Zeichenkette<br />
-Strasse : Zeichenkette<br />
-Plz : Ganzzahl<br />
-Ort : Zeichenkette<br />
Abbildung 3.26: Darstellung von Sub- bzw. Supertypen<br />
Auf Metho<strong>de</strong>n wur<strong>de</strong> <strong>in</strong> dieser Darstellung verzichtet. Wir wer<strong>de</strong>n jedoch ab Kapitel 6<br />
sehen, dass <strong>in</strong> Datenbanken auch Metho<strong>de</strong>n über so genannte »User Def<strong>in</strong>ed Types« ,<br />
»Trigger« und »Stored Procedures« gespeichert und ausgeführt wer<strong>de</strong>n können.<br />
3.6.5 Beziehungen und Beziehungstypen<br />
Ehepartner<br />
-Name : Zeichenkette<br />
-Vorname : Zeichenkette<br />
-Alter : Ganzzahl<br />
Beziehungen, <strong>in</strong> <strong><strong>de</strong>r</strong> UML Assoziationen genannt, wer<strong>de</strong>n durch L<strong>in</strong>ien und Symbole<br />
an <strong>de</strong>n En<strong>de</strong>n <strong><strong>de</strong>r</strong> L<strong>in</strong>ien beschrieben.<br />
1:1- und 1:N-Beziehungen wer<strong>de</strong>n durch e<strong>in</strong>e e<strong>in</strong>fache L<strong>in</strong>ie gekennzeichnet, N:M-<br />
Beziehungen durch so genannte Assoziationsklassen, <strong>in</strong><strong>de</strong>m <strong><strong>de</strong>r</strong> Beziehung automatisch<br />
e<strong>in</strong>e weitere Klasse zugeordnet wird. E<strong>in</strong> geson<strong><strong>de</strong>r</strong>ter Schritt zur Um<strong>de</strong>f<strong>in</strong>ition<br />
von N:M-Beziehungen ist <strong>de</strong>shalb nicht notwendig.<br />
Daneben wird das Symbol e<strong>in</strong>er Raute am En<strong>de</strong> e<strong>in</strong>er L<strong>in</strong>ie verwen<strong>de</strong>t, um Assoziationen<br />
<strong><strong>de</strong>r</strong> Form »ist Teil von« und »besteht aus« (Aggregation) darzustellen. In unserem<br />
Beispiel haben wir diesen Fall zwischen Veranstaltung und Vorstellung vorliegen. E<strong>in</strong>e<br />
Vorstellung existiert nicht ohne e<strong>in</strong>e Veranstaltung, entsprechend haben wir hier die<br />
Beziehung »besteht aus« .<br />
E<strong>in</strong>e Beziehung <strong><strong>de</strong>r</strong> Art »ist Teil von« existiert zwischen Mitarbeiter und Ehepartner.<br />
E<strong>in</strong> Ehepartner ist Teil e<strong>in</strong>es Mitarbeiters, gehört also zum Objekttyp »Mitarbeiter« .<br />
Ähnlich wäre es, wenn wir z.B. für Kun<strong>de</strong>n mehrere Adressen zulassen wür<strong>de</strong>n. In diesem<br />
Fall müssten wir zusätzlich e<strong>in</strong>e Klasse »Adresse« <strong>de</strong>f<strong>in</strong>ieren. Die Klasse<br />
»Adresse« wäre dann »Teil von« <strong><strong>de</strong>r</strong> Klasse »Kun<strong>de</strong>« . Diese Art <strong><strong>de</strong>r</strong> Beziehung wird<br />
durch e<strong>in</strong>e Raute dargestellt.<br />
Ist die Raute gefüllt, so han<strong>de</strong>lt es sich um e<strong>in</strong>e zusammengesetzte Aggregation. In diesem<br />
Fall können die Objekte, aus <strong>de</strong>nen sich das aggregierte Objekt zusammensetzt,<br />
ke<strong>in</strong>e weiteren Aggregationen mit an<strong><strong>de</strong>r</strong>en Objekten bil<strong>de</strong>n. Hierzu e<strong>in</strong> Beispiel: E<strong>in</strong><br />
Gebäu<strong>de</strong> besteht aus mehreren Räumen, e<strong>in</strong> Raum kann ohne das Gebäu<strong>de</strong> nicht existieren.<br />
E<strong>in</strong> ganz bestim<strong>mt</strong>er Raum kann nur e<strong>in</strong>em Gebäu<strong>de</strong> zugeordnet se<strong>in</strong> und kann<br />
daher nicht für e<strong>in</strong> weiteres Gebäu<strong>de</strong> verwen<strong>de</strong>t wer<strong>de</strong>n.<br />
Kard<strong>in</strong>alitäten wer<strong>de</strong>n mit Zeichen <strong><strong>de</strong>r</strong> Form »M<strong>in</strong>imum .. Maximum« dargestellt.<br />
M<strong>in</strong>imum und Maximum stehen dabei für die Anzahl <strong><strong>de</strong>r</strong> <strong>in</strong> Beziehung stehen<strong>de</strong>n<br />
Objekte. E<strong>in</strong> »*« steht für beliebig viele Objekte, e<strong>in</strong>e 0 für optional. E<strong>in</strong>e Kard<strong>in</strong>alität<br />
von »1..1« be<strong>de</strong>utet <strong>de</strong>mentsprechend »genau e<strong>in</strong>er« . Zur Ver<strong>de</strong>utlichung e<strong>in</strong> Beispiel:<br />
E<strong>in</strong>e Abteilung besteht aus e<strong>in</strong>em o<strong><strong>de</strong>r</strong> beliebig vielen Mitarbeitern (1..*). Die 1 stellt
»Unified Mo<strong>de</strong>l<strong>in</strong>g Language«<br />
dabei das M<strong>in</strong>imum dar und das Zeichen »*« das Maximum. Wür<strong>de</strong> man dagegen festlegen,<br />
dass e<strong>in</strong>e Abteilung aus maximal 20 Mitarbeitern bestehen darf, so wür<strong>de</strong> man<br />
1..20 schreiben.<br />
Abteilung<br />
-gehört zu<br />
3.6.6 Fallbeispiel<br />
-besteht aus<br />
1..1<br />
1..*<br />
Mitarbeiter<br />
-ist verheiratet mit<br />
Ehepartner<br />
Abbildung 3.27: Darstellung von 1:1- und 1:N-Beziehungstypen<br />
-kauft<br />
-wird erworben von<br />
Kun<strong>de</strong><br />
Artikel<br />
Abbildung 3.28: Darstellung von N:M-Beziehungstypen<br />
Wir haben die wichtigsten grafischen Elemente e<strong>in</strong>es Klassendiagramms <strong><strong>de</strong>r</strong> UML kennen<br />
gelernt und wollen uns nun ansehen, wie man von <strong><strong>de</strong>r</strong> Analyse <strong>de</strong>s Textbeispiels<br />
zu e<strong>in</strong>em Klassendiagramm kom<strong>mt</strong>. In <strong><strong>de</strong>r</strong> Regel geht man <strong>in</strong> sieben Schritten vor:<br />
1) I<strong>de</strong>ntifizieren <strong><strong>de</strong>r</strong> Klassen und Assoziationen;<br />
2) ersten Grobentwurf mit Klassen und Assoziationen erstellen;<br />
3) Super-, Subtypen mo<strong>de</strong>llieren;<br />
1<br />
-ist verheiratet mit<br />
1..*<br />
0..*<br />
1<br />
����������<br />
63
64<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
4) Aggregationen mo<strong>de</strong>llieren;<br />
5) Attribute h<strong>in</strong>zufügen und festlegen, ob Attribut optional o<strong><strong>de</strong>r</strong> obligatorisch;<br />
6) Schlüsselattribute festlegen o<strong><strong>de</strong>r</strong> h<strong>in</strong>zufügen;<br />
7) Festlegen <strong>de</strong>s Verhaltens <strong><strong>de</strong>r</strong> Klasse <strong>in</strong> Form von Metho<strong>de</strong>n.<br />
Gegenüber <strong><strong>de</strong>r</strong> Vorgehensweise <strong>de</strong>s ERM wird bei <strong><strong>de</strong>r</strong> UML bei N:M-Beziehungen<br />
ke<strong>in</strong>e Um<strong>de</strong>f<strong>in</strong>ition <strong><strong>de</strong>r</strong> Beziehung vorgenommen, da hier bereits bei <strong><strong>de</strong>r</strong> Mo<strong>de</strong>llierung<br />
von N:M-Beziehung e<strong>in</strong>e eigene Klasse h<strong>in</strong>zugefügt wird (siehe Abb. 3.28). Neben <strong>de</strong>m<br />
eigentlichen I<strong>de</strong>ntifizieren und Mo<strong>de</strong>llieren <strong><strong>de</strong>r</strong> Daten s<strong>in</strong>d jedoch gera<strong>de</strong> die Metho<strong>de</strong>n<br />
von Klassen wichtig, die <strong>in</strong> e<strong>in</strong>em sechsten Schritt mit <strong><strong>de</strong>r</strong> UML spezifiziert wer<strong>de</strong>n<br />
können.<br />
Damit sieht das Klassendiagramm mit <strong><strong>de</strong>r</strong> UML für unser Fallbeispiel wie folgt aus:<br />
Abteilung<br />
-Abteilungsbezeichnung<br />
-Abteilungsnummer<br />
-Abteilungsleiter<br />
-kauft<br />
-wird erworben von<br />
Werbeartikel<br />
-Beschreibung : Zeichenkette<br />
-Preis : Dezimal<br />
-Lagerbestand : Ganzzahl<br />
Kun<strong>de</strong><br />
-gehört zu<br />
-besteht aus<br />
0..1<br />
0..*<br />
0..*<br />
1..*<br />
-Kun<strong>de</strong>nnummer : Ganzzahl<br />
-Name : Zeichenkette<br />
-Vorname : Zeichenkette<br />
-Strasse : Zeichenkette<br />
-Plz : Ganzzahl<br />
-Ort : Zeichenkette<br />
Artikel<br />
-Artikelnummer : Ganzzahl<br />
-Bezeichnung : Zeichenkette<br />
ist Vorgesetzter von ist Mitarbeiter von<br />
Mitarbeiter<br />
-Personalnummer : Ganzzahl<br />
-Name : Zeichenkette<br />
-Vorname : Zeichenkette<br />
-Strasse : Zeichenkette<br />
-Plz : Ganzzahl<br />
-Ort : Zeichenkette<br />
Bestellung<br />
-Bestellnummer : Ganzzahl<br />
-Positionsnummer : Ganzzahl = 1<br />
-Menge : Ganzzahl = 1<br />
-Datum : Datum = 01.01.2002<br />
Sitzplatz<br />
-Bereich : Zeichenkette<br />
-Reihe : Ganzzahl<br />
-Sitz : Ganzzahl<br />
-Preis : Dezimal<br />
-Zustand : Char<br />
1<br />
-bearbeitet<br />
-ist verheiratet mit<br />
Abbildung 3.29: UML-Klassendiagramm für unser Fallbeispiel<br />
0..*<br />
1<br />
-ist verheiratet mit<br />
0..1<br />
-wird bearbeitet von<br />
Veranstaltung<br />
-Veranstaltungsnummer : Zeichenkette<br />
-Bezeichnung : Zeichenkette<br />
-Autor : Zeichenkette<br />
-ist für<br />
1..*<br />
-besteht aus 1<br />
-vermietet<br />
1..1<br />
-basiert auf 0..*<br />
Ehepartner<br />
-Name : Zeichenkette<br />
-Vorname : Zeichenkette<br />
-Alter : Ganzzahl<br />
Vorstellung<br />
-Haus : Zeichenkette<br />
-Strasse : Zeichenkette<br />
-Plz : Zeichenkette<br />
-Ort : Zeichenkette<br />
-Vorstellungsnummer : Ganzzahl<br />
-Datum : Datum<br />
-Uhrzeit : Datum<br />
Spielstätte<br />
1<br />
-präsentiert<br />
0..*<br />
-f<strong>in</strong><strong>de</strong>t statt <strong>in</strong>
3.7 Zusammenfassung<br />
Zusammenfassung<br />
In diesem Kapitel haben wir kennen gelernt, wie man von e<strong>in</strong>er Problembeschreibung<br />
zu e<strong>in</strong>em Datenmo<strong>de</strong>ll kom<strong>mt</strong>. Bevor mit <strong><strong>de</strong>r</strong> eigentlichen Datenmo<strong>de</strong>llierung begonnen<br />
wird, stellt man e<strong>in</strong>en Projektplan auf, <strong><strong>de</strong>r</strong> be<strong>in</strong>haltet, <strong>in</strong> welchen Schritten man<br />
vorgeht. Als Grundlage verwen<strong>de</strong>t man e<strong>in</strong> Phasenkonzept, das sozusagen als Vorlage<br />
zur Erstellung e<strong>in</strong>es Projektplanes dient. Dabei haben wir auch gesehen, dass die<br />
Datenmo<strong>de</strong>llierung selbst nur e<strong>in</strong>en Teil <strong>de</strong>s Entwicklungsprozesses von <strong><strong>de</strong>r</strong> Problembeschreibung<br />
zur Problemlösung darstellt.<br />
Im ersten Schritt lernt man das Geschäftsumfeld, <strong>in</strong> <strong>de</strong>m Probleme auftreten, kennen.<br />
Dazu spricht man mit Personen, sichtet Dokumente und sieht sich eventuell vorhan<strong>de</strong>ne<br />
Anwendungssysteme an.<br />
Daraufh<strong>in</strong> i<strong>de</strong>ntifiziert und klassifiziert man die gefun<strong>de</strong>nen Informationen und abstrahiert<br />
sie so weit, dass man so genannte Geschäftsobjekte und <strong><strong>de</strong>r</strong>en Beziehungen<br />
herausf<strong>in</strong><strong>de</strong>t. Geschäftsobjekte und <strong><strong>de</strong>r</strong>en Beziehungen wer<strong>de</strong>n <strong>in</strong> Datenmo<strong>de</strong>llen dargestellt,<br />
die zum e<strong>in</strong>en zur Kommunikation mit <strong>de</strong>m Kun<strong>de</strong>n und an<strong><strong>de</strong>r</strong>erseits als<br />
Grundlage zur Umsetzung <strong>in</strong> e<strong>in</strong>e Datenbankstruktur dienen.<br />
Zur Erstellung von Datenmo<strong>de</strong>llen haben sich zwei Mo<strong>de</strong>llierungstechniken <strong>in</strong> <strong><strong>de</strong>r</strong><br />
<strong>Praxis</strong> durchgesetzt, das »Entity-Relationship-Mo<strong>de</strong>ll« (ERM) und die »Unified Mo<strong>de</strong>l<strong>in</strong>g<br />
Language« (UML). Anhand e<strong>in</strong>es Fallbeispiels haben wir e<strong>in</strong> Datenmo<strong>de</strong>ll <strong>in</strong> Form<br />
e<strong>in</strong>es ERM nach Chen, e<strong>in</strong>es ERM nach Barker und mit <strong><strong>de</strong>r</strong> UML erstellt und dabei die<br />
Unterschie<strong>de</strong> zwischen <strong>de</strong>n Mo<strong>de</strong>llierungstechniken kennen gelernt.<br />
Dieses Kapitel soll lediglich als E<strong>in</strong>führung <strong>in</strong> die Datenmo<strong>de</strong>llierung dienen. Zur<br />
<strong>de</strong>taillierten Ause<strong>in</strong>an<strong><strong>de</strong>r</strong>setzung mit e<strong>in</strong>er <strong><strong>de</strong>r</strong> Mo<strong>de</strong>llierungstechniken, empfehle ich<br />
die Literaturliste am En<strong>de</strong> <strong>de</strong>s Buches.<br />
Zum Schluss sei noch erwähnt, dass das ERM und die UML nicht immer gewährleisten,<br />
dass e<strong>in</strong> <strong>in</strong> sich logisches Datenmo<strong>de</strong>ll entsteht. So enthält das Datenmo<strong>de</strong>ll unseres<br />
Fallbeispiels e<strong>in</strong>en Teil, <strong><strong>de</strong>r</strong> noch nicht »sauber« mo<strong>de</strong>lliert ist. Wir wer<strong>de</strong>n hierauf<br />
<strong>in</strong> Kapitel 6 zurückkommen und dort e<strong>in</strong>e Metho<strong>de</strong>, nämlich die Normalisierung kennen<br />
lernen, die das erstellte Mo<strong>de</strong>ll noch e<strong>in</strong>mal validiert. Die Normalisierung wird<br />
allerd<strong>in</strong>gs auf das logische Relationenmo<strong>de</strong>ll angewen<strong>de</strong>t. Bevor wir uns <strong>de</strong>shalb mit<br />
<strong><strong>de</strong>r</strong> Normalisierung beschäftigen, gehen wir im nächsten Kapitel auf das am weitesten<br />
verbreitete logische Mo<strong>de</strong>ll für relationale Datenbanken e<strong>in</strong>, das Relationenmo<strong>de</strong>ll.<br />
3.8 Aufgaben<br />
Wie<strong><strong>de</strong>r</strong>holungsfragen<br />
1) Aus welchen Phasen besteht das <strong>in</strong> diesem Buch vorgestellte Phasenkonzept?<br />
2) In welchem Bezug steht das Phasenkonzept zum Projektplan?<br />
3) Wozu dient <strong><strong>de</strong>r</strong> konzeptionelle Entwurf?<br />
4) Wor<strong>in</strong> besteht <strong><strong>de</strong>r</strong> Unterschied zwischen konzeptionellem und logischem Entwurf?<br />
65
66<br />
3 Datenbankentwurf – Von <strong><strong>de</strong>r</strong> Realität zum »Bauplan«<br />
5) Welcher Phase s<strong>in</strong>d die Mo<strong>de</strong>llierungstechniken <strong>de</strong>s ERM und <strong><strong>de</strong>r</strong> UML zuzuordnen?<br />
6) Wie wird e<strong>in</strong>e N:M-Beziehung im ERM nach Chen, ERM nach Barker und mit <strong><strong>de</strong>r</strong><br />
UML grafisch dargestellt?<br />
Übungen<br />
1) E<strong>in</strong> Mitarbeiter bestellt bei e<strong>in</strong>em Bürolieferanten Büromaterial. Welche <strong><strong>de</strong>r</strong> folgen<strong>de</strong>n<br />
Attribute s<strong>in</strong>d <strong>de</strong>m Geschäftsobjekt »Bürolieferant« zuzuordnen und welches<br />
Attribut wür<strong>de</strong>n Sie als Primärschlüssel für das Geschäftsobjekt festlegen?<br />
Name <strong>de</strong>s Mitarbeiters, Lieferantennummer, Bestellnummer, bestellte Artikel, Bezeichnung<br />
<strong><strong>de</strong>r</strong> Firma <strong>de</strong>s Mitarbeiters, Bezeichnung <strong>de</strong>s Lieferanten, Adresse <strong>de</strong>s<br />
Lieferanten.<br />
2) E<strong>in</strong> Onl<strong>in</strong>e-Spielzeugwarengeschäft verkauft über das Internet Spielzeug. E<strong>in</strong><br />
Kun<strong>de</strong> gibt mehrere Bestellungen auf. E<strong>in</strong>e Bestellung enthält mehrere Artikel bzw.<br />
je<strong><strong>de</strong>r</strong> Artikel kann auf verschie<strong>de</strong>nen Bestellungen ersche<strong>in</strong>en. Die Bestellungen<br />
wer<strong>de</strong>n von Mitarbeitern bearbeitet.<br />
Entwerfen Sie e<strong>in</strong> Datenmo<strong>de</strong>ll nach <strong>de</strong>m ERM von Baker und nach <strong><strong>de</strong>r</strong> UML.<br />
3) Für e<strong>in</strong> Geo-Informationssystem soll e<strong>in</strong> Datenmo<strong>de</strong>ll erstellt wer<strong>de</strong>n. Auf <strong><strong>de</strong>r</strong> Er<strong>de</strong><br />
gibt es mehrere Staaten. Je<strong><strong>de</strong>r</strong> Staat besteht wie<strong><strong>de</strong>r</strong>um aus mehreren Regionen und<br />
je<strong><strong>de</strong>r</strong> Staat hat genau e<strong>in</strong>en Staatsherrscher. E<strong>in</strong> Staatsherrscher kann entwe<strong><strong>de</strong>r</strong> e<strong>in</strong><br />
<strong>de</strong>mokratisch gewählter Präsi<strong>de</strong>nt o<strong><strong>de</strong>r</strong> e<strong>in</strong> Diktator se<strong>in</strong>. Merkmale e<strong>in</strong>es Staatsherrschers<br />
s<strong>in</strong>d se<strong>in</strong> Name und se<strong>in</strong> Geburtsdatum. Merkmale e<strong>in</strong>es <strong>de</strong>mokratisch<br />
gewählten Präsi<strong>de</strong>nten s<strong>in</strong>d se<strong>in</strong>e Parteizugehörigkeit und die Anzahl <strong><strong>de</strong>r</strong> Wählerstimmen,<br />
die er bei <strong><strong>de</strong>r</strong> letzten Wahl erhalten hat. Merkmale e<strong>in</strong>es Diktators s<strong>in</strong>d<br />
se<strong>in</strong> geschätztes Vermögen.<br />
E<strong>in</strong> Staat hat e<strong>in</strong>e Hauptstadt, die, genau wie e<strong>in</strong> Staat, gekennzeichnet ist, durch<br />
die Anzahl <strong><strong>de</strong>r</strong> Bewohner, e<strong>in</strong>e Gesa<strong>mt</strong>fläche <strong>in</strong> Quadratmetern und durch e<strong>in</strong>e Bevölkerungsdichte.<br />
Entsprechend existieren <strong>in</strong> je<strong><strong>de</strong>r</strong> Region weitere Orte mit gleichen<br />
Kennzahlen.<br />
Entwerfen Sie e<strong>in</strong> Datenmo<strong>de</strong>ll nach <strong>de</strong>m ERM von Baker und nach <strong><strong>de</strong>r</strong> UML.<br />
4) E<strong>in</strong>e Hotelkette hat mehrere Hotels <strong>in</strong> verschie<strong>de</strong>nen Orten. Je<strong>de</strong>s Hotel wird von<br />
e<strong>in</strong>em Hotelmanager geleitet. Je<strong>de</strong>s Hotel hat mehrere Doppel- und E<strong>in</strong>zelzimmer<br />
und verschie<strong>de</strong>ne Konferenzräume.<br />
In je<strong>de</strong>m dieser Räume bef<strong>in</strong><strong>de</strong>t sich Inventar, wie z.B. Stühle, Betten, Fernseher. E<strong>in</strong><br />
Doppelzimmer kostet pro Übernachtung 220 Euro, e<strong>in</strong> E<strong>in</strong>zelzimmer 150 Euro und<br />
je<strong><strong>de</strong>r</strong> Konferenzraum pro Quadratmeter 10 Euro. Die Räume wer<strong>de</strong>n sowohl an Privatpersonen<br />
vermietet, als auch an Firmen, sofern es sich um Konferenzräume han<strong>de</strong>lt.<br />
Entwerfen Sie e<strong>in</strong> Datenmo<strong>de</strong>ll nach <strong>de</strong>m ERM von Baker und nach <strong><strong>de</strong>r</strong> UML.<br />
5) In e<strong>in</strong>er Arztpraxis arbeiten die Ärzte Hohlbe<strong>in</strong>, Dürer und Grunewald. Hohlbe<strong>in</strong><br />
ist für Hals-/Nasen-/Ohrenkrankheiten zuständig, Dürer für <strong>in</strong>nere Krankheiten<br />
und Grunewald für Hautkrankheiten.<br />
In die Arztpraxis kommen Patienten, die von <strong>de</strong>n Ärzten, abhängig von ihrer Krankeit,<br />
behan<strong>de</strong>lt wer<strong>de</strong>n. Je<strong><strong>de</strong>r</strong> Patient wird mit Name, Vorname, Adresse und Krankenkasse<br />
registriert. Abhängig von <strong><strong>de</strong>r</strong> Krankheit, behan<strong>de</strong>ln auch mehrere Ärzte<br />
e<strong>in</strong>en Patienten.
Aufgaben<br />
Zu je<strong><strong>de</strong>r</strong> Krankheit wird neben <strong><strong>de</strong>r</strong> Diagnose festgehalten, welcher Arzt diese behan<strong>de</strong>lt<br />
und welche Kosten durch die Behandlung entstan<strong>de</strong>n s<strong>in</strong>d.<br />
Entwerfen Sie e<strong>in</strong> Datenmo<strong>de</strong>ll nach <strong>de</strong>m ERM von Baker und nach <strong><strong>de</strong>r</strong> UML.<br />
6) Im F<strong>in</strong>anza<strong>mt</strong> gibt es die Abteilungen »Betriebsprüfung« , »Gewerbesteuer« und<br />
»E<strong>in</strong>kommenssteuererklärungen« .<br />
In <strong><strong>de</strong>r</strong> Abteilung »E<strong>in</strong>kommenssteuererklärungen« arbeiten die F<strong>in</strong>anzbea<strong>mt</strong>en<br />
Muster, Mahlzahn, Hohlste<strong>in</strong> und Wichtig. Herr Wichtig ist <strong><strong>de</strong>r</strong> Abteilungsleiter.<br />
E<strong>in</strong> Abteilungsleiter betreut mehrere Mitarbeiter, wobei e<strong>in</strong> Mitarbeiter immer genau<br />
e<strong>in</strong>en Abteilungsleiter hat.<br />
Muster bearbeitet die Anträge <strong><strong>de</strong>r</strong> Steuerpflichtigen, <strong><strong>de</strong>r</strong>en Nachname mit »A-H«<br />
beg<strong>in</strong>nt, Mahlzahn von »I-M« und Hohlste<strong>in</strong> von »N-Z« .<br />
Pro E<strong>in</strong>kommenssteuererklärung gibt es genau e<strong>in</strong>en Bearbeiter. Bei <strong><strong>de</strong>r</strong> E<strong>in</strong>kommensteuererklärung<br />
wird neben <strong>de</strong>m Namen, <strong><strong>de</strong>r</strong> Adresse und <strong><strong>de</strong>r</strong> Steuernummer<br />
<strong>de</strong>s Steuerpflichtigen auch <strong><strong>de</strong>r</strong> Bearbeitungsstatus vermerkt.<br />
Bei schwierigen Fällen übergeben die Bearbeiter die E<strong>in</strong>kommenssteuererklärung<br />
ihrem Vorgesetzten Herrn Wichtig und benachrichtigen ihn über <strong>de</strong>n Teil, bei <strong>de</strong>m<br />
sie Probleme hatten. Herr Wichtig führt die Bearbeitung dann zu En<strong>de</strong>.<br />
Entwerfen Sie e<strong>in</strong> Datenmo<strong>de</strong>ll nach <strong>de</strong>m ERM von Baker und nach <strong><strong>de</strong>r</strong> UML.<br />
7) Zur Verwaltung <strong><strong>de</strong>r</strong> Fussballspiele möchte <strong><strong>de</strong>r</strong> »Hamburger Fussballverband«<br />
(HFV) e<strong>in</strong>e Datenbank erstellen.<br />
Der HFV besteht aus mehreren Mannschaften. Diese Mannschaften haben e<strong>in</strong>e Bezeichnung<br />
und bis zu vier verschie<strong>de</strong>ne Postadressen. Je<strong>de</strong> Mannschaft besteht aus<br />
mehreren Spielern. Je<strong><strong>de</strong>r</strong> Spieler hat e<strong>in</strong>en Vor- und Nachnamen, e<strong>in</strong>e Adresse und<br />
e<strong>in</strong>e bevorzugte Spielernummer. Je<strong><strong>de</strong>r</strong> Spieler darf nur für e<strong>in</strong>e e<strong>in</strong>zige Mannschaft<br />
spielen.<br />
Die Mannschaften spielen gegene<strong>in</strong>an<strong><strong>de</strong>r</strong> <strong>in</strong> e<strong>in</strong>em H<strong>in</strong>- und Rückspiel. H<strong>in</strong>- und<br />
Rückspiele f<strong>in</strong><strong>de</strong>n zu bestim<strong>mt</strong>en Term<strong>in</strong>en und <strong>in</strong> e<strong>in</strong>em bestim<strong>mt</strong>en Ort statt. E<strong>in</strong><br />
Fussballspiel wird von e<strong>in</strong>em Schiedsrichter und zwei L<strong>in</strong>ienrichtern geleitet.<br />
Entwerfen Sie e<strong>in</strong> Datenmo<strong>de</strong>ll nach <strong>de</strong>m ERM von Baker und nach <strong><strong>de</strong>r</strong> UML.<br />
8) Die Unternehmensberatung »Software Consult AG« möchte ihre Projekte mit <strong>de</strong>n<br />
Kun<strong>de</strong>n <strong>in</strong> e<strong>in</strong>er Datenbank verwalten. E<strong>in</strong> Kun<strong>de</strong> beauftragt e<strong>in</strong> o<strong><strong>de</strong>r</strong> mehrere Projekte.<br />
Projekte wer<strong>de</strong>n von Mitarbeitern <strong><strong>de</strong>r</strong> Unternehmensberatung durchgeführt.<br />
E<strong>in</strong> Mitarbeiter kann mehreren Projekten zugeordnet se<strong>in</strong>, und e<strong>in</strong> Projekt besteht<br />
<strong>in</strong> <strong><strong>de</strong>r</strong> Regel aus mehreren Mitarbeitern. Zusätzlich ist e<strong>in</strong> Mitarbeiter e<strong>in</strong>er Abteilung<br />
zugeordnet. Für je<strong>de</strong>s Projekt gibt es e<strong>in</strong>en Mitarbeiter, <strong><strong>de</strong>r</strong> Projektleiter für das<br />
Projekt ist.<br />
Merkmale e<strong>in</strong>es Projektes s<strong>in</strong>d die Bezeichnung, Anfangs- und geplanter Fertigstellungsterm<strong>in</strong>.<br />
Entwerfen Sie e<strong>in</strong> Datenmo<strong>de</strong>ll nach <strong>de</strong>m ERM von Baker und nach <strong><strong>de</strong>r</strong> UML.<br />
9) In e<strong>in</strong>er Volkshochschule unterrichten die Dozenten Hansen, Meier und Oberdorf.<br />
Meier unterrichtet die Kurse »EDV Grundlagen« und »W<strong>in</strong>Word« , Hansen <strong>de</strong>n<br />
Kurs »Kochen für K<strong>in</strong><strong><strong>de</strong>r</strong>« und Oberdorf die Kurse »Market<strong>in</strong>g« und »Controll<strong>in</strong>g« .<br />
Zu je<strong>de</strong>m Kurs mel<strong>de</strong>n sich mehrere Teilnehmer an, die für diesen Kurs e<strong>in</strong>e Kursgebühr<br />
zahlen müssen. Für je<strong>de</strong>n Kurs gibt es e<strong>in</strong>e maximale Anzahl an Teilnehmern.<br />
Entwerfen Sie e<strong>in</strong> Datenmo<strong>de</strong>ll nach <strong>de</strong>m ERM von Baker und nach <strong><strong>de</strong>r</strong> UML.<br />
67
4 Datenbankentwurf<br />
– Vom<br />
»Bauplan« zur<br />
Datenbankstruktur<br />
In Kapitel 4 sollen folgen<strong>de</strong> Fragen geklärt wer<strong>de</strong>n:<br />
� Wozu dient <strong><strong>de</strong>r</strong> logische Entwurf?<br />
� Wie kom<strong>mt</strong> man vom konzeptionellem Entwurf zum DV-technischen Entwurf<br />
(logisches Mo<strong>de</strong>ll)?<br />
� Welche Entwurfmetho<strong>de</strong> gibt es für <strong>de</strong>n logischen Entwurf von relationalen Datenbanken<br />
(Relationenmo<strong>de</strong>ll)?<br />
� Wie kom<strong>mt</strong> man vom Entity-Relationship-Mo<strong>de</strong>ll (ERM) zum Relationenmo<strong>de</strong>ll?<br />
4.1 Motivation<br />
Betrachten wir zunächst wie<strong><strong>de</strong>r</strong> unser Fallbeispiel. Inzwischen s<strong>in</strong>d sechs Wochen vergangen<br />
und Herr Dr. Fleissig von <strong><strong>de</strong>r</strong> Unternehmensberatung »Software Consult AG«<br />
hat das konzeptionelle Mo<strong>de</strong>ll für »KartoF<strong>in</strong>ale« erstellt. Er hat e<strong>in</strong> Entity-Relationship-Mo<strong>de</strong>ll<br />
nach Baker erstellt und es so weit mit <strong>de</strong>m Kun<strong>de</strong>n besprochen und<br />
immer wie<strong><strong>de</strong>r</strong> durchdiskutiert, dass er sich jetzt sicher ist, das Geschäftsumfeld von<br />
»KartoF<strong>in</strong>ale« verstan<strong>de</strong>n zu haben. Damit ist <strong><strong>de</strong>r</strong> erste Meilenste<strong>in</strong> <strong>de</strong>s Projektplanes<br />
erfolgreich und »just-<strong>in</strong>-time« erledigt. Herr Fleissig, stolz auf se<strong>in</strong>e Leistung, beg<strong>in</strong>nt<br />
nun hochmotiviert mit <strong><strong>de</strong>r</strong> Umsetzung auf <strong>de</strong>n Computer. Bevor er sich jedoch mit <strong><strong>de</strong>r</strong><br />
Umsetzung <strong>de</strong>s ERM auf <strong>de</strong>n Computer beschäftigt, muss das ERM so umgewan<strong>de</strong>lt<br />
wer<strong>de</strong>n, dass es überhaupt auf <strong>de</strong>n Computer übertragen wer<strong>de</strong>n kann.<br />
Zur Zeit hat Herr Fleissig ja nur e<strong>in</strong>e Grafik und e<strong>in</strong>e textuelle Beschreibung <strong>de</strong>s<br />
Geschäftsumfel<strong>de</strong>s. Da er noch nicht weiß, welches relationale Datenbank-Management-System<br />
(RDBMS) später e<strong>in</strong>gesetzt wer<strong>de</strong>n soll, muss er also e<strong>in</strong> Mo<strong>de</strong>ll entwerfen,<br />
dass auf e<strong>in</strong>en beliebigen Computer für e<strong>in</strong> beliebiges RDBMS übertragen wer<strong>de</strong>n<br />
kann.<br />
Herr Fleissig kennt sich natürlich mit relationalen Datenbank-Management-Systemen<br />
aus und weiß, dass diese die Daten <strong>in</strong> Form von Tabellen speichern. Also entschließt er<br />
sich se<strong>in</strong> ERM so umzuwan<strong>de</strong>ln, dass es <strong>in</strong> Form von Tabellen abgebil<strong>de</strong>t wer<strong>de</strong>n kann.<br />
Zunächst überlegt er sich, je<strong>de</strong>n Entitytyp <strong>in</strong> genau e<strong>in</strong>e Tabelle umzuwan<strong>de</strong>ln. Damit<br />
hat er schon e<strong>in</strong>mal die Daten <strong><strong>de</strong>r</strong> Entities abgebil<strong>de</strong>t, <strong>in</strong><strong>de</strong>m er pro Zeile e<strong>in</strong>er Tabelle<br />
e<strong>in</strong>en Entity speichert.<br />
Doch wie können Beziehungen <strong>in</strong> Tabellenform abgebil<strong>de</strong>t wer<strong>de</strong>n? Um e<strong>in</strong>en Bezug<br />
zwischen Tabellen herzustellen, erstellt er e<strong>in</strong>fach <strong>in</strong> <strong><strong>de</strong>r</strong> e<strong>in</strong>en Tabelle e<strong>in</strong> zusätzliches<br />
Attribut, das <strong>de</strong>n Primärschlüssel <strong><strong>de</strong>r</strong> an<strong><strong>de</strong>r</strong>en Tabelle als Bezug speichert. Betrachten<br />
69
70<br />
4 Datenbankentwurf – Vom »Bauplan« zur Datenbankstruktur<br />
wir hierzu die Beziehung zwischen Abteilung und Mitarbeiter. In Tabellenform aus<br />
<strong>de</strong>m ERM transformiert sieht das Ganze wie folgt aus:<br />
Abteilungsbezeichnung<br />
Rechnungswesen<br />
Vertrieb<br />
Personal<br />
Geschäftsführung<br />
PK<br />
Abteilung<br />
Abteilungsnummer<br />
1<br />
2<br />
3<br />
4<br />
PK<br />
Mitarbeiter<br />
FK<br />
Personalnummer Name Vorname Strasse Plz Ort Abteilungsbezeichnung<br />
1<br />
Wun<strong><strong>de</strong>r</strong> Hans Kohlweg 1 12345 Kohlsen Rechnungswesen<br />
3 Kart Karen Pantherstr. 12 25746 Hei<strong>de</strong><br />
Vertrieb<br />
4 Klug Frieda Musterweg 110 22222 Hamburg<br />
Vertrieb<br />
5 Kle<strong>in</strong> Karl M<strong>in</strong>imalweg 1 22233 Kle<strong>in</strong>sen<br />
Vertrieb<br />
7<br />
Münze Egon Geldstr. 10 22343 Reichtum Personal<br />
6<br />
Kowalski Karsten Blankeneser Weg 2 22244 Hamburg Geschäftsführung<br />
Herr Fleissig hat <strong>de</strong>n Primärschlüssel <strong><strong>de</strong>r</strong> Abteilung als Referenz <strong>in</strong> die Mitarbeitertabelle<br />
übernommen. Damit ist die 1:N-Beziehung zwischen Abteilung und Mitarbeiter<br />
abgebil<strong>de</strong>t. Man kann damit sowohl herausbekommen, zu welcher Abteilung e<strong>in</strong><br />
Mitarbeiter gehört und wer <strong><strong>de</strong>r</strong> entsprechen<strong>de</strong> Abteilungsleiter ist. Umgekehrt kann<br />
man auch ermitteln, zu welcher Abteilung welche Mitarbeiter gehören.<br />
Nehmen wir als Beispiel aus <strong><strong>de</strong>r</strong> Mitarbeitertabelle <strong>de</strong>n Mitarbeiter Karl Kle<strong>in</strong>. Herr<br />
Kle<strong>in</strong> gehört zur Abteilung »Vertrieb« . Der Wert »Vertrieb« ist gleichzeitig Primärschlüssel<br />
<strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle Abteilung. Sucht man <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »Abteilung« nun <strong>de</strong>n E<strong>in</strong>trag für<br />
<strong>de</strong>n Wert »Vertrieb« (1), so sieht man, dass <strong><strong>de</strong>r</strong> Abteilungsleiter dieser Abteilung die Personalnummer<br />
3 hat. Entsprechend kann man <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »Mitarbeiter« wie<strong><strong>de</strong>r</strong> nachsehen,<br />
um welchen Mitarbeiter es sich hier han<strong>de</strong>lt, nämlich um Frau Kart (2).<br />
Herr Fleissig erstellt die Tabellen <strong>in</strong> Textform. Dabei führt er jeweils die Bezeichnung<br />
<strong><strong>de</strong>r</strong> Tabelle und <strong>in</strong> Klammern die Attribute bzw. Spalten <strong><strong>de</strong>r</strong> Tabelle auf. Primärschlüssel<br />
stellt er unterstrichen dar und Referenzen jeweils kursiv. Für unsere Tabellen »Mitarbeiter«<br />
und »Abteilung« sieht das Ganze wie folgt aus:<br />
Abteilung (Abteilungsbezeichnung, Abteilungsnummer, Abteilungsleiter)<br />
Mitarbeiter (Personalnummer,Name,Vorname,Strasse, Plz, Ort, Abteilungsbezeichnung)<br />
4.2 Relationenmo<strong>de</strong>ll<br />
Abteilungsleiter<br />
1<br />
3<br />
7<br />
6<br />
FK<br />
Abbildung 4.1: Tabellen und <strong><strong>de</strong>r</strong>en Beziehungen<br />
Im letzten Kapitel haben wir gesehen, dass man zunächst das Umfeld <strong>de</strong>s zu lösen<strong>de</strong>n<br />
Problemes analysieren und beschreiben muss. Als Ergebnis entsteht das konzeptionelle<br />
Mo<strong>de</strong>ll, das häufig auch als Fachkonzept bezeichnet wird, da es e<strong>in</strong> Problem aus fachlicher<br />
und nicht technischer Sicht beschreiben soll. Bevor man sich nun an e<strong>in</strong>en Computer<br />
setzt und dieses Fachkonzept auf diesen überträgt, muss e<strong>in</strong> Konzept zur Über-<br />
1<br />
2
Grundlagen <strong>de</strong>s Relationenmo<strong>de</strong>lls<br />
tragung auf <strong>de</strong>n Computer erstellt wer<strong>de</strong>n. Man spricht hier vom logischen Mo<strong>de</strong>ll<br />
o<strong><strong>de</strong>r</strong> auch DV-Konzept, weil e<strong>in</strong> <strong>in</strong> sich logisches und mathematisch schlüssiges Konzept<br />
entstehen soll.<br />
Bei <strong><strong>de</strong>r</strong> Datenmo<strong>de</strong>llierung für relationale Datenbank-Management-Systeme hat sich<br />
hier das Relationenmo<strong>de</strong>ll durchgesetzt. Das Relationenmo<strong>de</strong>ll stam<strong>mt</strong> von Dr. E. F.<br />
Codd und wur<strong>de</strong> erstmals 1970 <strong>in</strong> e<strong>in</strong>em Artikel <strong>de</strong>s Datenbankjournals <strong>de</strong>s ACM<br />
(»Association for Comput<strong>in</strong>g Mach<strong>in</strong>ery« ) beschrieben. Der Titel zu diesem Artikel<br />
lautet »A Relational Mo<strong>de</strong>l of Data for Large Shared Data Banks« . Das Relationenmo<strong>de</strong>ll<br />
beschreibt die theoretischen mathematischen Grundlagen, die e<strong>in</strong>em relationalen<br />
Datenbank-Management-System zugrun<strong>de</strong> liegen. Entsprechend ist e<strong>in</strong> logisches<br />
Mo<strong>de</strong>ll auf Basis <strong>de</strong>s Relationenmo<strong>de</strong>lls auch sehr e<strong>in</strong>fach auf e<strong>in</strong> RDBMS zu übertragen.<br />
Da das logische Datenbankmo<strong>de</strong>ll auf <strong>de</strong>m Relationenmo<strong>de</strong>ll basiert, ist es unabhängig<br />
von e<strong>in</strong>em ganz bestim<strong>mt</strong>en RDBMS und e<strong>in</strong>er ganz bestim<strong>mt</strong>en Computerplattform.<br />
Im Folgen<strong>de</strong>n wer<strong>de</strong>n wir uns pragmatisch mit <strong>de</strong>m Relationenmo<strong>de</strong>ll beschäftigen,<br />
ohne dabei zu theoretisch und mathematisch zu wer<strong>de</strong>n. Es wer<strong>de</strong>n nur die Aspekte<br />
<strong>de</strong>s Relationenmo<strong>de</strong>lls beschrieben, die für die Umsetzung e<strong>in</strong>es Datenmo<strong>de</strong>lls notwendig<br />
s<strong>in</strong>d. Wir wer<strong>de</strong>n uns dabei vor allem darauf konzentrieren, wie man aus <strong>de</strong>m<br />
konzeptionellen Mo<strong>de</strong>ll (ERM o<strong><strong>de</strong>r</strong> UML-Mo<strong>de</strong>ll) e<strong>in</strong> Relationenmo<strong>de</strong>ll erstellt.<br />
4.3 Grundlagen <strong>de</strong>s Relationenmo<strong>de</strong>lls<br />
Bevor wir uns mit <strong><strong>de</strong>r</strong> eigentlichen Umsetzung <strong>de</strong>s konzeptionellen Mo<strong>de</strong>lls <strong>in</strong> e<strong>in</strong><br />
Relationenmo<strong>de</strong>ll beschäftigen, wollen wir kurz die wichtigsten Grundlagen <strong>de</strong>s Relationenmo<strong>de</strong>lls<br />
kennen lernen. Das Relationenmo<strong>de</strong>ll basiert mathematisch auf <strong><strong>de</strong>r</strong><br />
Mengenlehre und <strong><strong>de</strong>r</strong> Mengenalgebra (Relationentheorie).<br />
Objekttypen wer<strong>de</strong>n dabei <strong>in</strong> Form von Mengen (Relationen) dargestellt. Je<strong>de</strong> Relation<br />
wie<strong><strong>de</strong>r</strong>um besteht aus mehreren Objekten bzw. Objekt<strong>in</strong>stanzen, die gleichartig s<strong>in</strong>d<br />
und durch gleiche Attribute beschrieben wer<strong>de</strong>n. So gehört <strong>in</strong> unserem Fallbeispiel<br />
Herr Egon Münze zu <strong><strong>de</strong>r</strong> Relation »Mitarbeiter« und besitzt die Attribute »Personalnummer«<br />
, »Name« , »Vorname« , »Strasse« , »Plz« und »Ort« . E<strong>in</strong>e Objekt<strong>in</strong>stanz wird<br />
im Relationenmo<strong>de</strong>ll als Tupel bezeichnet. Da es sich um e<strong>in</strong>e Menge han<strong>de</strong>lt, existiert<br />
ke<strong>in</strong>e Reihenfolge bzw. Sortierung <strong><strong>de</strong>r</strong> Attribute o<strong><strong>de</strong>r</strong> auch <strong><strong>de</strong>r</strong> Tupel selber. Der E<strong>in</strong>fachheit<br />
halber wer<strong>de</strong>n Relationen nicht als Mengen gezeichnet, son<strong><strong>de</strong>r</strong>n <strong>in</strong> Form von<br />
2-dimensionalen Tabellen dargestellt. Entsprechend wer<strong>de</strong>n im allgeme<strong>in</strong>en Sprachgebrauch<br />
die Begriffe Relation, Tupel und Attribut selten verwen<strong>de</strong>t. Man spricht eher<br />
von Tabelle (Table), Satz (Record o<strong><strong>de</strong>r</strong> Row) und Spalte (Feld, Field, Column).<br />
Betrachten wir hierzu die Menge <strong><strong>de</strong>r</strong> Mitarbeiter aus unserem Fallbeispiel, so haben<br />
wir sieben Tupel bzw. Sätze.<br />
71
72<br />
1<br />
Wun<strong><strong>de</strong>r</strong><br />
Hans<br />
Kohlweg 1<br />
12345<br />
Kohlsen<br />
Rechnungswesen<br />
3<br />
Kart<br />
Karen<br />
Pantherstr. 12<br />
25746<br />
Hei<strong>de</strong><br />
Vertrieb<br />
4 Datenbankentwurf – Vom »Bauplan« zur Datenbankstruktur<br />
4<br />
Klug<br />
Frieda<br />
Musterweg 110<br />
22222<br />
Hamburg<br />
Vertrieb<br />
6<br />
Kowalski<br />
Karsten<br />
Blankeneser Weg 2<br />
22244<br />
Hamburg<br />
5<br />
Kle<strong>in</strong><br />
Karl<br />
M<strong>in</strong>imalweg 1<br />
22233<br />
Kle<strong>in</strong>sen<br />
Vertrieb<br />
Relation (Menge) = Tabelle<br />
(Table)<br />
7<br />
Münze<br />
Egon<br />
Geldstr. 10<br />
22343<br />
Reichtum<br />
Personal<br />
Tupel = Satz<br />
(Record, Row)<br />
Personalnummer Name Vorname Strasse Plz Ort Abteilungsbezeichnung<br />
1<br />
Wun<strong><strong>de</strong>r</strong> Hans Kohlweg 1 12345 Kohlsen Rechnungswesen<br />
4<br />
Klug Frieda Musterweg 110 22222 Hamburg<br />
Vertrieb<br />
3<br />
Kart Karen Pantherstr. 12 25746 Hei<strong>de</strong><br />
Vertrieb<br />
5<br />
Kle<strong>in</strong> Karl M<strong>in</strong>imalweg 1 22233 Kle<strong>in</strong>sen<br />
Vertrieb<br />
7<br />
Münze Egon Geldstr. 10 22343 Reichtum Personal<br />
6<br />
Kowalski Karsten Blankeneser Weg 2 22244 Hamburg Geschäftsführung<br />
Attribute = Spalte (Feld,<br />
Field, Column)<br />
Abbildung 4.2: Relation »Mitarbeiter«<br />
Je<strong><strong>de</strong>r</strong> dieser Sätze ist e<strong>in</strong><strong>de</strong>utig, d.h. ke<strong>in</strong> Satz kom<strong>mt</strong> mehrfach vor und je<strong>de</strong> Spalte hat<br />
e<strong>in</strong>en e<strong>in</strong><strong>de</strong>utigen Namen. Die Werte e<strong>in</strong>er Spalte s<strong>in</strong>d von <strong><strong>de</strong>r</strong> gleichen Art und haben<br />
e<strong>in</strong>en Wertebereich (Doma<strong>in</strong>). Der Wertebereich <strong><strong>de</strong>r</strong> Spalte Plz darf z.B. nur <strong>in</strong> Deutschland<br />
gültige Postleitzahlen enthalten. Der Wertebereich <strong><strong>de</strong>r</strong> Spalte Abteilungsbezeichnung<br />
darf dagegen nur Werte enthalten, die <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle Abteilung als Primärschlüssel<br />
auftreten.<br />
E<strong>in</strong> Satz <strong>in</strong>nerhalb e<strong>in</strong>er Tabelle wird e<strong>in</strong><strong>de</strong>utig gekennzeichnet durch se<strong>in</strong>en Primärschlüssel<br />
(Primary Key). Bei e<strong>in</strong>em Primärschlüssel han<strong>de</strong>lt es sich, wie wir bereits<br />
kennen gelernt haben, um e<strong>in</strong>e o<strong><strong>de</strong>r</strong> mehrere Spalten, die e<strong>in</strong>en Satz e<strong>in</strong><strong>de</strong>utig kennzeichnen.<br />
Existieren mehrere solcher Spalten, so wählt man e<strong>in</strong>en dieser möglichen<br />
Schlüsselkandidaten als Primärschlüssel aus. So hat z.B. die Tabelle »Abteilung« zwei<br />
mögliche Schlüsselkandidaten, nämlich die Abteilungsnummer und die Abteilungsbezeichnung.<br />
In diesem Fall kann man sich für e<strong>in</strong>e <strong><strong>de</strong>r</strong> bei<strong>de</strong>n Spalten als Primärschlüssel<br />
entschei<strong>de</strong>n.<br />
Der Wert e<strong>in</strong>es Primärschlüssels muss immer e<strong>in</strong>malig und darf nicht optional se<strong>in</strong>.<br />
Außer<strong>de</strong>m darf er sich während <strong><strong>de</strong>r</strong> »Lebenszeit« e<strong>in</strong>es Datensatzes nicht än<strong><strong>de</strong>r</strong>n. So<br />
darf z.B. <strong><strong>de</strong>r</strong> Wert »Vertrieb« <strong>de</strong>s Primärschlüssels Abteilungsbezeichnung <strong><strong>de</strong>r</strong> Tabelle<br />
»Abteilung« nur genau e<strong>in</strong>mal vorkommen. E<strong>in</strong> Primärschlüssel sollte immer m<strong>in</strong>imal<br />
se<strong>in</strong>, d.h. nur so viele Spalten zur e<strong>in</strong><strong>de</strong>utigen I<strong>de</strong>ntifikation besitzen, wie unbed<strong>in</strong>gt<br />
notwendig. So könnte man für die Tabelle »Abteilung« auch e<strong>in</strong>en Primärschlüssel<br />
<strong>de</strong>f<strong>in</strong>ieren, <strong><strong>de</strong>r</strong> aus <strong>de</strong>n bei<strong>de</strong>n Spalten Abteilungsbezeichnung und Abteilungsleiter<br />
besteht. Man hätte <strong>in</strong> diesem Fall also e<strong>in</strong>en zusammengesetzten Schlüssel (»Compound<br />
Key« ). Dies wür<strong>de</strong> jedoch das eben erwähnte Pr<strong>in</strong>zip <strong><strong>de</strong>r</strong> M<strong>in</strong>imalität e<strong>in</strong>es<br />
Schlüssels verletzen, da bereits die Abteilungsbezeichnung zur e<strong>in</strong><strong>de</strong>utigen I<strong>de</strong>ntifikation<br />
e<strong>in</strong>es Satzes ausreicht.<br />
Um nun Beziehungen (Assoziationen) zwischen Tabellen darzustellen, führt das Relationenmo<strong>de</strong>ll<br />
<strong>de</strong>n Begriff <strong>de</strong>s Fremdschlüssels (»Foreign Key« ) e<strong>in</strong>. Hierbei han<strong>de</strong>lt es
Umsetzung <strong>de</strong>s ERM <strong>in</strong> das Relationenmo<strong>de</strong>ll<br />
sich um e<strong>in</strong>e Spalte, die e<strong>in</strong>en Bezug zu e<strong>in</strong>er an<strong><strong>de</strong>r</strong>en Tabelle herstellt. Um z.B. die<br />
Beziehung »Mitarbeiter gehört zu Abteilung« <strong>in</strong> Tabellen abzubil<strong>de</strong>n, übernim<strong>mt</strong> die<br />
Tabelle »Mitarbeiter« <strong>de</strong>n Primärschlüssel <strong><strong>de</strong>r</strong> »Abteilung« als so genannten Fremdschlüssel.<br />
Demnach gilt, dass die Werte e<strong>in</strong>es Fremdschlüssel immer <strong>de</strong>n Werten <strong>de</strong>s<br />
dazugehörigen Primärschlüssels entsprechen müssen. So darf <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »Mitarbeiter«<br />
die Spalte »Abteilungsbezeichnung« nur Werte enthalten, die auch <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle<br />
»Abteilung« <strong>in</strong> <strong><strong>de</strong>r</strong> Spalte »Abteilungsbezeichnung« vorkommen. In <strong><strong>de</strong>r</strong> Tabelle »Mitarbeiter«<br />
ist die Spalte »Abteilungsbezeichnung« Fremdschlüssel und <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle<br />
»Abteilung« ist sie Primärschlüssel. E<strong>in</strong> Fremdschlüssel ist also immer <strong>in</strong> e<strong>in</strong>er an<strong><strong>de</strong>r</strong>en<br />
Tabelle e<strong>in</strong> Primärschlüssel. Diese E<strong>in</strong>schränkung, dass <strong><strong>de</strong>r</strong> Wert e<strong>in</strong>es Fremdschlüssel<br />
immer se<strong>in</strong>em dazugehörigem Primärschlüssel entsprechen muss, bezeichnet man als<br />
referentielle Integrität. Primär- und Fremdschlüssel dienen damit also zur Navigation<br />
zwischen <strong>de</strong>n Tabellen.<br />
Neben <strong><strong>de</strong>r</strong> referentiellen Integrität kennt das Relationenmo<strong>de</strong>ll noch zwei weitere allgeme<strong>in</strong>e<br />
E<strong>in</strong>schränkungen:<br />
� Entity-Integrität<br />
� Doma<strong>in</strong>-Integrität<br />
Entity-Integrität haben wir bereits kennen gelernt. Hierunter versteht man die Tatsache,<br />
dass e<strong>in</strong> Primärschlüssel immer e<strong>in</strong><strong>de</strong>utig e<strong>in</strong>en Satz kennzeichnen muss und <strong>de</strong>shalb<br />
niemals leer se<strong>in</strong> darf. Doma<strong>in</strong>-Integrität me<strong>in</strong>t dagegen die E<strong>in</strong>schränkung von Spalten<br />
auf bestim<strong>mt</strong>e Wertebereiche, die Spalte Plz darf nur gültige Postleitzahlen enthalten.<br />
Tabellen wer<strong>de</strong>n nach <strong>de</strong>m Relationenmo<strong>de</strong>ll <strong><strong>de</strong>r</strong> E<strong>in</strong>fachheit halber nicht <strong>in</strong> Tabellenform<br />
geschrieben. Hierfür verwen<strong>de</strong>t man e<strong>in</strong>e e<strong>in</strong>fache Notation, die die Spalten <strong><strong>de</strong>r</strong><br />
Tabelle <strong>in</strong> Klammern aufführt. Primärschlüssel wer<strong>de</strong>n dabei unterstrichen und<br />
Fremdschlüssel kursiv dargestellt:<br />
Tabellenname (Attribut 1, Attribut 2, Attribut 3, ..., Attribut n)<br />
Fassen wir noch e<strong>in</strong>mal zusammen. E<strong>in</strong>e Tabelle besteht aus Spalten mit e<strong>in</strong><strong>de</strong>utigen<br />
Bezeichnern für die Spaltennamen. Die Spalten beschreiben Sätze <strong><strong>de</strong>r</strong> entsprechen<strong>de</strong>n<br />
Tabelle. So macht es z.B. ke<strong>in</strong>en S<strong>in</strong>n, dass die Tabelle Mitarbeiter e<strong>in</strong>e Spalte für die<br />
Bezeichnung <strong><strong>de</strong>r</strong> Spielstätte hat, da die Bezeichnung <strong><strong>de</strong>r</strong> Spielstätte nicht unmittelbar<br />
e<strong>in</strong> Merkmal e<strong>in</strong>es Mitarbeiters ist. Je<strong>de</strong> Spalte enthält gleichartige Werte, die e<strong>in</strong>em<br />
bestim<strong>mt</strong>en Wertebereich (Doma<strong>in</strong>) entsprechen. Beziehungen zwischen Tabellen wer<strong>de</strong>n<br />
über Primär- und Fremdschlüssel abgebil<strong>de</strong>t, <strong>in</strong><strong>de</strong>m <strong><strong>de</strong>r</strong> Primärschlüssel <strong><strong>de</strong>r</strong> e<strong>in</strong>en<br />
Tabelle als Fremdschlüssel <strong>in</strong> die an<strong><strong>de</strong>r</strong>e Tabellen übernommen wird. Hierdurch kann<br />
zwischen <strong>de</strong>n Tabellen navigiert wer<strong>de</strong>n.<br />
4.4 Umsetzung <strong>de</strong>s ERM <strong>in</strong> das<br />
Relationenmo<strong>de</strong>ll<br />
Im letzten Kapitel haben wir gesehen, dass e<strong>in</strong> konzeptionelles Datenbankmo<strong>de</strong>ll verschie<strong>de</strong>ne<br />
Elemente zur Abbildung <strong>de</strong>s Geschäftsumfel<strong>de</strong>s verwen<strong>de</strong>t. Wir haben<br />
sechs Elemente unterschie<strong>de</strong>n:<br />
73
1) Geschäftsobjekte,<br />
74<br />
4 Datenbankentwurf – Vom »Bauplan« zur Datenbankstruktur<br />
2) Attribute,<br />
3) E<strong>in</strong><strong>de</strong>utige I<strong>de</strong>ntifizierer (Schlüssel),<br />
4) Beziehungen,<br />
5) Beziehungstypen,<br />
6) Sub- bzw. Supertypen.<br />
Im Folgen<strong>de</strong>n gehen wir auf die Umsetzung <strong><strong>de</strong>r</strong> Elemente <strong>in</strong> das Relationenmo<strong>de</strong>ll e<strong>in</strong>.<br />
Betrachten wir im ersten Schritt Geschäftsobjekte und <strong><strong>de</strong>r</strong>en Attribute. Diese wer<strong>de</strong>n<br />
im Relationenmo<strong>de</strong>ll jeweils als eigenständige Tabelle behan<strong>de</strong>lt. Die Notation gibt vor,<br />
<strong>de</strong>n Tabellennamen zu schreiben und <strong>in</strong> Klammern folgen <strong>de</strong>ssen Attribute. Primärschlüssel<br />
wer<strong>de</strong>n hierbei unterstrichen dargestellt. Betrachten wir dazu exemplarisch<br />
das ERM nach Baker für die Geschäftsobjekte Spielstätte, Veranstaltung und Vorstellung.<br />
Die Umsetzung sieht dann wie folgt aus:<br />
Schritt 1:<br />
Veranstaltung<br />
� ��������������������<br />
� �����������<br />
� �����<br />
Vorstellung<br />
� ������������������<br />
� �����<br />
��������<br />
Spielstätte<br />
� ����<br />
� �������<br />
����<br />
����<br />
Veranstaltung (��������������������� ������������ ������<br />
����������� �������������������� ������ ��������<br />
����������� ������ �������� ���� ����<br />
Abbildung 4.3: Umwandlung ERM <strong>in</strong> Relationenmo<strong>de</strong>ll (Schritt 1)<br />
Im zweiten Schritt wer<strong>de</strong>n die Beziehungen zwischen <strong>de</strong>n Geschäftsobjekten abgebil<strong>de</strong>t.<br />
Hierbei betrachten wir <strong>de</strong>n jeweiligen Beziehungstyp, d.h. ob es sich um e<strong>in</strong>e 1:1-,<br />
e<strong>in</strong>e 1:N- o<strong><strong>de</strong>r</strong> e<strong>in</strong>e N:M-Beziehung han<strong>de</strong>lt. Da N:M-Beziehungen bereits im ERM<br />
bzw. UML-Mo<strong>de</strong>ll <strong>in</strong> 1:N-Beziehungen umgewan<strong>de</strong>lt wur<strong>de</strong>n (siehe 3.4.4), kann dieser<br />
Beziehungstyp nicht mehr vorkommen.<br />
Bei 1:N-Beziehungen wird <strong><strong>de</strong>r</strong> Primärschlüssel <strong><strong>de</strong>r</strong> 1er-Tabelle (Elterntabelle) als<br />
Fremdschlüssel <strong>in</strong> die N-er-Tabelle (K<strong>in</strong>dtabelle) übernommen. Für unser Beispiel mit<br />
<strong><strong>de</strong>r</strong> Spielstätte be<strong>de</strong>utet das also, dass <strong><strong>de</strong>r</strong> Primärschlüssel <strong><strong>de</strong>r</strong> Tabelle Spielstätte, nämlich<br />
Haus, als Fremdschlüssel <strong>in</strong> die Tabelle Vorstellung übernommen wird. Damit<br />
ergibt sich im zweiten Schritt folgen<strong>de</strong> Umsetzung, so dass zur Tabelle Vorstellung<br />
zwei Fremdschlüssel h<strong>in</strong>zukommen:
Umsetzung <strong>de</strong>s ERM <strong>in</strong> das Relationenmo<strong>de</strong>ll<br />
Schritt 2 (1:N-Beziehung):<br />
Veranstaltung<br />
� ��������������������<br />
� �����������<br />
� �����<br />
besteht<br />
aus<br />
basiert<br />
auf<br />
Vorstellung<br />
� ������������������<br />
� �����<br />
��������<br />
Spielstätte<br />
präsentiert � ����<br />
� �������<br />
f<strong>in</strong><strong>de</strong>t statt<br />
����<br />
����<br />
Veranstaltung (��������������������� ������������ ������<br />
����������� �������������������� ������ �������� ��������������������� �����<br />
����������� ������ �������� ���� ����<br />
Abbildung 4.4: Umwandlung ERM <strong>in</strong> Relationenmo<strong>de</strong>ll (Schritt 2)<br />
Bei 1:1-Beziehungen gibt es verschie<strong>de</strong>ne Möglichkeiten, diese Beziehung über Tabellen<br />
abzubil<strong>de</strong>n.<br />
Die e<strong>in</strong>fachste Möglichkeit besteht dar<strong>in</strong>, aus bei<strong>de</strong>n Geschäftsobjekten e<strong>in</strong>e e<strong>in</strong>zige<br />
Tabelle zu erstellen. Die an<strong><strong>de</strong>r</strong>e Alternative besteht dar<strong>in</strong>, e<strong>in</strong>e Tabelle pro Geschäftsobjekt<br />
zu erstellen und <strong>de</strong>n Primärschlüssel <strong><strong>de</strong>r</strong> e<strong>in</strong>en Tabelle als Fremdschlüssel <strong>in</strong> die<br />
an<strong><strong>de</strong>r</strong>e Tabelle zu übernehmen. Im Gegensatz zur 1:N-Beziehung ist es dabei egal, welcher<br />
Primärschlüssel als Fremdschlüssel fungiert. Betrachten wir hierzu die Geschäftsobjekte<br />
»Mitarbeiter« und »Ehepartner« , die <strong>in</strong> e<strong>in</strong>er 1:1-Beziehung zue<strong>in</strong>an<strong><strong>de</strong>r</strong> stehen.<br />
Drei Möglichkeiten stehen zur Umsetzung zur Auswahl.<br />
Schritt 2 (1:1-Beziehung):<br />
Mitarbeiter<br />
� ��������������<br />
�����<br />
� �������<br />
� �������<br />
����<br />
����<br />
verheiratet<br />
mit<br />
Ehepartner<br />
�����<br />
� �������<br />
von<br />
������<br />
1. Möglichkeit<br />
����������� ���������������� ����� ���� ���� ��������������� ������������������ ������<br />
�� Möglichkeit<br />
����������� ���������������� ����� ���� ����<br />
���������� ������ �������� ������ ���������������<br />
�� Möglichkeit<br />
����������� ���������������� ����� ���� ���� ��������������� ������������������<br />
���������� ������ �������� ������<br />
Abbildung 4.5: Umwandlung ERM <strong>in</strong> Relationenmo<strong>de</strong>ll (Schritt 2)<br />
75
76<br />
4 Datenbankentwurf – Vom »Bauplan« zur Datenbankstruktur<br />
Für welche <strong><strong>de</strong>r</strong> drei Möglichkeiten man sich entschei<strong>de</strong>t, hängt u.a. davon ab, wie oft<br />
z.B. diese Beziehung vorkom<strong>mt</strong>. Wür<strong>de</strong>n wir annehmen, dass Mitarbeiter so gut wie<br />
nie verheiratet s<strong>in</strong>d, so wür<strong>de</strong> man bei Anwendung <strong><strong>de</strong>r</strong> 1. Alternative viele nicht vorhan<strong>de</strong>ne<br />
Werte für NameEhepartner, VornameEhepartner und Alter haben. In diesem<br />
Fall wäre es s<strong>in</strong>nvoll, die 2. o<strong><strong>de</strong>r</strong> 3. Möglichkeit anzuwen<strong>de</strong>n.<br />
Im letzten Schritt <strong><strong>de</strong>r</strong> Umsetzung <strong>de</strong>s ERM <strong>in</strong> das Relationenmo<strong>de</strong>ll wer<strong>de</strong>n die Superbzw.<br />
Subtypen <strong>in</strong> Tabellen abgebil<strong>de</strong>t. Bei <strong><strong>de</strong>r</strong> Beziehung e<strong>in</strong>es Supertyps zu se<strong>in</strong>en<br />
Subtypen han<strong>de</strong>lt es sich um e<strong>in</strong>e 1:1-Beziehung. Im Gegensatz zu e<strong>in</strong>er normalen 1:1-<br />
Beziehung wird bei e<strong>in</strong>er Super-Subtypen-Beziehung jedoch <strong><strong>de</strong>r</strong> Primärschlüssel <strong>de</strong>s<br />
Supertyps als Fremdschlüssel <strong>in</strong> <strong>de</strong>n Subtypen übernommen. Betrachten wir hierzu die<br />
Geschäftsobjekte Artikel (Supertyp) mit se<strong>in</strong>en bei<strong>de</strong>n Subtypen Werbeartikel und Sitzplatz.<br />
E<strong>in</strong>e Umwandlung <strong>in</strong> Tabellen wür<strong>de</strong> <strong>de</strong>mnach wie folgt aussehen:<br />
Schritt 3:<br />
Artikel<br />
# Artikelnummer<br />
o Bezeichnung<br />
Werbeartikel<br />
o Beschreibung<br />
* Preis<br />
* Lagerbestand<br />
Sitzplatz<br />
# Bereich<br />
# Reihe<br />
# Sitz<br />
* Preis<br />
* Zustand<br />
Artikel (Artikelnummer, Bezeichnung)<br />
Werbeartikel (Beschreibung, Preis, Lagerbestand, Artikelnummer)<br />
Sitzplatz (Bereich, Reihe, Sitz, Preis, Zustand, Artikelnummer)<br />
Abbildung 4.6: Umwandlung ERM <strong>in</strong> Relationenmo<strong>de</strong>ll (Schritt 3)<br />
Der Sitzplatz erhält <strong>in</strong> diesem Fall also e<strong>in</strong>en neuen Primärschlüssel, da e<strong>in</strong> Sitzplatz<br />
e<strong>in</strong><strong>de</strong>utig nun auch über Artikelnummer i<strong>de</strong>ntifiziert wird. Da »Artikelnummer« als<br />
Primärschlüssel aus nur e<strong>in</strong>er Spalte besteht, muss diese Spalte als Primärschlüssel verwen<strong>de</strong>t<br />
wer<strong>de</strong>n (M<strong>in</strong>imalität von Schlüsseln). Wir sehen hier auch, dass e<strong>in</strong> Primärschlüssel<br />
<strong>in</strong>nerhalb e<strong>in</strong>er Tabelle zugleich Primär- als auch Fremdschlüssel se<strong>in</strong> kann.<br />
Rekursive Beziehungen, also Beziehungen, die sich auf das gleiche Geschäftsobjekt<br />
beziehen, wer<strong>de</strong>n genauso <strong>in</strong> Tabellen umgewan<strong>de</strong>lt, wie es oben beschrieben wur<strong>de</strong>.<br />
Der e<strong>in</strong>zige Unterschied besteht dar<strong>in</strong>, dass die Beziehung sich auf die gleiche Tabelle<br />
bezieht. Nehmen wir als Beispiel die rekursive Beziehung zwischen Mitarbeiter und<br />
Vorgesetztem. Da e<strong>in</strong> Vorgesetzter auch zur Tabelle »Mitarbeiter« gehört und es sich bei<br />
<strong><strong>de</strong>r</strong> Beziehung zwischen Vorgesetztem und Mitarbeiter um e<strong>in</strong>e 1:1-Beziehung han<strong>de</strong>lt,<br />
wird <strong><strong>de</strong>r</strong> Primärschlüssel <strong><strong>de</strong>r</strong> Mitarbeitertabelle als Fremdschlüssel für <strong>de</strong>n Vorgesetzten<br />
<strong>in</strong> die gleiche Tabelle übernommen. Das Ganze sieht dann wie folgt aus:
4.5 Fallbeispiel<br />
Fallbeispiel<br />
Abbildung 4.7: Umwandlung ERM <strong>in</strong> Relationenmo<strong>de</strong>ll (Schritt 4)<br />
Für unser Fallbeispiel ergibt sich folgen<strong>de</strong>s Relationenmo<strong>de</strong>ll:<br />
Relation<br />
Schritt 4 (Rekursive Beziehungen):<br />
Mitarbeiter<br />
# Personalnummer<br />
* Name<br />
* Vorname<br />
* Strasse<br />
* Plz<br />
* Ort<br />
ist Untegebener von<br />
ist Vorgesetzter von<br />
Mitarbeiter (Personalnummer, Name, ..., Ort, PersonalnummerVorgesetzter)<br />
Abteilung (Abteilungsbezeichnung, Abteilungsnummer, Abteilungsleiter)<br />
Mitarbeiter (Personalnummer, Name, Vorname, Strasse, Plz, Ort,<br />
Abteilungsbezeichnung, NameEhepartner, VornameEhepartner, Alter,<br />
PersonalnummerVorgesetzter)<br />
Kun<strong>de</strong> (Kun<strong>de</strong>nnummer, Name, Vorname, Strasse, Plz, Ort)<br />
Bestellung (Bestellnummer, Positionsnummer, Menge, Datum, Kun<strong>de</strong>nnummer,<br />
Personalnummer, Artikelnummer)<br />
Artikel (Artikelnummer, Bezeichnung)<br />
Werbeartikel (Beschreibung, Preis, Lagerbestand, Artikelnummer)<br />
Sitzplatz (Bereich, Reihe, Sitz, Preis, Zustand, Artikelnummer, Vorstellungsnummer)<br />
Veranstaltung (Veranstaltungsnummer, Bezeichnung, Autor)<br />
Vorstellung (Vorstellungsnummer, Datum, Uhrzeit, Veranstaltungsnummer, Haus)<br />
Spielstätte (Haus, Strasse, Plz, Ort)<br />
4.6 Zusammenfassung<br />
In diesem Kapitel haben wir kennen gelernt, wie man aus <strong>de</strong>m Fachkonzept (konzeptionelles<br />
Mo<strong>de</strong>ll) e<strong>in</strong> logisches Mo<strong>de</strong>ll erstellt, das auf e<strong>in</strong> beliebiges relationales Datenbank-Management-System<br />
(RDBMS) übertragen wer<strong>de</strong>n kann. Wir haben uns dabei<br />
mit <strong>de</strong>n Grundlagen <strong>de</strong>s Relationenmo<strong>de</strong>lls von E. F. Codd beschäftigt. Das Relationenmo<strong>de</strong>ll<br />
besticht durch se<strong>in</strong>e mathematische E<strong>in</strong>fachheit und bil<strong>de</strong>t die Grundlage heutiger<br />
relationaler Datenbank-Management-Systeme.<br />
77
78<br />
4 Datenbankentwurf – Vom »Bauplan« zur Datenbankstruktur<br />
Nach <strong><strong>de</strong>r</strong> Betrachtung <strong><strong>de</strong>r</strong> theoretischen Grundlagen <strong>de</strong>s Relationenmo<strong>de</strong>lls haben wir<br />
gesehen, wie man aus e<strong>in</strong>em ERM bzw. e<strong>in</strong>em UML-Mo<strong>de</strong>ll e<strong>in</strong> Relationenmo<strong>de</strong>ll<br />
erstellt. Zur Darstellung <strong><strong>de</strong>r</strong> Tabellen schreibt man <strong>de</strong>n Tabellennamen und <strong>in</strong> Klammern<br />
die dazugehörigen Attribute. Primärschlüssel wer<strong>de</strong>n unterstrichen, Fremdschlüssel<br />
kursiv dargestellt. Folgen<strong>de</strong> Vorgehensweise ergibt sich daraus:<br />
1) Je<strong>de</strong>s Geschäftsobjekt wird durch e<strong>in</strong>e Tabelle abgebil<strong>de</strong>t.<br />
2) Die Attribute <strong>de</strong>s Geschäftsobjektes stellen die Spalten <strong><strong>de</strong>r</strong> Tabelle dar.<br />
3) Bei e<strong>in</strong>er 1:1-Beziehung wer<strong>de</strong>n entwe<strong><strong>de</strong>r</strong> alle Attribute <strong><strong>de</strong>r</strong> e<strong>in</strong>en Tabelle <strong>in</strong> die an<strong><strong>de</strong>r</strong>e<br />
übertragen, so dass nur noch e<strong>in</strong>e Tabelle existiert. O<strong><strong>de</strong>r</strong> <strong><strong>de</strong>r</strong> Primärschlüssel<br />
e<strong>in</strong>er <strong><strong>de</strong>r</strong> bei<strong>de</strong>n Tabellen wird als Fremdschlüssel <strong>in</strong> die an<strong><strong>de</strong>r</strong>e Tabelle übernommen.<br />
4) Bei e<strong>in</strong>er 1:N-Beziehung wird <strong><strong>de</strong>r</strong> Primärschlüssel <strong><strong>de</strong>r</strong> 1er-Tabelle als Fremdschlüssel<br />
<strong>in</strong> die N-er-Tabelle übernommen.<br />
5) Bei e<strong>in</strong>er Super-Subtypen-Beziehung wird <strong><strong>de</strong>r</strong> Primärschlüssel <strong><strong>de</strong>r</strong> Supertypen-<br />
Tabelle als Fremdschlüssel <strong>in</strong> die Subtypen-Tabellen übertragen. In <strong><strong>de</strong>r</strong> Regel stellt<br />
<strong><strong>de</strong>r</strong> Fremdschlüssel <strong>de</strong>s Subtypen dann auch <strong>de</strong>n Primärschlüssel <strong>de</strong>s Subtypen dar.<br />
6) Rekursive Beziehungen wer<strong>de</strong>n genau so aufgelöst, wie <strong>in</strong> <strong>de</strong>n Punkten 3 und 4 beschrieben,<br />
mit <strong>de</strong>m e<strong>in</strong>zigen Unterschied, dass Fremdschlüssel und Primärschlüssel<br />
<strong>in</strong> <strong><strong>de</strong>r</strong> gleichen Tabelle vorkommen.<br />
Die Umwandlung e<strong>in</strong>es ERM o<strong><strong>de</strong>r</strong> e<strong>in</strong>es UML-Mo<strong>de</strong>lls <strong>in</strong> e<strong>in</strong> Relationenmo<strong>de</strong>ll ist<br />
ohne weiteres systematisch möglich, <strong>in</strong><strong>de</strong>m man genau die beschriebenen sechs<br />
Schritte durchläuft.<br />
Zur Erstellung von ERM o<strong><strong>de</strong>r</strong> auch UML-Mo<strong>de</strong>llen gibt es heutzutage Softwarewerkzeuge,<br />
die e<strong>in</strong>em zwar nicht unbed<strong>in</strong>gt die Arbeit <strong>de</strong>s Fachkonzeptes abnehmen, aber<br />
weitgehend die Transformation <strong>in</strong> das logische Mo<strong>de</strong>ll und auch <strong>in</strong> das physische<br />
Mo<strong>de</strong>ll. Zu <strong>de</strong>n bekanntesten gehören <strong><strong>de</strong>r</strong> »Oracle Designer« , »Rational Rose Professional<br />
Data Mo<strong>de</strong>ler« (UML), »Sybase PowerDesigner« , »Embarca<strong><strong>de</strong>r</strong>o ER/Studio« o<strong><strong>de</strong>r</strong><br />
»Computer Associates ERw<strong>in</strong>« . Sofern man e<strong>in</strong>es dieser Werkzeuge e<strong>in</strong>setzt, sollte man<br />
immer be<strong>de</strong>nken, dass die Software e<strong>in</strong>em nur systematische Arbeiten abnehmen<br />
kann. E<strong>in</strong> Fehler im konzeptionellen Mo<strong>de</strong>ll, also auf fachlicher Ebene, kann auch das<br />
beste Softwarewerkzeug nur sehr bed<strong>in</strong>gt erkennen.<br />
Wir haben bisher gesehen, wie man von <strong>de</strong>n fachlichen Anfor<strong><strong>de</strong>r</strong>ungen <strong>de</strong>s konzeptionellen<br />
Mo<strong>de</strong>lls zu e<strong>in</strong>em logischen Mo<strong>de</strong>ll, <strong>de</strong>m Relationenmo<strong>de</strong>ll, gelangt, das auf<br />
e<strong>in</strong>e beliebige Computerplattform mit e<strong>in</strong>em beliebigen RDBMS übertragen wer<strong>de</strong>n<br />
kann. Im nächsten Kapitel lernen wir, wie man das erstellte Relationenmo<strong>de</strong>ll noch e<strong>in</strong>mal<br />
auf Korrektheit, Konsistenz und Vermeidung redundanter Daten überprüft.
4.7 Aufgaben<br />
Aufgaben<br />
Wie<strong><strong>de</strong>r</strong>holungsfragen<br />
1) Welche Eigenschaften besitzt e<strong>in</strong> Primärschlüssel?<br />
2) Welche Eigenschaften besitzt e<strong>in</strong> Fremdschlüssel?<br />
3) Was versteht man unter e<strong>in</strong>em Tupel, e<strong>in</strong>er Relation und e<strong>in</strong>em Attribut?<br />
4) Was versteht man unter referentieller Integrität?<br />
5) Was versteht man unter Entity-Integrität?<br />
6) Was versteht man unter Doma<strong>in</strong>- bzw. Domänen-Integrität?<br />
7) Wie wird e<strong>in</strong> Geschäftsobjekt <strong>in</strong> das Relationenmo<strong>de</strong>ll umgesetzt?<br />
8) Wie wird e<strong>in</strong>e 1:1-, e<strong>in</strong>e 1:N- und e<strong>in</strong>e N:M-Beziehung <strong>in</strong> das Relationenmo<strong>de</strong>ll<br />
umgesetzt?<br />
Übungen<br />
1) Die Umwandlung e<strong>in</strong>er 1:N-Beziehung erfolgt, <strong>in</strong><strong>de</strong>m man <strong>de</strong>n Primärschlüssel <strong><strong>de</strong>r</strong><br />
1er-Tabelle als Fremdschlüssel <strong>in</strong> die N-er-Tabelle übernim<strong>mt</strong>. Wür<strong>de</strong> auch <strong><strong>de</strong>r</strong> umgekehrte<br />
Fall funktionieren, also <strong>de</strong>n Primärschlüssel <strong><strong>de</strong>r</strong> N-er-Tabelle <strong>in</strong> die 1er-<br />
Tabelle übernehmen? Begrün<strong>de</strong>n Sie Ihre Antwort anhand e<strong>in</strong>es Beispiels aus zwei<br />
Tabellen!<br />
2) Angenommen bei <strong><strong>de</strong>r</strong> Beziehung zwischen Mitarbeiter und Vorgesetztem wür<strong>de</strong> es<br />
sich um e<strong>in</strong>e 1:N-Beziehung han<strong>de</strong>ln, also je<strong><strong>de</strong>r</strong> Mitarbeiter kann nicht nur e<strong>in</strong>en,<br />
son<strong><strong>de</strong>r</strong>n mehrere Vorgesetzte haben. Wie wür<strong>de</strong> dann die Tabelle Mitarbeiter aussehen?<br />
3) Wan<strong>de</strong>ln Sie die Entity-Relationship-Mo<strong>de</strong>lle bzw. die UML-Mo<strong>de</strong>lle <strong><strong>de</strong>r</strong> Übungen<br />
2-9 aus Kapitel 3 <strong>in</strong> das Relationenmo<strong>de</strong>ll um!<br />
79
5 Normalisierung<br />
–<br />
Überprüfung <strong><strong>de</strong>r</strong><br />
Datenbankstruktur<br />
In Kapitel 5 sollen folgen<strong>de</strong> Fragen geklärt wer<strong>de</strong>n:<br />
� Wie kann man das Relationenmo<strong>de</strong>ll auf Vermeidung mehrfach gespeicherter<br />
Daten überprüfen?<br />
� Welche Abhängigkeiten existieren zwischen Attributen von Tabellen?<br />
� Was versteht man unter <strong>de</strong>m Begriff »Normalisierung«?<br />
5.1 Motivation<br />
Herr Dr. Fleissig hat <strong>in</strong>zwischen vollständig das ERM für die Firma »KartoF<strong>in</strong>ale« <strong>in</strong><br />
das Relationenmo<strong>de</strong>ll übertragen. Bei <strong><strong>de</strong>r</strong> Tabelle »Bestellung« ist er sich noch unsicher.<br />
Um sich über eventuelle Probleme klar zu wer<strong>de</strong>n, überlegt er sich Testdaten und<br />
zeichnet diese <strong>in</strong> Tabellenform auf. Zugunsten <strong><strong>de</strong>r</strong> Übersichtlichkeit lässt er die Spalten<br />
Personalnummer und Artikelnummer weg.<br />
Bestellnummer<br />
4711<br />
4711<br />
4711<br />
4711<br />
3001<br />
3001<br />
Positionsnummer<br />
1<br />
2<br />
3<br />
4<br />
1<br />
2<br />
Menge<br />
4<br />
2<br />
1<br />
1<br />
8<br />
7<br />
Datum<br />
29.09.2001<br />
29.09.2001<br />
29.09.2001<br />
29.09.2001<br />
06.01.2002<br />
06.01.2002<br />
Kun<strong>de</strong>nnummer<br />
11112<br />
11112<br />
11112<br />
11112<br />
12343<br />
12343<br />
Personalnummer<br />
4<br />
4<br />
4<br />
4<br />
5<br />
5<br />
Abbildung 5.1: Redundante Daten <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »Bestellung«<br />
Artikelnummer<br />
1002<br />
1021<br />
1022<br />
2008<br />
1021<br />
1232<br />
Dabei stellt er fest, dass für die Bestellung mit <strong><strong>de</strong>r</strong> Bestellnummer 4711 das Datum <strong><strong>de</strong>r</strong><br />
Bestellung mehrfach, also redundant, vorhan<strong>de</strong>n ist. Entsprechen<strong>de</strong>s gilt für die<br />
Bestellnummer selbst, die Kun<strong>de</strong>nnummer <strong>de</strong>s Kun<strong>de</strong>n, <strong><strong>de</strong>r</strong> die Bestellung aufgegeben<br />
hat und die Personalnummer <strong>de</strong>s Mitarbeiters, <strong><strong>de</strong>r</strong> die Bestellung entgegengenommen<br />
hat. Sche<strong>in</strong>bar ist Herrn Fleissig hier e<strong>in</strong> Fehler unterlaufen. Verunsichert holt er se<strong>in</strong>en<br />
neuen Kollegen Herrn Klever und bittet diesen um Rat. Herr Klever, <strong><strong>de</strong>r</strong> sich während<br />
se<strong>in</strong>es Studiums auf Mo<strong>de</strong>llierung von Geschäftsprozessen und <strong><strong>de</strong>r</strong>en Daten spezialisiert<br />
hat, erkennt sofort, dass hier zwei Geschäftsobjekte mite<strong>in</strong>an<strong><strong>de</strong>r</strong> vermischt wur<strong>de</strong>n.<br />
Er gibt Herrn Dr. Fleissig folgen<strong>de</strong>n Rat: »Entwe<strong><strong>de</strong>r</strong> mo<strong>de</strong>llierst du die Bestellung im<br />
ERM noch e<strong>in</strong>mal neu, da <strong><strong>de</strong>r</strong> Entitytyp »Bestellung« z.Z. aus zwei verschie<strong>de</strong>nen<br />
81
82<br />
5 Normalisierung – Überprüfung <strong><strong>de</strong>r</strong> Datenbankstruktur<br />
Entitytypen besteht. Du hast die Entitytypen »Bestellung« und »Bestellposten« mite<strong>in</strong>an<strong><strong>de</strong>r</strong><br />
vermischt. Entsprechend müsstest du dann auch das Relationenmo<strong>de</strong>ll noch<br />
e<strong>in</strong>mal än<strong><strong>de</strong>r</strong>n. Die an<strong><strong>de</strong>r</strong>e Möglichkeit besteht <strong>in</strong> <strong><strong>de</strong>r</strong> Anwendung <strong><strong>de</strong>r</strong> Normalformen.<br />
Hierbei untersucht man die Abhängigkeiten zwischen <strong>de</strong>n Nichtschlüssel-Attributen<br />
zum Primärschlüssel. Nehmen wir mal <strong>de</strong><strong>in</strong>e Tabelle. Als Primärschlüssel hast du<br />
Bestellnummer und Positionsnummer gewählt. Alle Nichtschlüssel-Attribute müssen<br />
nach <strong><strong>de</strong>r</strong> zweiten Normalform vom gesa<strong>mt</strong>en Primärschlüssel abhängig se<strong>in</strong>. Datum<br />
und Kun<strong>de</strong>nnummer s<strong>in</strong>d jedoch ausschließlich von <strong><strong>de</strong>r</strong> Bestellnummer direkt abhängig.«<br />
Im weiteren Gesprächsverlauf erklärt Herr Klever se<strong>in</strong>em Kollegen die E<strong>in</strong>schränkungen<br />
<strong><strong>de</strong>r</strong> ersten bis dritten Normalform. Herr Fleissig, erfreut darüber etwas neues<br />
gelernt zu haben, wen<strong>de</strong>t die Normalformen an und löst damit se<strong>in</strong> Problem.<br />
5.2 Grundlagen <strong><strong>de</strong>r</strong> Normalisierung<br />
Nach<strong>de</strong>m E. F. Codd die Grundlagen relationaler Datenbanken geschaffen hatte, hat er<br />
sich mit <strong><strong>de</strong>r</strong> Vermeidung redundanter Daten im Relationenmo<strong>de</strong>ll beschäftigt, <strong><strong>de</strong>r</strong> Normalisierung.<br />
Aus diesen Überlegungen heraus entstan<strong>de</strong>n Vorgaben für bestim<strong>mt</strong>e E<strong>in</strong>schränkungen<br />
auf Tabellen, die <strong>in</strong> <strong>de</strong>n so genannten Normalformen beschrieben s<strong>in</strong>d.<br />
Die Normalisierung ist also e<strong>in</strong>e Entwurfstechnik, die dazu dient, Tabellen auf mehrfach<br />
gespeicherte Daten (Redundanz), Konsistenz und Korrektheit zu überprüfen.<br />
Durch die Normalisierung teilt man Tabellen <strong>in</strong> weitere Tabellen auf, um redundante<br />
Daten zu vermei<strong>de</strong>n. Die Aufteilung muss dabei verlustfrei se<strong>in</strong>, d.h. e<strong>in</strong> späteres<br />
Zusammensetzen <strong><strong>de</strong>r</strong> geteilten Tabelle über Fremd- und Primärschlüssel muss wie<strong><strong>de</strong>r</strong><br />
zur ursprünglichen Tabelle führen, ohne dass dabei Informationen verloren gehen.<br />
Die Normalisierung wird <strong>in</strong> <strong><strong>de</strong>r</strong> Regel nach <strong>de</strong>m Erstellen <strong>de</strong>s Relationenmo<strong>de</strong>lls verwen<strong>de</strong>t,<br />
um dieses Mo<strong>de</strong>ll noch e<strong>in</strong>mal zu überprüfen.<br />
Die Normalisierung geht generell <strong>in</strong> zwei Schritten vor: Zunächst wer<strong>de</strong>n Wie<strong><strong>de</strong>r</strong>holgruppen<br />
entfernt und danach redundant gespeicherte Daten. Bevor wir uns im E<strong>in</strong>zelnen<br />
mit <strong>de</strong>n Normalformen ause<strong>in</strong>an<strong><strong>de</strong>r</strong>setzen, müssen wir die Begriffe <strong><strong>de</strong>r</strong> funktionalen<br />
und <strong><strong>de</strong>r</strong> vollen funktionalen Abhängigkeit verstehen.<br />
Zwischen Attributen e<strong>in</strong>es Objekttyps existieren Abhängigkeiten. Diese Abhängigkeiten<br />
basieren aus Beobachtungen <strong><strong>de</strong>r</strong> realen Welt. Betrachten wir zum Beispiel e<strong>in</strong>mal<br />
<strong>de</strong>n Objekttyp »Getränk« .<br />
Bezeichnung<br />
Getränk<br />
Kaffee<br />
Coca-Cola<br />
M<strong>in</strong>eralwasser<br />
Milch<br />
Farbe<br />
schwarz<br />
schwarz<br />
-<br />
weiss<br />
Abbildung 5.2: Funktionale Abhängigkeit von Attributen
Grundlagen <strong><strong>de</strong>r</strong> Normalisierung<br />
Zwischen <strong>de</strong>n bei<strong>de</strong>n Attributen »Bezeichnung« und »Farbe« <strong>de</strong>s Objekttyps<br />
»Getränk« existiert e<strong>in</strong>e Abhängigkeit <strong>in</strong> <strong><strong>de</strong>r</strong> Form, dass man auf Grund <strong><strong>de</strong>r</strong> Bezeichnung<br />
<strong>de</strong>s Getränks e<strong>in</strong><strong>de</strong>utig sagen kann, wie <strong><strong>de</strong>r</strong> Wert <strong>de</strong>s Attributes »Farbe« ist. So<br />
weiß man, dass e<strong>in</strong> Getränk mit <strong><strong>de</strong>r</strong> Bezeichnung »Kaffee« für das Attribut Farbe <strong>de</strong>n<br />
Wert »schwarz« haben muss. Umgekehrt ist diese Schlussfolgerung jedoch nicht möglich.<br />
Wenn man weiß, welche Farbe e<strong>in</strong> Getränks hat, kann man daraus nicht bestimmen,<br />
wie die Bezeichnung <strong>de</strong>s Getränks ist. Das Ganze ist für Sie natürlich schon e<strong>in</strong><br />
»alter Hut« , da wir dies bereits <strong>in</strong> an<strong><strong>de</strong>r</strong>er Form bei <strong><strong>de</strong>r</strong> Bestimmung von Schlüsseln<br />
kennen gelernt haben. Beim Objekttyp »Getränk« ist das Attribut »Bezeichnung« <strong><strong>de</strong>r</strong><br />
Primärschlüssel. Entsprechend bestim<strong>mt</strong> <strong><strong>de</strong>r</strong> Wert <strong>de</strong>s Primärschlüssels e<strong>in</strong><strong>de</strong>utig <strong>de</strong>n<br />
Wert <strong><strong>de</strong>r</strong> an<strong><strong>de</strong>r</strong>en Attribute, <strong>in</strong> diesem Fall <strong>de</strong>n Wert <strong>de</strong>s Attributes Farbe. E. F. Codd<br />
schreibt <strong>in</strong> diesem Zusammenhang <strong>in</strong> Anlehnung an die Mathematik von funktionaler<br />
Abhängigkeit, da e<strong>in</strong>e mathematische Funktion immer <strong>de</strong>n gleichen Ausgabewert bei<br />
gleichen E<strong>in</strong>gabewerten liefert.<br />
Die Funktion y = 2x liefert z.B. für <strong>de</strong>n Wert x = 3 immer <strong>de</strong>n Ausgabewert 6 für die<br />
Variable y. Für je<strong>de</strong> beliebige Zahl, die man für die Variable x e<strong>in</strong>setzt, ergibt sich also<br />
e<strong>in</strong> ganz bestim<strong>mt</strong>er Wert für y. Man kann sagen, dass <strong><strong>de</strong>r</strong> Wert y abhängig ist vom<br />
Wert x bzw. x bestim<strong>mt</strong> y. Mathematisch spricht man auch von Determ<strong>in</strong>ante und<br />
schreibt: x → y.<br />
Doch kommen wir nun zu unserem Getränke-Beispiel zurück. Zwischen <strong>de</strong>n Attributen<br />
»Bezeichnung« und »Farbe« besteht folgen<strong>de</strong> funktionale Abhängigkeit:<br />
Bezeichnung → Farbe<br />
Das Attribut Farbe ist also funktional abhängig vom Attribut »Bezeichnung« . Erweitern<br />
wir nun unser Beispiel um e<strong>in</strong> weiteres Attribut »Geschmack« . Als Primärschlüssel<br />
wollen wir diesmal die bei<strong>de</strong>n Attribute »Bezeichnung« und »Geschmack« festlegen.<br />
Betrachten wir nun wie<strong><strong>de</strong>r</strong> die funktionalen Abhängigkeiten, so stellen wir fest,<br />
dass das Attribut Farbe weiterh<strong>in</strong> funktional abhängig ist vom Primärschlüssel. Wenn<br />
die Bezeichnung und <strong><strong>de</strong>r</strong> Geschmack e<strong>in</strong>es Getränkes bekannt s<strong>in</strong>d, dann ergibt sich<br />
daraus e<strong>in</strong><strong>de</strong>utig die Farbe <strong>de</strong>s Getränks.<br />
Wir können also schreiben: Bezeichnung, Geschmack → Farbe<br />
Schauen wir uns nun die Abhängigkeiten zwischen Geschmack und Farbe an, so stellen<br />
wir fest, dass ke<strong>in</strong>e funktionale Abhängigkeit zwischen diesen bei<strong>de</strong>n Attributen existiert.<br />
Ist <strong><strong>de</strong>r</strong> Geschmack e<strong>in</strong>es Getränkes bekannt, so kann nicht e<strong>in</strong><strong>de</strong>utig auf die Farbe<br />
geschlossen wer<strong>de</strong>n. An<strong><strong>de</strong>r</strong>erseits gilt nach wie vor für die Attribute Bezeichnung und<br />
Farbe, dass aufgrund <strong><strong>de</strong>r</strong> Bezeichnung e<strong>in</strong><strong>de</strong>utig auf die Farbe geschlossen wer<strong>de</strong>n<br />
kann. In diesem Fall ist Farbe zwar funktional abhängig von <strong>de</strong>m zusammengesetzten<br />
Primärschlüssel Bezeichnung und Geschmack, auf das Attribut »Geschmack« kann<br />
jedoch verzichtet wer<strong>de</strong>n, um das Attribut »Farbe« e<strong>in</strong><strong>de</strong>utig zu bestimmen.<br />
Wir sprechen von voller funktionaler Abhängigkeit, wenn je<strong>de</strong>s Nichtschlüssel-Attribut<br />
durch <strong>de</strong>n gesa<strong>mt</strong>en Primärschlüssel e<strong>in</strong><strong>de</strong>utig bestim<strong>mt</strong> wer<strong>de</strong>n kann. In unserem<br />
Beispiel ist das nicht <strong><strong>de</strong>r</strong> Fall, da die Farbe auch dann e<strong>in</strong><strong>de</strong>utig bestim<strong>mt</strong> wer<strong>de</strong>n kann,<br />
wenn das Attribut »Geschmack« nicht bekannt ist. Sicherlich wer<strong>de</strong>n Sie bemerkt<br />
83
84<br />
5 Normalisierung – Überprüfung <strong><strong>de</strong>r</strong> Datenbankstruktur<br />
haben, dass volle funktionale Abhängigkeit unmittelbar <strong>in</strong> Zusammenhang mit <strong><strong>de</strong>r</strong><br />
For<strong><strong>de</strong>r</strong>ung nach e<strong>in</strong>em m<strong>in</strong>imalen Primärschlüssel steht, wie wir es <strong>in</strong> Kapitel 4 kennen<br />
gelernt haben.<br />
Bezeichnung<br />
Kaffee<br />
Coca-Cola<br />
M<strong>in</strong>eralwasser<br />
Milch<br />
Getränk<br />
Geschmack<br />
bitter<br />
süß<br />
neutral<br />
neutral<br />
Farbe<br />
schwarz<br />
schwarz<br />
-<br />
weiss<br />
Abbildung 5.3: Volle funktionale Abhängigkeit von Attributen<br />
Der letzte Begriff, <strong><strong>de</strong>r</strong> noch zu klären ist, ist die so genannte transitive Abhängigkeit.<br />
Betrachten wir hierzu wie<strong><strong>de</strong>r</strong> e<strong>in</strong> Beispiel: Für e<strong>in</strong>en Objekttyp »Fahrzeug« wur<strong>de</strong> als<br />
Primärschlüssel das Attribut »Bezeichnung« festgelegt.<br />
Bezeichnung<br />
Fahrzeug<br />
Typ<br />
VW Käfer PKW<br />
Hanomag II LKW<br />
Vespa Light Motorroller<br />
Suzuki GX Motorrad<br />
Ford Focus GL PKW<br />
Anzahl<br />
Rä<strong><strong>de</strong>r</strong><br />
4<br />
4<br />
2<br />
2<br />
4<br />
Abbildung 5.4: Transitive funktionale Abhängigkeit von Attributen<br />
Zunächst können wir erkennen, dass abhängig vom Primärschlüssel bestim<strong>mt</strong> wer<strong>de</strong>n<br />
kann, welchen Wert die an<strong><strong>de</strong>r</strong>en Attribute haben müssen. So bestim<strong>mt</strong> z.B. <strong><strong>de</strong>r</strong> Wert<br />
Vespa, dass es sich beim Fahrzeugtyp um e<strong>in</strong>en Motorroller han<strong>de</strong>lt, <strong><strong>de</strong>r</strong> 2 Rä<strong><strong>de</strong>r</strong> und 4<br />
PS haben muss. Da <strong><strong>de</strong>r</strong> Primärschlüssel aus nur e<strong>in</strong>em Attribut besteht, müssen <strong>de</strong>mnach<br />
auch alle Nichtschlüssel-Attribute voll funktional abhängig vom Primärschlüssel<br />
se<strong>in</strong>. Re<strong>in</strong> funktionale Abhängigkeit kann ja nur dann auftreten, wenn <strong><strong>de</strong>r</strong> Primärschlüssel<br />
aus zusammengesetzten Attributen besteht.<br />
Untersuchen wir die Tabelle auf eventuell an<strong><strong>de</strong>r</strong>e funktionale Abhängigkeiten, so<br />
erkennen wir, dass, wenn <strong><strong>de</strong>r</strong> Fahrzeugtyp bekannt ist, man daraus die Anzahl <strong><strong>de</strong>r</strong><br />
Rä<strong><strong>de</strong>r</strong> ableiten kann. Das Attribut »Anzahl Rä<strong><strong>de</strong>r</strong>« sche<strong>in</strong>t also voll funktional abhängig<br />
zu se<strong>in</strong> vom Fahrzeugtyp. Wir sprechen hier von e<strong>in</strong>er transitiven Abhängigkeit, da<br />
wir folgen<strong>de</strong> Schlussfolgerung ziehen können: Wenn e<strong>in</strong>e Vespa e<strong>in</strong> Motorroller ist und<br />
je<strong><strong>de</strong>r</strong> Motorroller zwei Rä<strong><strong>de</strong>r</strong> hat, dann hat auch die Vespa zwei Rä<strong><strong>de</strong>r</strong>. O<strong><strong>de</strong>r</strong> allgeme<strong>in</strong>er:<br />
Wenn A <strong>de</strong>n Wert von B bestim<strong>mt</strong> und B <strong>de</strong>n Wert von C bestim<strong>mt</strong>, dann bestim<strong>mt</strong><br />
auch A <strong>de</strong>n Wert von C.<br />
PS<br />
45<br />
220<br />
4<br />
8<br />
65
1. Normalform<br />
Fassen wir noch e<strong>in</strong>mal zusammen:<br />
1) E<strong>in</strong> Attribut A ist von e<strong>in</strong>em Attribut B funktional abhängig, wenn zu je<strong>de</strong>m Wert<br />
von B e<strong>in</strong><strong>de</strong>utig <strong><strong>de</strong>r</strong> Wert von A bestim<strong>mt</strong> wer<strong>de</strong>n kann.<br />
2) Von voller funktionaler Abhängigkeit spricht man, wenn e<strong>in</strong> Attribut A von e<strong>in</strong>er<br />
Attributkomb<strong>in</strong>ation B komplett funktional abhängig ist, und nicht nur von e<strong>in</strong>em<br />
Teil dieser Attributkomb<strong>in</strong>ation.<br />
3) Transitive Abhängigkeit zwischen zwei Attributen A und C liegt vor, wenn e<strong>in</strong> Attribut<br />
A von e<strong>in</strong>em Attribut B e<strong>in</strong><strong>de</strong>utig bestim<strong>mt</strong> wird, das Attribut B aber wie<strong><strong>de</strong>r</strong>um<br />
von e<strong>in</strong>em Attribut C e<strong>in</strong><strong>de</strong>utig bestim<strong>mt</strong> wird.<br />
Da wir soweit die Grundlagen <strong><strong>de</strong>r</strong> Normalisierung kennen gelernt haben, ist es jetzt<br />
relativ e<strong>in</strong>fach, die Normalformen zu verstehen und anzuwen<strong>de</strong>n. Bis 1978 wur<strong>de</strong>n<br />
von E. F. Codd drei Normalformen aufgestellt, die entsprechend als erste, zweite und<br />
dritte Normalform bezeichnet wer<strong>de</strong>n. Daneben gibt es noch vier weitere Normalformen,<br />
die jedoch <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>Praxis</strong> nicht so relevant s<strong>in</strong>d, da Probleme, die durch diese Normalformen<br />
beseitigt wer<strong>de</strong>n, nur selten vorkommen. Wir wollen <strong>de</strong>shalb im Folgen<strong>de</strong>n<br />
auf die ersten drei Normalformen e<strong>in</strong>gehen. Anschließend wird anhand e<strong>in</strong>es Beispiels<br />
<strong>de</strong>utlich, dass unter Umstän<strong>de</strong>n auch weitergehen<strong>de</strong> Normalformen be<strong>de</strong>utsam se<strong>in</strong><br />
können.<br />
5.3 1. Normalform<br />
Die erste Normalform legt fest, dass e<strong>in</strong>e Tabelle nur aus Attributen mit atomaren Werten<br />
bestehen und es ke<strong>in</strong>e Wie<strong><strong>de</strong>r</strong>holgruppen geben darf. Als Beispiel schauen wir uns<br />
die Tabelle Kun<strong>de</strong> aus unserem Fallbeispiel an. Die Tabelle wur<strong>de</strong> um die Namen und<br />
das Alter <strong><strong>de</strong>r</strong> K<strong>in</strong><strong><strong>de</strong>r</strong> erweitert. In <strong><strong>de</strong>r</strong> unnormalisierten Form <strong><strong>de</strong>r</strong> Tabelle stellt man<br />
fest, dass die Strasse aus zwei unterschiedlichen Werten besteht, nämlich <strong>de</strong>m Strassennamen<br />
und <strong><strong>de</strong>r</strong> Hausnummer. Das Attribut »Strasse« ist also nicht atomar und muss<br />
<strong>de</strong>mentsprechend <strong>in</strong> zwei Attribute aufgeteilt wer<strong>de</strong>n.<br />
Bei <strong>de</strong>m Attribut »K<strong>in</strong>d« erkennt man, dass im Kreuzungspunkt von Zeile und Spalte<br />
nicht e<strong>in</strong> Wert, son<strong><strong>de</strong>r</strong>n je nach Anzahl <strong><strong>de</strong>r</strong> K<strong>in</strong><strong><strong>de</strong>r</strong>, mehrere Werte gespeichert wer<strong>de</strong>n.<br />
Diese Wie<strong><strong>de</strong>r</strong>holgruppen elim<strong>in</strong>ieren wir, <strong>in</strong><strong>de</strong>m wir pro K<strong>in</strong>d e<strong>in</strong>e Zeile erstellen. Das<br />
Ganze sieht dann wie <strong>in</strong> Abbildung 5.5 aus.<br />
Wie Sie sicher bemerkt haben, führt die Anwendung <strong><strong>de</strong>r</strong> ersten Normalform zunächst<br />
zu mehrfach gespeicherten Daten bei Wie<strong><strong>de</strong>r</strong>holgruppen. So existieren z.B. für <strong>de</strong>n<br />
Kun<strong>de</strong>n »Bolte, Bertram« jetzt drei Zeilen, da er drei K<strong>in</strong><strong><strong>de</strong>r</strong> hat. Zu<strong>de</strong>m muss <strong><strong>de</strong>r</strong> Primärschlüssel<br />
neu <strong>de</strong>f<strong>in</strong>iert wer<strong>de</strong>n, da das Attribut »Kun<strong>de</strong>nnummer« alle<strong>in</strong>e nicht<br />
mehr ausreicht. Wir haben zur Zeit also durch Anwendung <strong><strong>de</strong>r</strong> ersten Normalform<br />
unser Resultat eher verschlechtert.<br />
Durch Anwendung <strong><strong>de</strong>r</strong> ersten Normalform erzeugt man also zunächst redundante<br />
Daten. Erst durch Anwendung <strong><strong>de</strong>r</strong> zweiten und dritten Normalform wer<strong>de</strong>n diese redundanten<br />
Daten wie<strong><strong>de</strong>r</strong> beseitigt. Das wollen wir uns jetzt ansehen.<br />
85
5.4 2. Normalform<br />
86<br />
Kun<strong>de</strong> (unnormalisiert)<br />
Kun<strong>de</strong>nnummer<br />
1<br />
2<br />
3<br />
Kun<strong>de</strong> (1. NF)<br />
5 Normalisierung – Überprüfung <strong><strong>de</strong>r</strong> Datenbankstruktur<br />
Name<br />
Bolte<br />
Muster<br />
Wiegerich<br />
Vorname<br />
Bertram<br />
Hans<br />
Frieda<br />
Strasse<br />
Busweg 12<br />
Musterweg 12<br />
Wan<strong><strong>de</strong>r</strong>str. 89<br />
Überführung <strong>in</strong> 1. Normalform<br />
Abbildung 5.5: Anwendung <strong><strong>de</strong>r</strong> 1. Normalform<br />
Die zweite Normalform bezieht sich ausschließlich auf Tabellen, <strong><strong>de</strong>r</strong>en Primärschlüssel<br />
aus mehreren Attributen zusammengesetzt ist. E<strong>in</strong>e Tabelle bef<strong>in</strong><strong>de</strong>t sich dann <strong>in</strong> <strong><strong>de</strong>r</strong><br />
zweiten Normalform, wenn alle Nichtschlüssel-Attribute nicht nur von e<strong>in</strong>em Teil,<br />
son<strong><strong>de</strong>r</strong>n vom gesa<strong>mt</strong>en Primärschlüssel voll funktional abhängig s<strong>in</strong>d.<br />
Nehmen wir dazu wie<strong><strong>de</strong>r</strong> unser Beispiel aus Abschnitt 5.3. Durch das H<strong>in</strong>zufügen <strong><strong>de</strong>r</strong><br />
Attribute für die K<strong>in</strong><strong><strong>de</strong>r</strong> <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n musste zunächst <strong><strong>de</strong>r</strong> Primärschlüssel neu <strong>de</strong>f<strong>in</strong>iert<br />
wer<strong>de</strong>n, da die Kun<strong>de</strong>nnummer alle<strong>in</strong>e nicht mehr e<strong>in</strong><strong>de</strong>utig alle an<strong><strong>de</strong>r</strong>en Attribute<br />
bestim<strong>mt</strong>. Als Primärschlüssel haben wir die Komb<strong>in</strong>ation aus <strong>de</strong>n Attributen<br />
Kun<strong>de</strong>nnummer und Name <strong>de</strong>s K<strong>in</strong><strong>de</strong>s gewählt.<br />
Wen<strong>de</strong>n wir jetzt die zweite Normalform auf diese Tabelle an, so erkennen wir, dass<br />
z.B. das Attribut Strasse zwar durch <strong>de</strong>n Primärschlüssel e<strong>in</strong><strong>de</strong>utig bestim<strong>mt</strong> wer<strong>de</strong>n<br />
kann, aber zur Bestimmung <strong><strong>de</strong>r</strong> Strasse nur e<strong>in</strong> Teil <strong>de</strong>s Primärschlüssels, das Attribut<br />
Kun<strong>de</strong>nnummer, ausreichen wür<strong>de</strong>. Das gleiche gilt für die Attribute »Name« , »Vorname«<br />
, »Plz« und »Ort« .<br />
Betrachten wir das letzte Attribut »Alter« , so stellen wir fest, dass dieses e<strong>in</strong><strong>de</strong>utig<br />
durch <strong>de</strong>n gesa<strong>mt</strong>en Primärschlüssel aus Kun<strong>de</strong>nnummer und Name <strong>de</strong>s K<strong>in</strong><strong>de</strong>s<br />
bestim<strong>mt</strong> wer<strong>de</strong>n kann. Nur e<strong>in</strong> Teil <strong>de</strong>s Primärschlüssels, Name <strong>de</strong>s K<strong>in</strong><strong>de</strong>s o<strong><strong>de</strong>r</strong> die<br />
Kun<strong>de</strong>nnummer, reicht <strong>in</strong> diesem Fall also nicht aus. Kennen wir die Kun<strong>de</strong>nnummer,<br />
so kommen z.B. für <strong>de</strong>n Kun<strong>de</strong>n 1 die Werte 5, 8, 12 <strong>in</strong> Betracht. Die Kun<strong>de</strong>nnummer<br />
alle<strong>in</strong>e ist also nicht e<strong>in</strong><strong>de</strong>utig. Kennen wir <strong>de</strong>n Namen e<strong>in</strong>es K<strong>in</strong><strong>de</strong>s, so gilt das gleiche.<br />
Für das Attribut »K<strong>in</strong>d« mit <strong>de</strong>m Wert »Katja« können wir zwar e<strong>in</strong><strong>de</strong>utig bestimmen,<br />
dass das Attribut »Alter« 5 ist. Für <strong>de</strong>n Wert »Ursula« ist dies jedoch nicht mög-<br />
Plz<br />
44444<br />
22222<br />
33333<br />
Ort<br />
Kohlscheidt<br />
Karlstadt<br />
Rettrich<br />
K<strong>in</strong>d<br />
Katja, Ursula, Karl<br />
Ursula, Enzo<br />
Kun<strong>de</strong>nnummer<br />
Name Vorname Strasse<br />
Hausnummer<br />
Plz Ort<br />
K<strong>in</strong>d<br />
1<br />
Bolte Bertram Busweg 12 44444 Kohlscheidt Katja<br />
1 Bolte Bertram Busweg 12 44444 Kohlscheidt Ursula<br />
1 Bolte Bertram Busweg 12 44444 Kohlscheidt Karl<br />
2<br />
Muster Hans Musterweg 12 22222 Karlstadt<br />
3 Wiegerich Frieda Wan<strong><strong>de</strong>r</strong>str. 89 33333 Rettrich<br />
Ursula<br />
3 Wiegerich Frieda Wan<strong><strong>de</strong>r</strong>str. 89 33333 Rettrich Enzo<br />
Kun<strong>de</strong> (Kun<strong>de</strong>nnummer, Name, Vorname, Strasse, Hausnummer, Plz, Ort, K<strong>in</strong>d, Alter)<br />
Alter<br />
5, 8, 12<br />
16, 9<br />
Alter<br />
5<br />
8<br />
12<br />
16<br />
9
3. Normalform<br />
lich, da <strong><strong>de</strong>r</strong> Name dieses K<strong>in</strong><strong>de</strong>s zweimal vorkom<strong>mt</strong>, e<strong>in</strong>mal für <strong>de</strong>n Kun<strong>de</strong>n mit <strong><strong>de</strong>r</strong><br />
Kun<strong>de</strong>nnummer 1 und für <strong>de</strong>n Kun<strong>de</strong>n mit <strong><strong>de</strong>r</strong> Kun<strong>de</strong>nnummer 3. Das Attribut<br />
»Alter« ist also voll funktional abhängig vom gesa<strong>mt</strong>en Primärschlüssel aus Kun<strong>de</strong>nnummer<br />
und Name <strong>de</strong>s K<strong>in</strong><strong>de</strong>s.<br />
Kun<strong>de</strong>nnummer<br />
1<br />
2<br />
3<br />
Kun<strong>de</strong> (1. NF)<br />
Kun<strong>de</strong>nnummer<br />
Name Vorname Strasse<br />
Hausnummer<br />
Plz Ort<br />
K<strong>in</strong>d<br />
1<br />
Bolte Bertram Busweg 12 44444 Kohlscheidt Katja<br />
1 Bolte Bertram Busweg 12 44444 Kohlscheidt Ursula<br />
1 Bolte Bertram Busweg 12 44444 Kohlscheidt Karl<br />
2<br />
Muster Hans Musterweg 12 22222 Karlstadt<br />
3 Wiegerich Frieda Wan<strong><strong>de</strong>r</strong>str. 89 33333 Rettrich<br />
Ursula<br />
3 Wiegerich Frieda Wan<strong><strong>de</strong>r</strong>str. 89 33333 Rettrich Enzo<br />
Name<br />
Bolte<br />
Muster<br />
Wiegerich<br />
Vorname<br />
Bertram<br />
Hans<br />
Frieda<br />
Strasse<br />
Busweg<br />
Musterweg<br />
Wan<strong><strong>de</strong>r</strong>str.<br />
Um <strong>de</strong>n E<strong>in</strong>schränkungen <strong><strong>de</strong>r</strong> zweiten Normalform gerecht zu wer<strong>de</strong>n, teilt man die<br />
Tabelle <strong>in</strong> zwei Tabellen auf. Die erste Tabelle erhält alle Attribute, die voll funktional<br />
abhängig s<strong>in</strong>d von Kun<strong>de</strong>nnummer, die zweite Tabelle erhält alle Attribute, die voll<br />
funktional abhängig s<strong>in</strong>d von Kun<strong>de</strong>nnummer und Name <strong>de</strong>s K<strong>in</strong><strong>de</strong>s.<br />
5.5 3. Normalform<br />
Überführung <strong>in</strong> 2. Normalform<br />
Kun<strong>de</strong> (2. NF) K<strong>in</strong>d (2. NF)<br />
Hausnummer<br />
12<br />
12<br />
89<br />
Kun<strong>de</strong> (Kun<strong>de</strong>nnummer, Name, Vorname, Strasse, Hausnummer, Plz, Ort)<br />
K<strong>in</strong>d (Kun<strong>de</strong>nnummer, K<strong>in</strong>d, Alter)<br />
Abbildung 5.6: Anwendung <strong><strong>de</strong>r</strong> 2. Normalform<br />
Die dritte Normalform bezieht sich auf funktionale Abhängigkeiten zwischen Nichtschlüssel-Attributen.<br />
E<strong>in</strong>e Tabelle bef<strong>in</strong><strong>de</strong>t sich dann <strong>in</strong> <strong><strong>de</strong>r</strong> dritten Normalform, wenn<br />
alle Nichtschlüssel-Attribute ausschließlich vom Primärschlüssel funktional abhängig<br />
s<strong>in</strong>d, und nicht transitiv über e<strong>in</strong> Nichtschlüssel-Attribut. Allerd<strong>in</strong>gs gibt es hierbei<br />
e<strong>in</strong>e Ausnahme, und zwar darf e<strong>in</strong> Nichtschlüssel-Attribut nach wie vor von e<strong>in</strong>em<br />
Schlüsselkandidaten abhängig se<strong>in</strong>.<br />
Betrachten wir dazu wie<strong><strong>de</strong>r</strong> unser Beispiel. Der Primärschlüssel <strong><strong>de</strong>r</strong> Kun<strong>de</strong>ntabelle ist<br />
die Kun<strong>de</strong>nnummer. Über die Kun<strong>de</strong>nnummer kann e<strong>in</strong><strong>de</strong>utig die Postleitzahl und<br />
<strong><strong>de</strong>r</strong> Ort e<strong>in</strong>es Kun<strong>de</strong>n bestim<strong>mt</strong> wer<strong>de</strong>n. An<strong><strong>de</strong>r</strong>erseits erkennen wir hier aber auch e<strong>in</strong>e<br />
funktionale Abhängigkeit zwischen <strong><strong>de</strong>r</strong> Postleitzahl und <strong>de</strong>m Ort. Ist die Postleitzahl<br />
e<strong>in</strong>es Kun<strong>de</strong>n bekannt, so kann e<strong>in</strong><strong>de</strong>utig auf <strong>de</strong>n Ortsnamen geschlossen wer<strong>de</strong>n. Der<br />
Ort ist also voll funktional abhängig von <strong>de</strong>m Attribut Plz. Wir haben es hier mit e<strong>in</strong>er<br />
transitiven Abhängigkeit zu tun, über die Kun<strong>de</strong>nnummer kann die Postleitzahl<br />
bestim<strong>mt</strong> wer<strong>de</strong>n und über die Postleitzahl <strong><strong>de</strong>r</strong> Ortsname. Das Attribut Plz ist also e<strong>in</strong><br />
Schlüssel für Ortsname.<br />
Plz<br />
44444<br />
22222<br />
33333<br />
Ort<br />
Kohlscheidt<br />
Karlstadt<br />
Rettrich<br />
Kun<strong>de</strong>nnummer<br />
1<br />
1<br />
1<br />
3<br />
3<br />
K<strong>in</strong>d<br />
Katja<br />
Ursula<br />
Karl<br />
Ursula<br />
Enzo<br />
Alter<br />
5<br />
8<br />
12<br />
16<br />
9<br />
Alter<br />
5<br />
8<br />
12<br />
16<br />
9<br />
87
88<br />
Kun<strong>de</strong> (2. NF)<br />
5 Normalisierung – Überprüfung <strong><strong>de</strong>r</strong> Datenbankstruktur<br />
Kun<strong>de</strong>nnummer<br />
Name Vorname Strasse<br />
Hausnummer<br />
Plz Ort<br />
1<br />
Bolte Bertram Busweg 12 44444 Kohlscheidt<br />
2<br />
Muster Hans Musterweg 12 22222 Karlstadt<br />
3 Wiegerich Frieda Wan<strong><strong>de</strong>r</strong>str. 89 33333 Rettrich<br />
4 Carlson Peter Petristr. 201 44444 Kohlscheidt<br />
Überführung <strong>in</strong> 2. Normalform<br />
Kun<strong>de</strong> (3. NF) Ort (3. NF)<br />
Kun<strong>de</strong>nnummer<br />
Name Vorname Strasse<br />
Hausnummer<br />
1<br />
Bolte Bertram Busweg 12<br />
2<br />
Muster Hans Musterweg 12<br />
3 Wiegerich Frieda Wan<strong><strong>de</strong>r</strong>str. 89<br />
4 Carlson Peter Petristr. 201<br />
Kun<strong>de</strong> (Kun<strong>de</strong>nnummer, Name, Vorname, Strasse, Hausnummer, Plz)<br />
Ort (Plz, Ort)<br />
Abbildung 5.7: Anwendung <strong><strong>de</strong>r</strong> 3. Normalform<br />
Um diese Abhängigkeit aufzulösen, teilt man die Tabelle wie<strong><strong>de</strong>r</strong>um <strong>in</strong> zwei Tabellen<br />
auf. Die erste Tabelle behält als Primärschlüssel die Kun<strong>de</strong>nnummer und entsprechend<br />
alle Attribute, die von diesem voll funktional, aber nicht transitiv abhängig s<strong>in</strong>d. Dies<br />
s<strong>in</strong>d also alle Attribute außer Ort. Die zweite Tabelle erhält als Primärschlüssel das<br />
Attribut Plz und als Nichtschlüssel-Attribut <strong>de</strong>n Ortsnamen.<br />
5.6 Weitere Normalformen<br />
Plz<br />
44444<br />
22222<br />
33333<br />
Ort<br />
Kohlscheidt<br />
Karlstadt<br />
Rettrich<br />
Die ersten drei Normalformen <strong>de</strong>cken <strong>in</strong> <strong><strong>de</strong>r</strong> Regel die häufigsten Probleme ab, die bei<br />
e<strong>in</strong>em Datenmo<strong>de</strong>ll auftreten können. Daher soll es an dieser Stelle genügen, nur die<br />
ersten drei Normalformen ausführlich zu erläutern und die weiteren Normalformen<br />
im Folgen<strong>de</strong>n kurz zu erwähnen.<br />
Als Ersatz für die dritte Normalform wird häufig die Boyce-Codd-Normalform angewen<strong>de</strong>t.<br />
Sie sieht vor, alle Determ<strong>in</strong>anten e<strong>in</strong>er Tabelle zu bestimmen und für je<strong>de</strong><br />
Determ<strong>in</strong>ante e<strong>in</strong>e Tabellen zu erstellen.<br />
Die vierte und die fünfte Normalform beschäftigen sich mit so genannten mehrwertigen<br />
Abhängigkeiten. Mehrwertige Abhängigkeiten treten nur auf, wenn <strong><strong>de</strong>r</strong> Primärschlüssel<br />
aus zwei o<strong><strong>de</strong>r</strong> mehr Attributen zusammengesetzt ist. Betrachten wir hierzu<br />
wie<strong><strong>de</strong>r</strong> unser Fallbeispiel. Angenommen, wir möchten zu je<strong>de</strong>m K<strong>in</strong>d e<strong>in</strong>es Kun<strong>de</strong>n<br />
<strong>de</strong>ssen Hobbies speichern, so könnten wir e<strong>in</strong> zusätzliches Attribut »Hobby« <strong><strong>de</strong>r</strong><br />
Tabelle »K<strong>in</strong>d« h<strong>in</strong>zufügen. Der Übersichtlichkeit halber wird das Attribut »Alter«<br />
weggelassen. Zur Erläuterung sehen wir uns diesen ersten Entwurf mit e<strong>in</strong>igen Beispieldaten<br />
an:<br />
Plz<br />
44444<br />
22222<br />
33333<br />
44444
Zusammenfassung<br />
Kun<strong>de</strong>nnummer<br />
K<strong>in</strong>d<br />
Hobby<br />
1<br />
Katja<br />
Tennis<br />
1<br />
Ursula<br />
Zeichnen<br />
1 Ursula<br />
Tennis<br />
1 Ursula<br />
Tanzen<br />
1<br />
Karl<br />
Fussball<br />
3<br />
Ursula<br />
Tennis<br />
3<br />
Enzo<br />
Handball<br />
Bisher bestand <strong><strong>de</strong>r</strong> Primärschlüssel aus Kun<strong>de</strong>nnummer und K<strong>in</strong>d. Durch das H<strong>in</strong>zufügen<br />
<strong><strong>de</strong>r</strong> Spalte »Hobby« muss <strong><strong>de</strong>r</strong> Primärschlüssel jedoch um dieses Attribut erweitert<br />
wer<strong>de</strong>n, um e<strong>in</strong><strong>de</strong>utig zu se<strong>in</strong>, da z.B. <strong><strong>de</strong>r</strong> Wert »Ursula« <strong>de</strong>s Kun<strong>de</strong>n mit <strong><strong>de</strong>r</strong> Kun<strong>de</strong>nnummer<br />
1 dreimal auftritt. Obwohl die Tabelle <strong>in</strong> <strong><strong>de</strong>r</strong> dritten Normalform ist,<br />
erkennen wir redundante Daten, so wird z.B. Ursula mit <strong><strong>de</strong>r</strong> Kun<strong>de</strong>nnummer 1 dreimal<br />
gespeichert.<br />
Da Probleme dieser Art nur bei zusammengesetzten Primärschlüsseln auftreten, s<strong>in</strong>d<br />
sie sehr selten. In <strong><strong>de</strong>r</strong> Regel versucht man e<strong>in</strong>en Primärschlüssel auf e<strong>in</strong>, höchstens<br />
zwei Attribute zu beschränken. Auf Lösungen solcher Probleme wollen wir hier <strong>de</strong>shalb<br />
nicht weiter e<strong>in</strong>gehen.<br />
Schließlich gibt es noch die »Doma<strong>in</strong>-Key-Normalform« (DKNF), die e<strong>in</strong>en etwas<br />
an<strong><strong>de</strong>r</strong>en Weg beschreitet, <strong>in</strong><strong>de</strong>m sie Tabellen auf die Anwendung e<strong>in</strong>es bestim<strong>mt</strong>en<br />
Themas (»S<strong>in</strong>gle-Theme« ) untersucht.<br />
5.7 Zusammenfassung<br />
Abbildung 5.8: Mehrwertige Abhängigkeiten<br />
In diesem Kapitel haben wir gesehen, wie man e<strong>in</strong> vorher erstelltes Relationenmo<strong>de</strong>ll<br />
noch e<strong>in</strong>mal auf logische Korrektheit überprüfen kann. Ziel <strong><strong>de</strong>r</strong> Normalisierung ist<br />
dabei die Vermeidung redundanter Daten. Dabei haben wir drei Normalformen kennen<br />
gelernt, die man nache<strong>in</strong>an<strong><strong>de</strong>r</strong> auf Tabellen anwen<strong>de</strong>n sollte, um diese zu überprüfen.<br />
Folgen<strong>de</strong> Schritte s<strong>in</strong>d zur Erfüllung <strong><strong>de</strong>r</strong> drei Normalformen durchzuführen:<br />
1) Normalform<br />
- Attribute mit mehreren Werten, z.B. Adresse, <strong>in</strong> atomare Attribute aufspalten;<br />
- Wie<strong><strong>de</strong>r</strong>holgruppen, z.B. K<strong>in</strong><strong><strong>de</strong>r</strong> <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n, <strong>in</strong> mehrere Zeilen aufteilen.<br />
2) Normalform<br />
- Überprüfen <strong><strong>de</strong>r</strong> vollen funktionalen Abhängigkeit <strong><strong>de</strong>r</strong> Nichtschlüssel-Attribute<br />
zum Primärschlüssel;<br />
89
90<br />
5 Normalisierung – Überprüfung <strong><strong>de</strong>r</strong> Datenbankstruktur<br />
- Gegebenenfalls Aufteilen <strong><strong>de</strong>r</strong> Tabelle nach <strong><strong>de</strong>r</strong>en voller funktionaler Abhängigkeit<br />
(nur bei zusammengesetzten Primärschlüsseln notwendig).<br />
3) Normalform<br />
- Überprüfen von transitiven Abhängigkeiten <strong>de</strong>s Primärschlüssels zu <strong>de</strong>n Nichtschlüssel-Attributen<br />
(Ausnahme: Funktionale Abhängigkeit von e<strong>in</strong>em Schlüsselkandidaten);<br />
- Gegebenfalls Aufteilen <strong><strong>de</strong>r</strong> Tabelle, so dass transitiv abhängige Attribute mit ihrem<br />
funktional abhängigen Attribut e<strong>in</strong>e eigene Tabelle bil<strong>de</strong>n und transitiv abhängiges<br />
Attribut <strong>in</strong> Orig<strong>in</strong>altabelle erhalten bleibt.<br />
Generell gilt, dass e<strong>in</strong> »sauber« mo<strong>de</strong>lliertes ERM bzw. UML-Mo<strong>de</strong>ll bereits <strong>in</strong> e<strong>in</strong> redundanzfreies<br />
Relationenmo<strong>de</strong>ll überführt wird.<br />
Dennoch sollte die Normalisierung <strong>in</strong> drei Fällen angewen<strong>de</strong>t wer<strong>de</strong>n. Zum e<strong>in</strong>en zur<br />
nachträglichen Überprüfung von Tabellen, bei <strong>de</strong>nen man Unstimmigkeiten vermutet,<br />
wie <strong>in</strong> unserem Fallbeispiel. Zum an<strong><strong>de</strong>r</strong>en zur Überprüfung, wenn nachträglich Attribute<br />
zur Datenbank h<strong>in</strong>zugefügt wer<strong>de</strong>n sollen. Und schließlich um e<strong>in</strong>e bereits vorhan<strong>de</strong>ne<br />
relationale Datenbankstruktur nachträglich zu normalisieren. Häufig wer<strong>de</strong>n<br />
<strong>in</strong> Firmen relationale Datenbanken erstellt, ohne vorab e<strong>in</strong> konzeptionelles und logisches<br />
Mo<strong>de</strong>ll zu entwerfen. In diesem Fall eignet sich die Normalisierung als nachträgliche<br />
Designtechnik, um das Datenmo<strong>de</strong>ll redundanzfrei zu entwerfen.<br />
Weitere Normalformen<br />
1. NF<br />
�������<br />
����� ����������������<br />
Normalisierung<br />
3. NF<br />
3. NF<br />
������� ������������ ���<br />
������� ������������ ���<br />
���������������<br />
���������������<br />
2. NF<br />
������������ ���<br />
��������<br />
���������������<br />
Abbildung 5.9: Zusammenfassung »Normalformen«<br />
Wir s<strong>in</strong>d jetzt soweit mit <strong>de</strong>m Entwurf unserer Datenbankstruktur fortgeschritten, dass<br />
diese im nächsten Kapitel physisch umgesetzt wer<strong>de</strong>n kann. Da wir <strong>in</strong> <strong>de</strong>n folgen<strong>de</strong>n
Zusammenfassung<br />
Kapiteln immer wie<strong><strong>de</strong>r</strong> auf dieses Datenmo<strong>de</strong>ll zurückkommen, soll <strong>de</strong>shalb hier noch<br />
e<strong>in</strong>mal das endgültige ERM unseres Fallbeispiels und das dazugehörige Relationenmo<strong>de</strong>ll<br />
dargestellt wer<strong>de</strong>n.<br />
besteht<br />
Abteilung aus<br />
� ���������������������<br />
� ����������������<br />
� ����������������<br />
Kun<strong>de</strong><br />
� ������������<br />
� ����<br />
� �������<br />
� �������<br />
� ����������<br />
� ����������<br />
� ������������<br />
gibt<br />
auf<br />
gehört<br />
zu<br />
Bestellung<br />
� �������������<br />
� �����<br />
gehört<br />
zu<br />
ist auf<br />
besteht<br />
aus<br />
Bestellposten<br />
� ���������������<br />
� �����<br />
enthält<br />
Artikel<br />
� �������������<br />
� �����������<br />
Werbeartikel<br />
� ������������<br />
� �����<br />
� ������������<br />
Sitzplatz<br />
� �������<br />
� �����<br />
� ����<br />
� �����<br />
� �������<br />
hat<br />
ist für<br />
ist Untegebener von<br />
von<br />
wird<br />
bearbeitet<br />
von<br />
Mitarbeiter<br />
� ��������������<br />
gehört � ����<br />
zu � �������<br />
� �������<br />
� ����������<br />
� ����������<br />
K<strong>in</strong>d<br />
� �������<br />
� ������������<br />
� ����������<br />
ist<br />
Vorgesetzter<br />
von<br />
Veranstaltung<br />
� ��������������������<br />
� �����������<br />
� �����<br />
� ������������<br />
besteht<br />
aus<br />
basiert<br />
auf<br />
Vorstellung<br />
� ������������������<br />
� �����<br />
� �������<br />
verheiratet<br />
mit<br />
bearbeitet<br />
Abbildung 5.10: Das endgültige ERM <strong>de</strong>s Fallbeispiels<br />
von<br />
Ehepartner<br />
� ����<br />
� �������<br />
� ������������<br />
� ����������<br />
Ort<br />
� ���<br />
� ��������<br />
Spielstätte<br />
präsentiert<br />
� ����<br />
� �������<br />
f<strong>in</strong><strong>de</strong>t statt<br />
� ����������<br />
� ������������<br />
91
92<br />
5 Normalisierung – Überprüfung <strong><strong>de</strong>r</strong> Datenbankstruktur<br />
Entsprechend sieht das Relationenmo<strong>de</strong>ll wie folgt aus:<br />
Relation<br />
Abteilung (Abteilungsbezeichnung, Abteilungsnummer, PersonalnummerAbteilungsleiter)<br />
Mitarbeiter (Personalnummer, Name, Vorname, Geschlecht, Strasse, Hausnummer, Plz,<br />
Abteilungsbezeichnung, NameEhepartner, VornameEhepartner, Geburtsdatum<br />
Ehepartner, GeschlechtEhepartner, Gehalt, PersonalnummerVorgesetzter)<br />
Kun<strong>de</strong> (Kun<strong>de</strong>nnummer, Name, Vorname, Geschlecht, Strasse, Hausnummer, Plz,<br />
Geburtsdatum)<br />
Bestellung (Bestellnummer, Datum, Kun<strong>de</strong>nnummer, Personalnummer)<br />
Bestellposten<br />
(Positionsnummer, Bestellnummer, Menge, Artikelnummer)<br />
Artikel (Artikelnummer, Bezeichnung)<br />
Werbeartikel (Beschreibung, Preis, Lagerbestand, Artikelnummer)<br />
Sitzplatz (Bereich, Reihe, Sitz, Preis, Zustand, Artikelnummer, Vorstellungsnummer)<br />
Veranstaltung<br />
(Veranstaltungsnummer, Bezeichnung, Autor, Beschreibung)<br />
Vorstellung (Vorstellungsnummer, Datum, Uhrzeit, Veranstaltungsnummer, Haus)<br />
Spielstätte (Haus, Strasse, Hausnummer, Beschreibung, Plz)<br />
Ort (Plz, Ort)<br />
K<strong>in</strong>d (Vorname, Geburtsdatum, Geschlecht, Kun<strong>de</strong>nnummer)<br />
5.8 Aufgaben<br />
Tabelle 5.1: Relationenmo<strong>de</strong>ll<br />
Wie<strong><strong>de</strong>r</strong>holungsfragen<br />
1) Wozu dient die Normalisierung?<br />
2) Def<strong>in</strong>ieren Sie die erste, zweite und dritte Normalform!<br />
3) Wor<strong>in</strong> besteht <strong><strong>de</strong>r</strong> Unterschied zwischen funktionaler und voll funktionaler Abhängigkeit?<br />
4) In Abschnitt 5.3 wur<strong>de</strong> das Attribut »Alter« für die K<strong>in</strong><strong><strong>de</strong>r</strong> e<strong>in</strong>es Kun<strong>de</strong>n e<strong>in</strong>geführt.<br />
Dies ist als problematisch zu betrachten. Warum?
Aufgaben<br />
Übungen<br />
1) Wen<strong>de</strong>n Sie auf folgen<strong>de</strong> Tabelle die ersten drei Normalformen an!<br />
Hersteller<br />
VW<br />
Hanomag<br />
Vespa<br />
Suzuki<br />
Ford<br />
Mo<strong>de</strong>ll<br />
Käfer<br />
II<br />
Vespa Light<br />
GX<br />
Fahrzeug<br />
Typ<br />
PKW<br />
LKW<br />
Motorroller<br />
Motorrad<br />
Focus PKW<br />
Anzahl<br />
Rä<strong><strong>de</strong>r</strong><br />
VW Golf PKW 4 72<br />
VW Golf PKW 4 72 Volkswagenstr. 10, 34444Wolfsburg Deutschland Ja<br />
Abbildung 5.11: Tabelle Fahrzeug<br />
2) Im ERM-Entwurf unseres Fallbeispiels wur<strong>de</strong> die Tabelle »Bestellung« im Relationenmo<strong>de</strong>ll<br />
folgen<strong><strong>de</strong>r</strong>maßen entworfen:<br />
Bestellung (Bestellnummer, Positionsnummer, Menge, Datum, Kun<strong>de</strong>nnummer,<br />
Personalnummer, Artikelnummer)<br />
Wen<strong>de</strong>n Sie die ersten drei Normalformen auf die Tabelle Bestellung an!<br />
3) Wen<strong>de</strong>n Sie auf folgen<strong>de</strong> Tabelle die ersten drei Normalformen an!<br />
Materialnummer<br />
101<br />
221<br />
101<br />
134<br />
002<br />
007<br />
Materialbezeichnung<br />
CD-Rohl<strong>in</strong>g<br />
Kugelschreiber<br />
CD-Rohl<strong>in</strong>g<br />
Papier A4<br />
Toner schwarz<br />
Heftzwecken<br />
Abbildung 5.12: Tabelle Büromaterial<br />
4) Wen<strong>de</strong>n Sie auf folgen<strong>de</strong> Tabelle die ersten drei Normalformen an!<br />
4<br />
4<br />
2<br />
2<br />
4<br />
PS<br />
45<br />
220<br />
4<br />
8<br />
65<br />
Büromaterial<br />
Lieferantennummer<br />
2<br />
2<br />
31<br />
2<br />
31<br />
26<br />
Adresse<br />
Volkswagenstr. 10, 34444Wolfsburg<br />
Musterstr. 1, 22222 Hamburg<br />
La Strada 2, 122 Rom<br />
Koniciva 3, Yokohama<br />
Fritzweg 2, 54455 Köln<br />
Volkswagenstr. 10, 34444Wolfsburg<br />
Abbildung 5.13: Tabelle Fußballvere<strong>in</strong><br />
Land<br />
Deutschland<br />
Deutschland<br />
Italien<br />
Japan<br />
Deutschland<br />
Deutschland<br />
Klimaanlage<br />
Ja<br />
Ne<strong>in</strong><br />
Ne<strong>in</strong><br />
Ne<strong>in</strong><br />
Ja<br />
Ne<strong>in</strong><br />
Preis<br />
1.99<br />
0.99<br />
1.89<br />
8.99<br />
39.50<br />
026 Schnellhefter 2 InnoPaper<br />
81 0.89<br />
Vere<strong>in</strong>sbezeichnung<br />
1. FC Muster<br />
E<strong>in</strong>tracht Fritz<br />
1. FC Muster<br />
1. FC Muster<br />
Hehner SV<br />
Hehner SV<br />
Hehner SV<br />
Gründungsjahr<br />
1921<br />
1949<br />
1921<br />
1921<br />
1971<br />
1971<br />
1971<br />
Lieferantenbezeichnung<br />
InnoPaper<br />
InnoPaper<br />
Computer-Men<strong>de</strong>l<br />
InnoPaper<br />
Computer-Men<strong>de</strong>l<br />
Muster-Büroartikel<br />
Fußballvere<strong>in</strong><br />
Spielernummer<br />
2<br />
11<br />
7<br />
11<br />
2<br />
3<br />
Spieler-<br />
Name<br />
Karl Be<strong>in</strong><br />
Fritz Wurf<br />
Hans Mehnel<br />
Kurt Bebel<br />
Franz Be<strong>in</strong><br />
1 Franz Be<strong>in</strong><br />
Lagerbestand<br />
61<br />
156<br />
61<br />
702<br />
8<br />
81<br />
Hubertus Kle<strong>in</strong><br />
0.79<br />
Geburtsdatum<br />
1980-09-02<br />
1979-02-23<br />
1986-12-31<br />
1975-06-16<br />
1971-11-30<br />
1983-08-09<br />
1982-06-26<br />
93
94<br />
5 Normalisierung – Überprüfung <strong><strong>de</strong>r</strong> Datenbankstruktur<br />
5) Die folgen<strong>de</strong> Tabelle enthält Daten zu Projekten. Aufgeführt s<strong>in</strong>d Projekte und die<br />
erfor<strong><strong>de</strong>r</strong>lichen Sprachkenntnisse, sowie die Mitarbeiter, die über die entsprechen<strong>de</strong>n<br />
Sprachkenntnisse verfügen. Als Primärschlüssel ist ausschließlich e<strong>in</strong>e Komb<strong>in</strong>ation<br />
aller drei Attribute möglich. Damit erfüllt die Tabelle die 3. Normalform.<br />
Dennoch s<strong>in</strong>d redundante Daten vorhan<strong>de</strong>n, da mehrwertige Abhängigkeiten vorkommen.<br />
Wie kann dieses Problem behoben wer<strong>de</strong>n?<br />
Personalnummer<br />
1<br />
1<br />
1<br />
2<br />
2<br />
3<br />
3<br />
Projektzuordnung<br />
Projektnummer<br />
1<br />
1<br />
6<br />
1<br />
6<br />
1<br />
2<br />
Sprachkenntnisse<br />
Deutsch<br />
Englisch<br />
Englisch<br />
Englisch<br />
Franzosisch<br />
Englisch<br />
Spanisch<br />
Abbildung 5.14: Tabelle Projektzuordnung
6 SQL<br />
– Anlegen <strong><strong>de</strong>r</strong><br />
Datenbankstruktur<br />
In Kapitel 6 sollen folgen<strong>de</strong> Fragen geklärt wer<strong>de</strong>n:<br />
� Wie kann man die Struktur <strong>de</strong>s erstellten Relationenmo<strong>de</strong>lls auf e<strong>in</strong> relationales<br />
Datenbank-Management-System (RDBMS) übertragen?<br />
� Was ist SQL?<br />
� Was s<strong>in</strong>d Datentypen?<br />
� Wie speichert man Werte von Attributen, die man nicht kennt?<br />
� Mit welchen Anweisungen <strong><strong>de</strong>r</strong> Sprache SQL erstellt man die Datenbankstruktur?<br />
� Mit welchen Anweisungen <strong><strong>de</strong>r</strong> Sprache SQL kann man e<strong>in</strong>e bestehen<strong>de</strong> Datenbankstruktur<br />
wie<strong><strong>de</strong>r</strong> än<strong><strong>de</strong>r</strong>n?<br />
6.1 Motivation<br />
Herr Dr. Fleissig hat se<strong>in</strong> Relationenmo<strong>de</strong>ll nun soweit fertig, dass er es auf <strong>de</strong>n Computer<br />
übertragen kann. Für e<strong>in</strong>en ersten Test hat er sich die Datenbank-Management-Systemsoftware<br />
DB2 von <strong><strong>de</strong>r</strong> Firma IBM aus <strong>de</strong>m Internet heruntergela<strong>de</strong>n und <strong>in</strong>stalliert.<br />
Nach<strong>de</strong>m er sich mit <strong>de</strong>m Produkt vertraut gemacht hat, startet er das dazugehörige<br />
Programm »Command Center«. Mit Hilfe dieses Programms kann er Befehle <strong>in</strong> <strong><strong>de</strong>r</strong><br />
Sprache SQL e<strong>in</strong>geben, um zunächst physikalisch e<strong>in</strong>e leere Datenbank zu erzeugen.<br />
Danach gibt er entsprechen<strong>de</strong> SQL-Anweisungen e<strong>in</strong>, um die Strukturen <strong><strong>de</strong>r</strong> Tabellen<br />
und <strong><strong>de</strong>r</strong>en Beziehungen <strong>in</strong> <strong><strong>de</strong>r</strong> Datenbank abzubil<strong>de</strong>n.<br />
6.2 Grundlagen<br />
In <strong>de</strong>n letzten bei<strong>de</strong>n Kapiteln haben wir e<strong>in</strong>en Teil <strong><strong>de</strong>r</strong> theoretischen Grundlagen <strong>de</strong>s<br />
Relationenmo<strong>de</strong>lls kennen gelernt, auf <strong>de</strong>m relationale Datenbank-Management-Systeme<br />
(RDBMS) basieren. E<strong>in</strong> RDBMS speichert die Datenbankstruktur <strong>in</strong> Form von<br />
Tabellen. Je<strong>de</strong> Tabelle besteht aus Zeilen und Spalten, <strong>in</strong> <strong>de</strong>nen die Werte e<strong>in</strong>zelner<br />
Objekte gespeichert wer<strong>de</strong>n.<br />
Da durch e<strong>in</strong> RDBMS <strong>in</strong> <strong><strong>de</strong>r</strong> Regel mehrere tausend dieser Tabellen gespeichert wer<strong>de</strong>n,<br />
ist es s<strong>in</strong>nvoll, die Tabellen wie<strong><strong>de</strong>r</strong>um <strong>in</strong> e<strong>in</strong>e bestim<strong>mt</strong>e Hierarchie zu glie<strong><strong>de</strong>r</strong>n.<br />
Zur Übersicht verwen<strong>de</strong>t e<strong>in</strong>e RDBMS als oberste Hierarchiestufe die Kategorie. E<strong>in</strong>e<br />
Kategorie wie<strong><strong>de</strong>r</strong>um kann verschie<strong>de</strong>ne Datenbank-Schemata speichern und e<strong>in</strong><br />
Datenbank-Schema be<strong>in</strong>haltet letztendlich die Tabellen mit <strong>de</strong>n Spalten selbst.<br />
95
96<br />
Kartenverkauf<br />
Kategorie<br />
Schema<br />
Rechnungswesen<br />
Schema<br />
6 SQL – Anlegen <strong><strong>de</strong>r</strong> Datenbankstruktur<br />
Schema<br />
Vertrieb<br />
RDBMS<br />
Personal<br />
Kategorie<br />
Abbildung 6.1: Hierarchische Struktur e<strong>in</strong>er relationalen Datenbank<br />
Diese Struktur dient ausschließlich <strong><strong>de</strong>r</strong> Übersicht, um nicht alle Tabellen e<strong>in</strong>es RDBMS<br />
auf e<strong>in</strong>er Hierarchiestufe speichern zu müssen.<br />
Um nun Tabellenstrukturen <strong>in</strong> e<strong>in</strong>er Datenbank anzulegen, verwen<strong>de</strong>t man e<strong>in</strong>e Datenbanksprache.<br />
Über diese Datenbanksprache kann man mit <strong>de</strong>m RDBMS kommunizieren,<br />
um diesem Anweisungen zu geben.<br />
Für relationale Datenbanken hat sich die Sprache SQL durchgesetzt. SQL steht für<br />
»Structured Query Language« und wur<strong>de</strong> ursprünglich von <strong><strong>de</strong>r</strong> Firma IBM entwickelt.<br />
Nach<strong>de</strong>m E. F. Codd die Grundlagen über das Relationenmo<strong>de</strong>ll veröffentlicht hatte,<br />
begann IBM mit <strong><strong>de</strong>r</strong> Entwicklung e<strong>in</strong>es ersten Prototypen für e<strong>in</strong> relationales Datenbank-Management-System<br />
mit <strong>de</strong>m Namen System/R. E<strong>in</strong> Teil dieser Entwicklung<br />
bezog sich natürlich auch auf Abfragesprachen für System/R. Daraus entstand <strong><strong>de</strong>r</strong> Vorläufer<br />
<strong>de</strong>s heutigen SQL, die Sprache SEQUEL (»Structured English Query Language« ).<br />
Mit <strong><strong>de</strong>r</strong> kommerziellen Verbreitung relationaler Datenbank-Management-Systeme seit<br />
Anfang <strong><strong>de</strong>r</strong> 80er Jahre, setzte sich auch SQL durch. Dies war <strong><strong>de</strong>r</strong> Anstoß dafür, dass<br />
sich das ANSI (»American National Standard Institute« ) mit <strong><strong>de</strong>r</strong> Standardisierung <strong><strong>de</strong>r</strong><br />
Sprache beschäftigte. 1986 wur<strong>de</strong> <strong><strong>de</strong>r</strong> erste SQL-Standard mit <strong><strong>de</strong>r</strong> Bezeichnung ANSI<br />
SQL-86 veröffentlicht. 1992 folgte die Publikation <strong>de</strong>s ANSI SQL-92 Standards und<br />
1999 <strong>de</strong>s ANSI SQL:1999 Standards. Allgeme<strong>in</strong> spricht man auch von SQL-1, SQL-2<br />
und SQL-3.<br />
Da die Standards ke<strong>in</strong>e zw<strong>in</strong>gen<strong>de</strong> Vorgabe s<strong>in</strong>d für Firmen, die relationale Datenbank-Management-Systeme<br />
entwickeln, wur<strong>de</strong>n sie bisher niemals komplett <strong>in</strong> e<strong>in</strong>er<br />
<strong><strong>de</strong>r</strong> bekannten RDBMS implementiert. ANSI SQL ist zwar nicht das Maß aller D<strong>in</strong>ge,<br />
<strong>de</strong>nnoch stimmen die grundlegen<strong>de</strong>n Eigenschaften von SQL bei <strong>de</strong>n jeweiligen<br />
RDBMS-Produkten weitgehend übere<strong>in</strong>. Kennt man also <strong>de</strong>n SQL Standard, ist es relativ<br />
e<strong>in</strong>fach, Datenbankstrukturen für beliebige RDBMS-Produkte anzulegen, um dort<br />
Schema<br />
Personal<br />
Schema<br />
Tabellen Tabellen<br />
Kategorie<br />
Schema<br />
Tabellen<br />
Spalten
Datentypen<br />
die gewünschten Daten zu verwalten. Allerd<strong>in</strong>gs ist es utopisch zu glauben, man<br />
beherrsche alle RDBMS-Produkte, wenn man <strong>de</strong>n SQL-Standard kennt. Es ist eher vergleichbar<br />
mit <strong>de</strong>m Erlernen normaler Anwendungsprogramme. Wenn man sich z.B.<br />
mit <strong>de</strong>m Umgang e<strong>in</strong>es ganz bestim<strong>mt</strong>en Textverarbeitungsprogramms beschäftigt<br />
hat, fällt es e<strong>in</strong>em <strong>in</strong> <strong><strong>de</strong>r</strong> Regel leichter, auch an<strong><strong>de</strong>r</strong>e Textverarbeitungsprogramme zu<br />
bedienen, da die grundlegen<strong>de</strong>n Pr<strong>in</strong>zipien immer gleich s<strong>in</strong>d.<br />
Wir wer<strong>de</strong>n uns im Folgen<strong>de</strong>n mit <strong>de</strong>n wichtigsten Sprach-Eigenschaften <strong>de</strong>s SQL:1999<br />
Standards beschäftigen. Allerd<strong>in</strong>gs kann hier nicht <strong><strong>de</strong>r</strong> gesa<strong>mt</strong>e Standard behan<strong>de</strong>lt<br />
wer<strong>de</strong>n, da dieser aus über 2000 Seiten besteht. Vielmehr han<strong>de</strong>lt es sich um e<strong>in</strong>e E<strong>in</strong>führung<br />
<strong>in</strong> aktuelle und neue Konzepte von SQL, die sich <strong>in</strong> <strong>de</strong>n nächsten Jahren <strong>in</strong><br />
<strong>de</strong>n meisten RDBMS-Produkten durchsetzen wer<strong>de</strong>n bzw. schon vor <strong><strong>de</strong>r</strong> Verabschiedung<br />
<strong>de</strong>s SQL:1999 Standards <strong>in</strong> <strong>de</strong>n RDBMS-Produkten zu f<strong>in</strong><strong>de</strong>n waren.<br />
Bevor wir die erste SQL-Anweisung zum Anlegen von Tabellenstrukturen kennen lernen,<br />
müssen wir uns zunächst jedoch mit <strong>de</strong>n Datentypen ause<strong>in</strong>an<strong><strong>de</strong>r</strong>setzen.<br />
6.3 Datentypen<br />
Wir haben <strong>in</strong> <strong>de</strong>n letzen Kapiteln schon <strong>de</strong>n Begriff <strong>de</strong>s Wertebereichs o<strong><strong>de</strong>r</strong> <strong><strong>de</strong>r</strong> Doma<strong>in</strong><br />
kennen gelernt. Je<strong>de</strong> Eigenschaft e<strong>in</strong>es bestim<strong>mt</strong>en Objekts kann bestim<strong>mt</strong>e Werte<br />
annehmen. Zum Beispiel kann das Alter e<strong>in</strong>er Person <strong>in</strong> Jahren <strong>in</strong> <strong><strong>de</strong>r</strong> Regel nur Werte<br />
zwischen 0 und 150 annehmen, also nur ganzzahlige Werte (vorausgesetzt e<strong>in</strong>e Person<br />
wird nicht älter als 150). An<strong><strong>de</strong>r</strong>erseits enthält die Eigenschaft Gehalt e<strong>in</strong>es Mitarbeiters<br />
auch Zahlen, aber <strong>in</strong> diesem Fall mit Dezimalstellen. Der Name e<strong>in</strong>es Mitarbeiters kann<br />
auch Buchstaben o<strong><strong>de</strong>r</strong> Son<strong><strong>de</strong>r</strong>zeichen enthalten, das Geburtsdatum dagegen nur gültige<br />
Datumswerte. Es gibt also verschie<strong>de</strong>ne Typen von Daten, je nach<strong>de</strong>m welche<br />
Werte e<strong>in</strong> Attribut annehmen darf.<br />
SQL unterschei<strong>de</strong>t fünf Arten von vor<strong>de</strong>f<strong>in</strong>ierten atomaren Datentypen:<br />
� Zahlen zum Speichern von numerischen Werten, z.B. Alter, Gehalt;<br />
� Zeichenketten zum Speichern von beliebigen Zeichenfolgen, z.B. Beschreibung,<br />
Vorname, Strasse;<br />
� Datum/Zeit zum Speichern von Zeitwerten, z.B. Geburtsdatum, Term<strong>in</strong>;<br />
� Intervall zum Speichern von Zeitabstän<strong>de</strong>n, z.B. Dauer;<br />
� Boolean zum Speichern von Wahr-/Falsch-Werten, z.B. »Führersche<strong>in</strong> vorhan<strong>de</strong>n« .<br />
Für je<strong>de</strong>n Datentyp kennt SQL e<strong>in</strong> bestim<strong>mt</strong>es Schlüsselwort, über das <strong><strong>de</strong>r</strong> Datentyp<br />
e<strong>in</strong>es Attributes festgelegt wird. Will man e<strong>in</strong>em Attribut e<strong>in</strong>en bestim<strong>mt</strong>en Wert<br />
zuweisen, so muss <strong><strong>de</strong>r</strong> Datentyp beachtet wer<strong>de</strong>n. Damit z.B. e<strong>in</strong>er Zahl ke<strong>in</strong>e Zeichenkette<br />
zugewiesen wer<strong>de</strong>n kann, ist e<strong>in</strong>e bestim<strong>mt</strong>e Schreibweise für Werte von Datentypen<br />
vorgegeben. Man spricht hierbei von Literalen. Literale s<strong>in</strong>d unverän<strong><strong>de</strong>r</strong>bare<br />
konstante Werte, die <strong>de</strong>n E<strong>in</strong>schränkungen <strong>de</strong>s zugehörigen Datentyps entsprechen.<br />
97
98<br />
6 SQL – Anlegen <strong><strong>de</strong>r</strong> Datenbankstruktur<br />
Schlüsselwort Beschreibung Beispiel:<br />
Literal<br />
Beispiel:<br />
Deklaration<br />
SMALLINT Ganzzahl mit ger<strong>in</strong>gerem<br />
Wertebereich als INTEGER<br />
25 Alter SMALLINT<br />
INTEGER Ganzzahl 200399 E<strong>in</strong>wohnerzahl INTEGER<br />
DECIMAL (p, s) Zahl mit Dezimalstellen,<br />
p (precision) = Gesa<strong>mt</strong>stellen,<br />
s (scale) = Dezimalstellen<br />
NUMERIC (p, s) Zahl mit Dezimalstellen,<br />
p = Gesa<strong>mt</strong>stellen,<br />
s = Dezimalstellen<br />
REAL Angenäherte Zahl mit<br />
Dezimalstellen<br />
FLOAT (p) Angenäherte Zahl mit<br />
Dezimalstellen<br />
DOUBLE Angenäherte Zahl mit<br />
Dezimalstellen<br />
12.99<br />
+22<br />
.6221<br />
232.11<br />
-1.22<br />
4E3<br />
-0.14E-8<br />
4E3<br />
-0.14E-8<br />
4E3<br />
-0.14E-8<br />
Tabelle 6.1: Numerische Datentypen<br />
Gehalt DECIMAL (8,2)<br />
Preis NUMERIC (5,2)<br />
Pi REAL<br />
Volumen REAL<br />
Entfernung FLOAT (10)<br />
Breite FLOAT<br />
Messwert DOUBLE<br />
Radius DOUBLE<br />
Für alle numerischen Datentypen gilt, dass diese immer nur e<strong>in</strong>en bestim<strong>mt</strong>en Wertebereich<br />
ab<strong>de</strong>cken können, da Computer nicht beliebig hohe bzw. beliebig niedrige Zahlen<br />
speichern können. So gilt z.B. bei <strong>de</strong>n meisten RDBMS-Produkten für <strong>de</strong>n Datentyp<br />
SMALLINT e<strong>in</strong> Wertebereich von -32.768 bis +32.767, dieser kann jedoch höher o<strong><strong>de</strong>r</strong><br />
auch niedriger se<strong>in</strong>. Er ist aber immer auf e<strong>in</strong>en bestim<strong>mt</strong>en Bereich begrenzt. E<strong>in</strong>e<br />
Spalte, die also mit <strong>de</strong>m Datentyp SMALLINT angelegt wur<strong>de</strong>, kann als höchste Zahl<br />
<strong>de</strong>n Wert +32.767 enthalten und als kle<strong>in</strong>ste Zahl <strong>de</strong>n Wert -32.768.<br />
Generell unterschei<strong>de</strong>t man bei numerischen Datentypen zwischen exakten und angenäherten<br />
Datentypen. Die ersten vier Datentypen bil<strong>de</strong>n e<strong>in</strong>en numerischen Wert exakt<br />
ab. Dagegen gibt es angenäherte Datentypen, die berechnete Zahlen wie z.B. die Zahl<br />
Pi bis zu e<strong>in</strong>er ganz bestim<strong>mt</strong>en Anzahl Nachkommastellen speichern können.<br />
Literale von angenäherten (approximierten) numerischen Datentypen wer<strong>de</strong>n <strong>in</strong> Form<br />
<strong><strong>de</strong>r</strong> E Notation ausgedrückt, wie es <strong>in</strong> Programmiersprachen wie C o<strong><strong>de</strong>r</strong> Pascal üblich<br />
ist. Der Buchstabe E steht dabei für »10 hoch irgen<strong>de</strong>twas« .<br />
4E3 entspricht damit also <strong><strong>de</strong>r</strong> Zahl: 4 * 10 3 = 4 * 1000 = 4000,<br />
-321E-8 dagegen <strong><strong>de</strong>r</strong> Zahl -321 * 10 -8 = –321 * 0.00000001 = -0.00000321.<br />
Im kaufmännischen Bereich wer<strong>de</strong>n vorwiegend die numerischen Datentypen DECI-<br />
MAL, NUMERIC und INTEGER benutzt. Numerische Datentypen mit angenähertem<br />
Wert s<strong>in</strong>d hauptsächlich im wissenschaftlichen und mathematischen Bereich s<strong>in</strong>nvoll.<br />
Zeichenketten s<strong>in</strong>d sicherlich die am häufigsten verwen<strong>de</strong>ten Datentypen <strong>in</strong>nerhalb<br />
e<strong>in</strong>er Datenbank, da Attribute dieses Typs allgeme<strong>in</strong>e textuelle Beschreibungen enthal-
Datentypen<br />
ten (schließlich kommunizieren wir ja mehr über Buchstaben und Wörter als über Zahlen).<br />
Attribute <strong>de</strong>s Datentyps CHARACTER haben immer genau die <strong>in</strong> Klammern<br />
angegebene Länge und wer<strong>de</strong>n <strong>de</strong>shalb immer mit Leerzeichen aufgefüllt, wenn die<br />
e<strong>in</strong>getragenen Wörter weniger Buchstaben aufweisen. Attribute <strong>de</strong>s Datentyps VAR-<br />
CHAR speichern ebenso wie CHARACTER auch Texte, allerd<strong>in</strong>gs <strong>in</strong> variabler Länge,<br />
also ohne H<strong>in</strong>zufügen von Leerzeichen bei kürzeren Wörtern. Der Datentyp BIT wird<br />
selten e<strong>in</strong>gesetzt, da er für das Speichern e<strong>in</strong>zelner Bits (z.B. Ja/Ne<strong>in</strong>-Zustän<strong>de</strong>)<br />
gedacht ist. Mit SQL:1999 ist <strong><strong>de</strong>r</strong> Datentyp BOOLEAN h<strong>in</strong>zugekommen, <strong><strong>de</strong>r</strong> zwar auch<br />
zur Speicherung von Ja/Ne<strong>in</strong>-Zustän<strong>de</strong>n gedacht ist, aber benutzerfreundlicher ist, da<br />
hier mit Wahrheitswerten gearbeitet wird.<br />
Schlüsselwort Beschreibung Beispiel:<br />
Literal<br />
CHARACTER(n) Zeichenkette mit<br />
fester Länge<br />
CHARACTER VARYING (n)<br />
VARCHAR (n)<br />
Zeichenkette variabler<br />
Länge<br />
BIT (n) Bitkette fester<br />
Länge<br />
BIT VARYING(n) Bitkette variabler<br />
Länge<br />
CHARACTER LARGE OBJECT(n)<br />
CLOB (n)<br />
BINARY LARGE OBJECT(n)<br />
BLOB (n)<br />
Zeichenkette für<br />
Fließtext<br />
Bitkette für B<strong>in</strong>ärdaten<br />
Tabelle 6.2: Zeichenketten<br />
Schlüsselwort Beschreibung Beispiel:<br />
Literal<br />
BOOLEAN Boolescher Wert TRUE<br />
FALSE<br />
Tabelle 6.3: Boolean<br />
Beispiel:<br />
Deklaration<br />
'Hans' Vorname CHAR(20)<br />
'Muster' Name VARCHAR(50)<br />
B'01101'<br />
X'12DEF'<br />
B'01101'<br />
X'12DEF'<br />
'sehr<br />
langer Text'<br />
B'01101'<br />
X'12DEF'<br />
Zustaen<strong>de</strong> BIT (6)<br />
Zustaen<strong>de</strong> BIT (6)<br />
BeschreibungCLOB(1M)<br />
Kapitel CLOB(20K)<br />
Lebenslauf CLOB(8000)<br />
Foto BLOB (80M)<br />
Beispiel:<br />
Deklaration<br />
Fuehrersche<strong>in</strong> BOOLEAN<br />
S<strong>in</strong>d große Textdaten <strong>in</strong> e<strong>in</strong>em Attribut zu speichern, so verwen<strong>de</strong>t man <strong>de</strong>n Datentyp<br />
CLOB. Als Parameter wird die Anzahl <strong><strong>de</strong>r</strong> Zeichen angegeben. Zur Vere<strong>in</strong>fachung darf<br />
man hier die bei<strong>de</strong>n Buchstaben K für Kilobyte (=1024 Zeichen) und M für Megabyte<br />
(=1024*1024 Zeichen) verwen<strong>de</strong>n.<br />
Für große b<strong>in</strong>äre Dateien, wie z.B. Audios, Vi<strong>de</strong>os o<strong><strong>de</strong>r</strong> Bil<strong><strong>de</strong>r</strong>, verwen<strong>de</strong>t man <strong>de</strong>n<br />
Datentyp BLOB.<br />
99
100<br />
6 SQL – Anlegen <strong><strong>de</strong>r</strong> Datenbankstruktur<br />
Schließlich gibt es noch die folgen<strong>de</strong>n Datentypen zur Speicherung von Datums- und<br />
Zeitwerten.<br />
Schlüsselwort Beschreibung<br />
Beispiel:<br />
Literal<br />
Beispiel:<br />
Deklaration<br />
DATE Datum '2002-09-29' Geburtsdatum<br />
DATE<br />
TIME (p) Uhrzeit '20:15:00.00000<br />
0'<br />
'18:00'<br />
Spielbeg TIME<br />
TIMESTAMP (p) Datum und<br />
Uhrzeit<br />
INTERVAL YEAR(p)<br />
INTERVAL MONTH(p)<br />
INTERVAL YEAR(p) TO MONTH<br />
INTERVAL DAY(p) TO HOUR(p)<br />
INTERVAL DAY(p) TO MINUTE(p)<br />
INTERVAL DAY(p) TO SECOND(p)<br />
INTERVAL MINUTE(p) TO SECOND(p)<br />
INTERVAL SECOND(p,s)<br />
'2002-09-29<br />
18:00'<br />
Zeit<strong>in</strong>tervalle '3'<br />
'12'<br />
'62-10'<br />
'26 19:30'<br />
'-61 22:30'<br />
'21 31.0001'<br />
'15:31:0001'<br />
'59.000008'<br />
Tabelle 6.4: Datum / Zeit / Zeit<strong>in</strong>tervall<br />
Term<strong>in</strong> TIME-<br />
STAMP<br />
Alter YEAR(3)<br />
Fallgeschw<br />
SECOND(2,6)<br />
Wir haben nun die wichtigsten Datentypen von SQL:1999 kennen gelernt und auch<br />
gesehen, wie man entsprechen<strong>de</strong> Werte als Literale schreibt. Was <strong>in</strong> diesem Zusammenhang<br />
noch gar nicht angesprochen wur<strong>de</strong>, ist das Speichern von Werten, die entwe<strong><strong>de</strong>r</strong><br />
nicht bekannt s<strong>in</strong>d o<strong><strong>de</strong>r</strong> nicht existieren. Angenommen, Sie sollen die Daten<br />
e<strong>in</strong>es bestim<strong>mt</strong>en Kun<strong>de</strong>n <strong>in</strong> <strong><strong>de</strong>r</strong> Kun<strong>de</strong>ntabelle speichern, wissen jedoch nicht <strong>de</strong>ssen<br />
Geburtsdatum. SQL bietet hierfür e<strong>in</strong> vor<strong>de</strong>f<strong>in</strong>iertes Schlüsselwort: NULL.<br />
Der Wort NULL steht nicht für die Zahl 0, NULL ist auch ke<strong>in</strong> Wert, son<strong><strong>de</strong>r</strong>n soll e<strong>in</strong>fach<br />
ausdrücken, dass e<strong>in</strong> Wert nicht bekannt ist. Dies hat zur Konsequenz, dass SQL<br />
mit e<strong>in</strong>er dreiwertigen Logik arbeitet.<br />
Betrachten wir hierzu e<strong>in</strong> Beispiel: Angenommen die Spalte Lagerbestand ist für e<strong>in</strong>en<br />
bestim<strong>mt</strong>en Werbeartikel nicht bekannt, also NULL. Wür<strong>de</strong>n wir nun vergleichen wollen,<br />
ob <strong><strong>de</strong>r</strong> Lagerbestand z.B. größer als 8 ist, so haben wir e<strong>in</strong> Problem. Der Vergleich<br />
»Lagerbestand > 8« ergibt we<strong><strong>de</strong>r</strong> wahr noch falsch, da wir <strong>de</strong>n Lagerbestand ja nicht<br />
kennen. Das Ergebnis dieses Vergleiches ist <strong>de</strong>mentsprechend also unbekannt.<br />
Dieses Problem muss auch bei <strong><strong>de</strong>r</strong> Verknüpfung von Bed<strong>in</strong>gungen mit UND/ODER<br />
berücksichtigt wer<strong>de</strong>n. Angenommen, wir wollen wissen, ob sowohl <strong><strong>de</strong>r</strong> Lagerbestand<br />
für e<strong>in</strong>en bestim<strong>mt</strong>en Werbeartikel größer 8 und gleichzeitig <strong><strong>de</strong>r</strong> Preis kle<strong>in</strong>er als 4,99<br />
Euro ist. Die erste Bed<strong>in</strong>gung ergibt, wie oben gesehen, unbekannt. Ist <strong><strong>de</strong>r</strong> Preis z.B.<br />
gleich 3 Euro, so ist die zweite Bed<strong>in</strong>gung wahr. E<strong>in</strong>e UND-Verküpfung von unbekannt<br />
und wahr muss als Ergebnis wie<strong><strong>de</strong>r</strong> e<strong>in</strong> unbekannt ergeben, da wir ja nicht mit Sicher-
Erzeugen und Bearbeiten e<strong>in</strong>er Tabelle<br />
heit sagen können, ob die Bed<strong>in</strong>gung erfüllt ist. Wür<strong>de</strong>n wir umgekehrt die bei<strong>de</strong>n<br />
Bed<strong>in</strong>gungen mit ODER verknüpfen, so ist das Ergebnis wahr. Betrachten wir abschließend<br />
die Wahrheitstabellen für wahr, falsch und unbekannt.<br />
falsch UND falsch = falsch<br />
falsch UND wahr = falsch<br />
falsch UND unbekannt = falsch<br />
wahr UND unbekannt = unbekannt<br />
wahr UND wahr = wahr<br />
unbekannt UND unbekannt = unbekannt<br />
Tabelle 6.5: Wahrheitstabelle für UND-Verknüpfungen<br />
falsch ODER falsch = falsch<br />
falsch ODER wahr = wahr<br />
falsch ODER unbekannt = unbekannt<br />
wahr ODER unbekannt = wahr<br />
wahr ODER wahr = wahr<br />
unbekannt ODER unbekannt = unbekannt<br />
Tabelle 6.6: Wahrheitstabelle für ODER-Verknüpfungen<br />
6.4 Erzeugen und Bearbeiten e<strong>in</strong>er Tabelle<br />
6.4.1 Erzeugen e<strong>in</strong>er Tabelle<br />
Wie wird nun e<strong>in</strong>e Tabelle angelegt? Hierzu kennt SQL die Anweisung CREATE<br />
TABLE. Betrachten wir hierzu die Tabelle Ort aus unserem Fallbeispiel. Diese besteht<br />
aus <strong>de</strong>n bei<strong>de</strong>n Attributen Ort und Postleitzahl. Die Anweisung, um diese Tabelle <strong>in</strong><br />
e<strong>in</strong>er Datenbank anzulegen, lautet:<br />
CREATE TABLE Ort<br />
(<br />
Plz INTEGER,<br />
Ort VARCHAR (200)<br />
)<br />
Mit dieser e<strong>in</strong>fachen Anweisung haben wir die Tabelle »Ort« <strong>in</strong> unserer Datenbank<br />
angelegt. Da zu je<strong><strong>de</strong>r</strong> Postleitzahl immer e<strong>in</strong> Ort bekannt ist, wollen wir allerd<strong>in</strong>gs verh<strong>in</strong><strong><strong>de</strong>r</strong>n,<br />
dass nicht aus Versehen e<strong>in</strong>e Postleitzahl ohne Ort gespeichert wird. Dazu<br />
kann man <strong>in</strong> <strong><strong>de</strong>r</strong> CREATE TABLE-Anweisung angeben, ob e<strong>in</strong> Attribut NULL-Werte<br />
101
102<br />
6 SQL – Anlegen <strong><strong>de</strong>r</strong> Datenbankstruktur<br />
enthalten darf. Daneben wollen wir unserem RDBMS auch bekannt geben, dass es sich<br />
bei <strong>de</strong>m Attribut Plz um <strong>de</strong>n Primärschlüssel han<strong>de</strong>lt. Die Anweisung dazu sieht wie<br />
folgt aus:<br />
CREATE TABLE Ort<br />
(<br />
Plz INTEGER NOT NULL ,<br />
Ort VARCHAR (200) NOT NULL ,<br />
-- Primärschlüssel festlegen<br />
CONSTRAINT primschluessel_Ort PRIMARY KEY (Plz)<br />
)<br />
Da die Attribute Plz und Ort ke<strong>in</strong> NULL enthalten dürfen ersche<strong>in</strong>en nun h<strong>in</strong>ter <strong><strong>de</strong>r</strong><br />
Deklaration <strong><strong>de</strong>r</strong> Attribute und <strong><strong>de</strong>r</strong>en Datentypen die bei<strong>de</strong>n Schlüsselwörter NOT<br />
NULL.<br />
Integritätsbed<strong>in</strong>gungen e<strong>in</strong>er Tabelle gibt man <strong>in</strong> SQL über das Schlüsselwort CONS-<br />
TRAINT bekannt. H<strong>in</strong>ter diesem Schlüsselwort folgt e<strong>in</strong>e beliebige Bezeichnung für<br />
die Integritätsbed<strong>in</strong>gung, und dann die Integritätsbed<strong>in</strong>gung selbst. Über die bei<strong>de</strong>n<br />
Schlüsselwörter PRIMARY KEY legt man <strong>de</strong>n Primärschlüssel fest. In Klammern<br />
ersche<strong>in</strong>t das Attribut o<strong><strong>de</strong>r</strong> die Attributkomb<strong>in</strong>ation, die <strong>de</strong>n Primärschlüssel darstellt,<br />
<strong>in</strong> unserem Beispiel das Attribut Plz.<br />
Wie im letzten Beispiel gezeigt, kann man <strong>in</strong> SQL:1999 auch Kommentare e<strong>in</strong>fügen,<br />
<strong>in</strong><strong>de</strong>m e<strong>in</strong>e Zeile mit zwei B<strong>in</strong><strong>de</strong>strichen beg<strong>in</strong>nt und dah<strong>in</strong>ter <strong><strong>de</strong>r</strong> Kommentar folgt<br />
(z.B. -- Primärschlüssel festlegen). In dieser Form kann man e<strong>in</strong>zeilige Kommentare<br />
schreiben. Mehrzeilige Kommentare wer<strong>de</strong>n durch die bei<strong>de</strong>n Zeichen /* e<strong>in</strong>geleitet<br />
und durch die bei<strong>de</strong>n Zeichen */ wie<strong><strong>de</strong>r</strong> been<strong>de</strong>t, z.B.<br />
/* Dies ist e<strong>in</strong> Kommentar<br />
über zwei Zeilen */<br />
Wir wollen jetzt e<strong>in</strong>e weitere Tabelle aus unserm Fallbeispiel anlegen, die Tabelle<br />
»Spielstaette« . Um die Tabelle anzulegen, verwen<strong>de</strong>n wir wie<strong><strong>de</strong>r</strong> die Anweisung CRE-<br />
ATE TABLE. Über CONSTRAINT legen wir schließlich fest, welches Attribut als Primärschlüssel<br />
bestim<strong>mt</strong> wur<strong>de</strong>:<br />
CREATE TABLE Spielstaette<br />
(<br />
Haus VARCHAR (100) NOT NULL ,<br />
Strasse VARCHAR (50) NOT NULL ,<br />
Hausnummer CHAR (6) ,<br />
Plz INTEGER ,<br />
Beschreibung CLOB(1M) ,<br />
)<br />
CONSTRAINT primschluessel_Spielstaette PRIMARY KEY (Haus)
Erzeugen und Bearbeiten e<strong>in</strong>er Tabelle<br />
In <strong>de</strong>n letzten bei<strong>de</strong>n Kapiteln haben wir gesehen, dass Beziehungen zwischen Tabellen<br />
über Fremdschlüssel abgebil<strong>de</strong>t wer<strong>de</strong>n. Unsere Tabelle Spielstaette besitzt e<strong>in</strong>en<br />
solchen Fremdschlüssel, das Attribut Plz. Über das Attribut kann <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle Ort<br />
nachgesehen wer<strong>de</strong>n, welcher Ortsname zu welcher Postleitzahl gehört. In unserer obigen<br />
SQL-Anweisung haben wir <strong>de</strong>m RDBMS diese Beziehung jedoch noch nicht mitgeteilt.<br />
In Abschnitt 4.3 haben wir die verschie<strong>de</strong>nen Integritätsbed<strong>in</strong>gungen kennen<br />
gelernt. E<strong>in</strong>e dieser Integritätsbed<strong>in</strong>gungen, die referentielle Integrität, bezog sich auf<br />
die eben beschriebene Beziehung zwischen Primär- und Fremdschlüssel.<br />
Da es sich bei <strong><strong>de</strong>r</strong> referenziellen Integrität wie<strong><strong>de</strong>r</strong>um um e<strong>in</strong>e E<strong>in</strong>schränkung han<strong>de</strong>lt,<br />
verwen<strong>de</strong>n wir das SQL-Schlüsselwort CONSTRAINT gefolgt von e<strong>in</strong>er beliebigen<br />
Bezeichnung für die Integritätsbed<strong>in</strong>gung. Danach folgen die Schlüsselwörter, um<br />
e<strong>in</strong>en Fremdschlüssel zu <strong>de</strong>klarieren: FOREIGN KEY. In Klammern wird dah<strong>in</strong>ter das<br />
Attribut bzw. die Attributkomb<strong>in</strong>ation angegeben, die <strong>de</strong>n Fremdschlüssel darstellt.<br />
Schließlich muss man festlegen, auf welches Attribut <strong>in</strong> welcher Tabelle sich <strong><strong>de</strong>r</strong><br />
Fremdschlüssel bezieht. Dies erfolgt über das Wort REFERENCES gefolgt vom Tabellennamen<br />
und <strong>de</strong>m Attribut. Mit Angabe <strong>de</strong>s Fremdschlüssel wird die Tabelle »Spielstaette«<br />
wie folgt erzeugt:<br />
CREATE TABLE Spielstaette<br />
(<br />
Haus VARCHAR (100) NOT NULL ,<br />
Strasse VARCHAR (50) NOT NULL ,<br />
Hausnummer CHAR (6) ,<br />
Plz INTEGER ,<br />
Beschreibung CLOB(1M) ,<br />
)<br />
CONSTRAINT primschluessel_Spielstaette PRIMARY KEY (Haus),<br />
CONSTRAINT fremdschluessel_PlzOrt FOREIGN KEY (Plz)<br />
REFERENCES Ort (Plz)<br />
Betrachten wir hierzu folgen<strong>de</strong>s Beispiel. Angenommen, <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »Ort« wur<strong>de</strong><br />
fälschlicherweise für <strong>de</strong>n Ort Hamburg nicht die Postleitzahl 22287, son<strong><strong>de</strong>r</strong>n 33387 e<strong>in</strong>getragen.<br />
Auf diese Postleitzahl wird jedoch <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »Spielstaette« referenziert:<br />
Spielstaette<br />
Haus<br />
Deutsche Staatsoper<br />
...<br />
Strasse<br />
Opernstr.<br />
Hausnummer<br />
12<br />
Plz<br />
33387<br />
Plz<br />
33387<br />
...<br />
Ort<br />
Abbildung 6.2: Problem <strong><strong>de</strong>r</strong> referenziellen Integrität<br />
Beschreibung<br />
Ort<br />
...<br />
Hamburg<br />
103
104<br />
6 SQL – Anlegen <strong><strong>de</strong>r</strong> Datenbankstruktur<br />
Wür<strong>de</strong> man nun die Postleitzahl <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle Ort von 33387 <strong>in</strong> 22287 än<strong><strong>de</strong>r</strong>n, so<br />
wür<strong>de</strong> die Spielstaette »Deutsche Staatsoper« auf e<strong>in</strong>en E<strong>in</strong>trag <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle Ort verweisen,<br />
<strong>de</strong>n es nicht mehr gibt. Die Beziehung wür<strong>de</strong> also sozusagen <strong>in</strong>s »Leere« laufen.<br />
Das Gleiche gilt, wenn <strong><strong>de</strong>r</strong> Satz mit <strong><strong>de</strong>r</strong> Plz 33387 aus <strong><strong>de</strong>r</strong> Tabelle »Ort« gelöscht<br />
wür<strong>de</strong>.<br />
Um solche Probleme zu vermei<strong>de</strong>n, erlaubt e<strong>in</strong> RDBMS das Än<strong><strong>de</strong>r</strong>n o<strong><strong>de</strong>r</strong> Löschen<br />
e<strong>in</strong>es Satzes nicht, solange <strong><strong>de</strong>r</strong> Wert e<strong>in</strong>es Fremdschlüssels noch auf die Tabelle verweist.<br />
Da diese E<strong>in</strong>schränkung jedoch sehr restriktiv ist, kann man über SQL bei <strong><strong>de</strong>r</strong> Festlegung<br />
e<strong>in</strong>es Fremdschlüssels angeben, wie mit <strong>de</strong>m Fremdschlüssel verfahren wer<strong>de</strong>n<br />
soll, wenn e<strong>in</strong> solches Problem auftritt. SQL:1999 kennt fünf mögliche Aktionen, die bei<br />
e<strong>in</strong>er Fremdschlüsselverletzung ausgeführt wer<strong>de</strong>n können:<br />
� RESTRICT o<strong><strong>de</strong>r</strong> NO ACTION<br />
� SET NULL<br />
� SET DEFAULT<br />
� CASCADE<br />
RESTRICT entspricht <strong><strong>de</strong>r</strong> Standar<strong>de</strong><strong>in</strong>stellung und verh<strong>in</strong><strong><strong>de</strong>r</strong>t das Än<strong><strong>de</strong>r</strong>n o<strong><strong>de</strong>r</strong><br />
Löschen e<strong>in</strong>es Satzes, auf <strong>de</strong>n sich e<strong>in</strong> Fremdschlüssel bezieht. In unserem Beispiel<br />
wür<strong>de</strong> also das Än<strong><strong>de</strong>r</strong>n o<strong><strong>de</strong>r</strong> Löschen zurückgewiesen.<br />
SET NULL legt fest, dass <strong><strong>de</strong>r</strong> Fremdschlüssel auf NULL gesetzt wird, somit ke<strong>in</strong> Bezug<br />
mehr zur Elterntabelle vorhan<strong>de</strong>n ist.<br />
SET DEFAULT entspricht SET NULL, mit <strong>de</strong>m Unterschied, dass e<strong>in</strong> vorher <strong>de</strong>f<strong>in</strong>ierter<br />
Standardwert für <strong>de</strong>n Fremdschlüssel verwen<strong>de</strong>t wird. Wir wer<strong>de</strong>n später <strong>in</strong> diesem<br />
Kapitel das Schlüsselwort DEFAULT kennen lernen. Hiermit kann e<strong>in</strong> Standardwert<br />
festgelegt wer<strong>de</strong>n, <strong><strong>de</strong>r</strong> bei E<strong>in</strong>fügen e<strong>in</strong>es Satzes für e<strong>in</strong> Attribut verwen<strong>de</strong>t wird, wenn<br />
für dieses Attribut nicht explizit e<strong>in</strong> Wert angegeben wur<strong>de</strong>. Angenommen, aus <strong><strong>de</strong>r</strong><br />
Abteilungstabelle wird die Abteilung »Vertrieb« gelöscht. DEFAULT sorgt nun dafür,<br />
dass <strong>de</strong>n Mitarbeitern, die <strong><strong>de</strong>r</strong> gelöschten Abteilung »Vertrieb« zugeordnet waren, <strong><strong>de</strong>r</strong><br />
<strong>de</strong>f<strong>in</strong>ierte Standardwert »Rechnungswesen« als Fremdschlüssel zugeordnet wird,<br />
sofern die Tabelle »Mitarbeiter« wie folgt angelegt wur<strong>de</strong>:<br />
CREATE TABLE Mitarbeiter<br />
(<br />
Personalnummer INTEGER NOT NULL,<br />
...<br />
Abteilungsbezeichnung VARCHAR (30) DEFAULT 'Rechnungswesen',<br />
...<br />
)
Erzeugen und Bearbeiten e<strong>in</strong>er Tabelle<br />
CASCADE bewirkt schließlich, dass <strong><strong>de</strong>r</strong> Wert <strong>de</strong>s Fremdschlüssels automatisch auf<br />
<strong>de</strong>n Wert <strong>de</strong>s geän<strong><strong>de</strong>r</strong>ten Primärschlüssels gesetzt wird bzw. <strong><strong>de</strong>r</strong> Satz sowohl aus <strong><strong>de</strong>r</strong><br />
Elterntabelle als auch aus <strong><strong>de</strong>r</strong> K<strong>in</strong>dtabelle gelöscht wird.<br />
Bei Anwendung <strong><strong>de</strong>r</strong> Aktionen SET NULL und CASCADE wür<strong>de</strong>n die Tabellen nach<br />
<strong><strong>de</strong>r</strong> Än<strong><strong>de</strong>r</strong>ung wie folgt aussehen.<br />
Spielstaette<br />
Haus<br />
Deutsche Staatsoper<br />
...<br />
Spielstaette<br />
Haus<br />
Deutsche Staatsoper<br />
...<br />
Strasse<br />
Opernstr.<br />
SET NULL<br />
Hausnummer<br />
12<br />
Abbildung 6.3: Referenzielle Integrität bei SET NULL<br />
Strasse<br />
Opernstr.<br />
CASCADE<br />
Hausnummer<br />
12<br />
Abbildung 6.4: Referenzielle Integrität bei CASCADE<br />
Doch wie gibt man über SQL <strong>de</strong>m RDBMS bekannt, welche Aktion bei Verletzung <strong><strong>de</strong>r</strong><br />
referentiellen Integrität verwen<strong>de</strong>t wer<strong>de</strong>n soll? Die Aktion gehört mit zur Def<strong>in</strong>ition<br />
<strong>de</strong>s Fremdschlüssels und folgt dieser direkt. Angenommen, wir möchten, dass das<br />
Attribut Plz auf NULL gesetzt wird, wenn <strong><strong>de</strong>r</strong> entsprechen<strong>de</strong> Satz <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »Ort«<br />
gelöscht wird. Außer<strong>de</strong>m soll die Plz <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »Spielstaette« automatisch geän<strong><strong>de</strong>r</strong>t<br />
wer<strong>de</strong>n, wenn diese <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »Ort« geän<strong><strong>de</strong>r</strong>t wird. Die SQL-Anweisung hierfür<br />
sieht folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
Plz<br />
NULL<br />
Plz<br />
22287<br />
...<br />
Plz<br />
22287<br />
Plz<br />
22287<br />
...<br />
Ort<br />
Ort<br />
Beschreibung<br />
Ort<br />
...<br />
Hamburg<br />
Beschreibung<br />
Ort<br />
...<br />
Hamburg<br />
105
106<br />
6 SQL – Anlegen <strong><strong>de</strong>r</strong> Datenbankstruktur<br />
CREATE TABLE Spielstaette<br />
(<br />
Haus VARCHAR (100) NOT NULL ,<br />
Strasse VARCHAR (50) NOT NULL ,<br />
Hausnummer CHAR (6) ,<br />
Plz INTEGER ,<br />
Beschreibung CLOB(1M) ,<br />
)<br />
CONSTRAINT primschluessel_Spielstaette PRIMARY KEY (Haus),<br />
CONSTRAINT fremdschluessel_PlzOrt FOREIGN KEY (Plz)<br />
REFERENCES Ort (Plz)<br />
/* bei Löschen <strong>de</strong>s zugehörigen Ortes die Plz<br />
automatisch auf NULL setzen */<br />
ON DELETE SET NULL<br />
/* bei Än<strong><strong>de</strong>r</strong>n <strong><strong>de</strong>r</strong> zugehörigen Plz <strong>in</strong> <strong><strong>de</strong>r</strong><br />
Orttabelle, die Plz von Spielstaette<br />
automatisch anpassen */<br />
ON UPDATE CASCADE<br />
Zuerst ersche<strong>in</strong>t das Ereignis (ON DELETE o<strong><strong>de</strong>r</strong> ON UPDATE) und dann die Aktion,<br />
die bei Auftreten <strong>de</strong>s entsprechen<strong>de</strong>n Ereignisses ausgeführt wer<strong>de</strong>n soll.<br />
Von <strong>de</strong>n drei Integritätsbed<strong>in</strong>gungen, die wir <strong>in</strong> Abschnitt 4.3 behan<strong>de</strong>lt haben, können<br />
wir bisher die referentielle Integrität (FOREIGN KEY) und die Entity-Integrität (PRI-<br />
MARY KEY) über SQL abbil<strong>de</strong>n. Fehlt also noch die Darstellung von Doma<strong>in</strong>-Integritätsbed<strong>in</strong>gungen<br />
<strong>in</strong> SQL.<br />
Nehmen wir als Beispiel wie<strong><strong>de</strong>r</strong> unsere Tabelle Ort. Als Datentyp für die Postleitzahl<br />
haben wir e<strong>in</strong>e Ganzzahl (INTEGER) verwen<strong>de</strong>t. Der Wertebereich für e<strong>in</strong>en INTEGER<br />
liegt bei <strong>de</strong>n meisten RDBMS-Produkten zwischen -2.147.483.647 und +2.147.483.648.<br />
Allerd<strong>in</strong>gs wissen wir, dass e<strong>in</strong>e Postleitzahl <strong>in</strong> Deutschland immer aus fünf Zahlen<br />
besteht, Werte größer als 99.999 also nicht möglich s<strong>in</strong>d (es gibt bei Postleitzahlen zwar<br />
noch mehr E<strong>in</strong>schränkungen, <strong><strong>de</strong>r</strong> Übersichtlichkeit halber bleiben wir hier aber bei dieser<br />
vere<strong>in</strong>fachten Darstellung).<br />
Um E<strong>in</strong>schränkungen solcher Art über SQL auszudrücken, kennt SQL verschie<strong>de</strong>ne<br />
Sprachelemente. E<strong>in</strong> Sprachelement, dass hierfür <strong>in</strong>nerhalb <strong><strong>de</strong>r</strong> CREATE TABLE-<br />
Anweisung verwen<strong>de</strong>t wer<strong>de</strong>n kann, ist das Schlüsselwort CHECK.<br />
CHECK wird wie die an<strong><strong>de</strong>r</strong>en bei<strong>de</strong>n Integritätsbed<strong>in</strong>gungen auch durch das Schlüsselwort<br />
CONSTRAINT und e<strong>in</strong>e Bezeichnung für diese E<strong>in</strong>schränkung e<strong>in</strong>geleitet.<br />
Darauf folgt das Wort CHECK und dann die Bed<strong>in</strong>gung, die bei E<strong>in</strong>fügen e<strong>in</strong>es Satzes<br />
<strong>in</strong> die Tabelle erfüllt se<strong>in</strong> muss.<br />
Für unser Beispiel mit <strong><strong>de</strong>r</strong> Postleitzahl sieht das dann wie folgt aus:<br />
CREATE TABLE Ort<br />
(<br />
Plz INTEGER NOT NULL ,
)<br />
Erzeugen und Bearbeiten e<strong>in</strong>er Tabelle<br />
Ort VARCHAR (200) NOT NULL ,<br />
CONSTRAINT primschluessel_Ort PRIMARY KEY (Plz),<br />
CONSTRAINT pruef_Plz CHECK (Plz > 0 AND Plz
108<br />
6 SQL – Anlegen <strong><strong>de</strong>r</strong> Datenbankstruktur<br />
<strong>de</strong>n ob <strong><strong>de</strong>r</strong> Wert für e<strong>in</strong> Attribut e<strong>in</strong>er bestim<strong>mt</strong>en Wertemenge, <strong>in</strong> diesem Fall ›M‹ und<br />
›W‹ entspricht. Das Schlüsselwort IN und weitere Bed<strong>in</strong>gungsausdrücke wer<strong>de</strong>n wir<br />
<strong>de</strong>tailliert <strong>in</strong> Kapitel 8 kennen lernen.<br />
Im Folgen<strong>de</strong>n wird beschrieben, wie SQL noch weitere Doma<strong>in</strong>-Integritätsbed<strong>in</strong>gungen<br />
unterstützt. Hierzu wer<strong>de</strong>n wir kennen lernen, wie man allgeme<strong>in</strong>e Datentypen<br />
mit bestim<strong>mt</strong>en E<strong>in</strong>schränkungen erstellen und e<strong>in</strong>fache eigene Datentypen <strong>de</strong>f<strong>in</strong>ieren<br />
kann.<br />
6.4.2 Erstellen e<strong>in</strong>facher benutzer<strong>de</strong>f<strong>in</strong>ierter Datentypen<br />
Bisher haben wir ausschließlich vor<strong>de</strong>f<strong>in</strong>ierte Datentypen kennen gelernt, also Datentypen,<br />
die uns von SQL vorgegeben wer<strong>de</strong>n. SQL bietet jedoch die Möglichkeit, eigene<br />
Datentypen zu erstellen, die auf vor<strong>de</strong>f<strong>in</strong>ierten Datentypen basieren. Nehmen wir z.B.<br />
unser Attribut Plz. Dieses Attribut kom<strong>mt</strong> <strong>in</strong> verschie<strong>de</strong>nen Tabellen vor, z.B. »Ort« ,<br />
»Spielstaette« o<strong><strong>de</strong>r</strong> »Kun<strong>de</strong>« . In je<strong><strong>de</strong>r</strong> Tabelle muss darauf geachtet wer<strong>de</strong>n, dass <strong><strong>de</strong>r</strong><br />
gleiche vor<strong>de</strong>f<strong>in</strong>ierte Datentyp, nämlich INTEGER, verwen<strong>de</strong>t wur<strong>de</strong>.<br />
Es ist <strong>de</strong>shalb möglich, e<strong>in</strong>en e<strong>in</strong>fachen Datentyp selbst zu erstellen, <strong>de</strong>n man dann z.B.<br />
mit DTyp_Plz bezeichnet. Das Anlegen e<strong>in</strong>facher Datentypen erfolgt über die SQL-<br />
Anweisung CREATE DISTINCT TYPE und sieht für das Attribut »Plz« dann folgen<strong><strong>de</strong>r</strong>maßen<br />
aus:<br />
CREATE DISTINCT Dtyp_Plz AS INTEGER<br />
Anstelle <strong>de</strong>s vor<strong>de</strong>f<strong>in</strong>ierten Datentyps INTEGER kann nun für die Postleitzahl <strong><strong>de</strong>r</strong><br />
benutzer<strong>de</strong>f<strong>in</strong>ierte Datentyp DTyp_Plz verwen<strong>de</strong>t wer<strong>de</strong>n. Für das Anlegen <strong><strong>de</strong>r</strong><br />
Tabelle »Ort« be<strong>de</strong>utet das:<br />
CREATE TABLE Ort<br />
(<br />
Plz DTyp_Plz NOT NULL ,<br />
Ort VARCHAR (200) NOT NULL ,<br />
CONSTRAINT primschluessel_Ort PRIMARY KEY (Plz)<br />
CONSTRAINT pruef_Plz CHECK (Plz > 0 AND Plz
Erzeugen und Bearbeiten e<strong>in</strong>er Tabelle<br />
6.4.3 Überprüfungen von Wertebereichen<br />
Seit <strong>de</strong>m ANSI SQL-92 Standard kennt SQL <strong>de</strong>n Begriff <strong><strong>de</strong>r</strong> Doma<strong>in</strong>. In SQL stellt dieses<br />
e<strong>in</strong> allgeme<strong>in</strong>es Konzept dar, um Wertebereiche von Attributen zu überprüfen.<br />
Dazu erstellt man e<strong>in</strong>e Doma<strong>in</strong> und kann diese anstelle e<strong>in</strong>es beliebigen Datentyps e<strong>in</strong>setzen.<br />
Diese Vorgehensweise er<strong>in</strong>nert stark an die gera<strong>de</strong> besprochenen benutzer<strong>de</strong>f<strong>in</strong>ierten<br />
Datentypen. Im Gegensatz zu benutzer<strong>de</strong>f<strong>in</strong>ierten Datentypen s<strong>in</strong>d Doma<strong>in</strong>s<br />
aber eher e<strong>in</strong>e Schreiberleichterung, da hiermit Datentypen und <strong><strong>de</strong>r</strong>en E<strong>in</strong>schränkungen<br />
an e<strong>in</strong>er Stelle beschrieben und für unterschiedliche Attribut<strong>de</strong>klarationen verwen<strong>de</strong>t<br />
wer<strong>de</strong>n können. Jedoch unterliegen durch Doma<strong>in</strong> <strong>de</strong>klarierte Datentypen ke<strong>in</strong>er<br />
strengen Typüberprüfung, was ja bei benutzer<strong>de</strong>f<strong>in</strong>ierten Datentypen <strong><strong>de</strong>r</strong> Fall ist.<br />
E<strong>in</strong>e Doma<strong>in</strong> wird mit <strong><strong>de</strong>r</strong> SQL-Anweisung CREATE DOMAIN erstellt. Betrachten wir<br />
hierzu unsere Tabelle Kun<strong>de</strong>. Diese besitzt das Attribut »Geschlecht« , das auch <strong>in</strong> <strong>de</strong>n<br />
Tabellen »Mitarbeiter« und »K<strong>in</strong>d« vorkom<strong>mt</strong>. Das Erzeugen <strong><strong>de</strong>r</strong> Doma<strong>in</strong> für dieses<br />
Attribut sieht wie folgt aus:<br />
CREATE DOMAIN dom_Geschlecht AS CHAR(1)<br />
DEFAULT 'W'<br />
CHECK (VALUE IN ('W', 'M'))<br />
E<strong>in</strong>e Doma<strong>in</strong> wird ähnlich wie e<strong>in</strong> e<strong>in</strong>facher benutzer<strong>de</strong>f<strong>in</strong>ierter Datentyp angelegt.<br />
Neben <strong>de</strong>m vor<strong>de</strong>f<strong>in</strong>ierten Datentyp, hier CHAR(1), kann <strong><strong>de</strong>r</strong> Wertebereich jedoch weitergehend<br />
überprüft wer<strong>de</strong>n, so wie wir es bei <strong>de</strong>n Integritätsbed<strong>in</strong>gungen zum Anlegen<br />
e<strong>in</strong>er Tabelle bereits gesehen haben. Das Schlüsselwort VALUE kennzeichnet dabei<br />
<strong>de</strong>n aktuellen Wert <strong><strong>de</strong>r</strong> Doma<strong>in</strong>.<br />
Für das Anlegen <strong><strong>de</strong>r</strong> Tabelle Kun<strong>de</strong> be<strong>de</strong>utet das:<br />
CREATE TABLE Kun<strong>de</strong><br />
(<br />
Kun<strong>de</strong>nnummer INTEGER NOT NULL ,<br />
Name ARCHAR (30) NOT NULL ,<br />
Vorname VARCHAR (20) NOT NULL ,<br />
Geschlecht dom_Geschlecht ,<br />
Strasse VARCHAR ( 50) NOT NULL ,<br />
Hausnummer CHAR (6) ,<br />
Plz DTyp_Plz ,<br />
CONSTRAINT pk_Kun<strong>de</strong> PRIMARY KEY (Kun<strong>de</strong>nnummer),<br />
CONSTRAINT fk_Plz FOREIGN KEY (Plz)<br />
REFERENCES Ort (Plz)<br />
ON DELETE SET NULL<br />
ON UPDATE CASCADE<br />
)<br />
Entgegen <strong><strong>de</strong>r</strong> ersten Lösung zum Anlegen dieser Tabelle, können wir nun auch auf die<br />
E<strong>in</strong>schränkung zum Überprüfen <strong><strong>de</strong>r</strong> Werte für Geschlecht verzichten, da wir dies ja<br />
bereits durch Anlegen <strong><strong>de</strong>r</strong> Doma<strong>in</strong> beschrieben haben.<br />
109
6.4.4 Reihen (Arrays)<br />
110<br />
6 SQL – Anlegen <strong><strong>de</strong>r</strong> Datenbankstruktur<br />
ANSI SQL:1999 unterstützt auch Arrays. Hierbei han<strong>de</strong>lt es sich um Wie<strong><strong>de</strong>r</strong>holgruppen<br />
e<strong>in</strong>es bestim<strong>mt</strong>en Attributs. Angenommen, Sie wollen <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »Kun<strong>de</strong>«<br />
maximal drei unterschiedliche Telefonnummern speichern, so können Sie dies auf drei<br />
verschie<strong>de</strong>ne Arten tun. Entwe<strong><strong>de</strong>r</strong> <strong>de</strong>f<strong>in</strong>ieren Sie drei verschie<strong>de</strong>ne Attribute,<br />
»Telefon1« , »Telefon2« und »Telefon3« . O<strong><strong>de</strong>r</strong> Sie erzeugen e<strong>in</strong>e eigene Tabelle »Telefon«<br />
, die als Fremdschlüssel die Kun<strong>de</strong>nnummer enthält (also 1:N-Beziehung zwischen<br />
Kun<strong>de</strong> und Telefon). Die dritte Möglichkeit schließlich ist die Verwendung e<strong>in</strong>es<br />
Arrays wie folgt:<br />
CREATE TABLE Kun<strong>de</strong><br />
(<br />
...<br />
Telefon CHAR (10) ARRAY[3] ,<br />
...<br />
Sicherlich wer<strong>de</strong>n Sie jetzt erwi<strong><strong>de</strong>r</strong>n, dass dies aber doch <strong><strong>de</strong>r</strong> ersten Normalform und<br />
damit <strong>de</strong>m Relationenmo<strong>de</strong>ll wi<strong><strong>de</strong>r</strong>spricht. Die erste Normalform besagt ja, dass Tabellen<br />
ke<strong>in</strong>e Wie<strong><strong>de</strong>r</strong>holgruppen enthalten dürfen und je<strong><strong>de</strong>r</strong> Wert e<strong>in</strong>es Attributs atomar<br />
se<strong>in</strong> soll. Das stim<strong>mt</strong>! Mit ANSI SQL:1999 weicht man das Relationenmo<strong>de</strong>ll <strong>in</strong><br />
bestim<strong>mt</strong>en Bereichen zugunsten pragmatischer Ansätze und <strong><strong>de</strong>r</strong> objektorientierten<br />
Softwareentwicklung auf.<br />
6.4.5 Än<strong><strong>de</strong>r</strong>n und Löschen<br />
Bis hierher haben wir gesehen, wie man Tabellen anlegt und dass man zum Beschreiben<br />
<strong><strong>de</strong>r</strong> Attribute vor<strong>de</strong>f<strong>in</strong>ierte Datentypen, benutzer<strong>de</strong>f<strong>in</strong>ierte Datentypen und<br />
Doma<strong>in</strong>s verwen<strong>de</strong>n kann. Allerd<strong>in</strong>gs haben wir diese Datenbankobjekte nur erzeugt,<br />
aber noch nicht besprochen, wie man diese löscht bzw. än<strong><strong>de</strong>r</strong>t.<br />
SQL kennt die Schlüsselworter ALTER für das Än<strong><strong>de</strong>r</strong>n und DROP für das Löschen von<br />
Datenbankobjekten. Um z.B. die Tabelle »Ort« wie<strong><strong>de</strong>r</strong> zu löschen, schreibt man:<br />
DROP TABLE Ort<br />
Was ist jedoch, wenn auf Sätze <strong><strong>de</strong>r</strong> Tabelle »Ort« noch durch Fremdschlüssel verwiesen<br />
wird? Generell gilt, dass e<strong>in</strong>e Tabelle nicht gelöscht wer<strong>de</strong>n kann, wenn e<strong>in</strong> Fremdschlüssel<br />
e<strong>in</strong>er an<strong><strong>de</strong>r</strong>en Tabelle auf <strong>de</strong>n Primärschlüssel dieser Tabelle verweist, da<br />
sonst die referenzielle Integrität verletzt wür<strong>de</strong>. Dies gilt für alle Datenbankobjekte.<br />
Datenbankobjekte, auf die an<strong><strong>de</strong>r</strong>e Datenbankobjekte verweisen, können also nicht<br />
gelöscht wer<strong>de</strong>n. D.h., bevor man e<strong>in</strong> Datenbankobjekt löschen kann, auf das verwiesen<br />
wird, müssen erst alle Datenbankobjekte gelöscht wer<strong>de</strong>n, die dieses verwen<strong>de</strong>n.<br />
Der SQL Standard bietet seit 1992 zwar die Möglichkeit, am En<strong>de</strong> <strong><strong>de</strong>r</strong> DROP-Anweisung<br />
das Schlüsselwort CASCADE anzugeben, um automatisch alle Datenbankobjekte<br />
zu löschen, die auf dieses verweisen, doch selbst die bekannten RDBMS-Produkte<br />
unterstützen diese Spracheigenschaft nicht. Die Konsequenzen e<strong>in</strong>er DROP-Anwei-
Zusammenfassung<br />
sung mit <strong><strong>de</strong>r</strong> Option CASCADE s<strong>in</strong>d manchmal sicherlich auch nicht überschaubar.<br />
Denken Sie an e<strong>in</strong> Datenbankmo<strong>de</strong>ll von mehreren tausend Tabellen, die sich gegenseitig<br />
referenzieren. Wür<strong>de</strong>n Sie nun e<strong>in</strong>e zentrale Tabelle löschen, so wür<strong>de</strong> dies das<br />
automatische Löschen aller Tabellen nach sich ziehen, die diese verwen<strong>de</strong>n. Die referenzierten<br />
Tabellen wie<strong><strong>de</strong>r</strong>um wür<strong>de</strong>n an<strong><strong>de</strong>r</strong>e Tabellen nach sich ziehen usw. Also<br />
selbst wenn CASCADE <strong>in</strong> e<strong>in</strong>em RDBMS als Spracheigenschaft für DROP unterstützt<br />
wird, sollte man es mit e<strong>in</strong>er gewissen Vorsicht verwen<strong>de</strong>n.<br />
Exemplarisch löschen wir nun noch e<strong>in</strong>mal unseren angelegten benutzer<strong>de</strong>f<strong>in</strong>ierten<br />
Datentyp und unsere Doma<strong>in</strong>:<br />
DROP DISTINCT TYPE DTyp_Plz<br />
DROP DOMAIN dom_Geschlecht<br />
Das nachträgliche Än<strong><strong>de</strong>r</strong>n e<strong>in</strong>es Datenbankobjektes ist natürlich etwas aufwändiger<br />
als das Löschen. Schauen wir uns hierzu das Än<strong><strong>de</strong>r</strong>n von E<strong>in</strong>schränkungen und Attributen<br />
e<strong>in</strong>er Tabelle an. Um e<strong>in</strong> Attribut zu löschen, verwen<strong>de</strong>t man zunächst die SQL-<br />
Anweisung ALTER TABLE gefolgt vom Tabellennamen. Danach folgt die Anweisung<br />
DROP zum Löschen e<strong>in</strong>es Attributes und dann <strong><strong>de</strong>r</strong> Attributname.<br />
ALTER TABLE Kun<strong>de</strong> DROP COLUMN Geschlecht<br />
Um die Spalte »Geschlecht« nachträglich <strong><strong>de</strong>r</strong> Tabelle wie<strong><strong>de</strong>r</strong> h<strong>in</strong>zuzufügen, schreibt<br />
man:<br />
ALTER TABLE Kun<strong>de</strong> ADD COLUMN Geschlecht CHAR(1)<br />
Entsprechend legt man Integritätsbed<strong>in</strong>gungen an bzw. löscht sie wie<strong><strong>de</strong>r</strong>. Um z.B. <strong>de</strong>n<br />
Primärschlüssel <strong><strong>de</strong>r</strong> Tabelle »Ort« zu löschen und danach wie<strong><strong>de</strong>r</strong> anzulegen, schreibt<br />
man:<br />
ALTER TABLE Ort<br />
DROP CONSTRAINT primschluessel_Ort<br />
ALTER TABLE Ort<br />
ADD CONSTRAINT primschluessel_Ort PRIMARY KEY (Plz)<br />
6.5 Zusammenfassung<br />
In diesem Kapitel haben wir gelernt, wie man e<strong>in</strong>e Datenbankstruktur mit Hilfe <strong><strong>de</strong>r</strong><br />
SQL-Anweisung CREATE TABLE anlegt. Dazu haben wir gesehen, welche vor<strong>de</strong>f<strong>in</strong>ierten<br />
Datentypen SQL bietet, und dass e<strong>in</strong>fache eigene Datentypen mit CREATE DIS-<br />
TINCT TYPE erstellt wer<strong>de</strong>n. Mit CREATE DOMAIN kann man eigene Wertebereiche<br />
erzeugen, die bestim<strong>mt</strong>en E<strong>in</strong>schränkungen entsprechen. Benutzer<strong>de</strong>f<strong>in</strong>ierte Datentypen<br />
und Doma<strong>in</strong>s können dabei überall dort e<strong>in</strong>gesetzt wer<strong>de</strong>n, wo e<strong>in</strong> Datentyp für<br />
e<strong>in</strong> Attribut festgelegt wer<strong>de</strong>n muss.<br />
Allgeme<strong>in</strong> wird die Gruppe <strong><strong>de</strong>r</strong> SQL-Anweisungen zum Anlegen von Datenbankobjekten<br />
als »Data Def<strong>in</strong>ition Language« (DDL) bezeichnet.<br />
111
112<br />
6 SQL – Anlegen <strong><strong>de</strong>r</strong> Datenbankstruktur<br />
Beim Erstellen <strong><strong>de</strong>r</strong> Tabelle haben wir auch gesehen, wie man Integritätsbed<strong>in</strong>gungen<br />
über das Schlüsselwort CONSTRAINT <strong>de</strong>f<strong>in</strong>iert. Integritätsbed<strong>in</strong>gungen dienen dazu,<br />
<strong>de</strong>m RDBMS Geschäftsregeln bekanntzugeben, damit dieses auf <strong><strong>de</strong>r</strong>en E<strong>in</strong>haltung achten<br />
kann.<br />
Am En<strong>de</strong> haben wir betrachtet, wie man diese Datenbankobjekte wie<strong><strong>de</strong>r</strong> löschen bzw.<br />
nachträglich än<strong><strong>de</strong>r</strong>n kann.<br />
Sicherlich wer<strong>de</strong>n Sie sich jetzt fragen, wie man <strong>de</strong>nn nun e<strong>in</strong>e Datenbank selbst<br />
erzeugt. ANSI SQL selbst bietet ke<strong>in</strong>e SQL-Anweisung, um leere Datenbanken anzulegen.<br />
Der Grund hierfür liegt dar<strong>in</strong> begrün<strong>de</strong>t, dass das physikalische Erzeugen e<strong>in</strong>er<br />
Datenbank zum großen Teil abhängig ist von <strong><strong>de</strong>r</strong> Computerplattform, weshalb man<br />
hierauf verzichtet hat. Dennoch bieten die meisten RDBMS-Produkte eigene SQL-<br />
Sprachelemente, um Datenbanken physikalisch zu erzeugen. In <strong><strong>de</strong>r</strong> Regel legt man<br />
e<strong>in</strong>e leere Datenbank über die Schlüsselwörter CREATE DATABASE an und kann diese<br />
über DROP DATABASE wie<strong><strong>de</strong>r</strong> löschen. Unsere Beispieldatenbank können wir also<br />
wie folgt unter <strong>de</strong>m Namen »Vertrieb« anlegen:<br />
CREATE DATABASE Vertrieb<br />
Zum Schluss noch e<strong>in</strong> H<strong>in</strong>weis zur Reihenfolge, <strong>in</strong> <strong><strong>de</strong>r</strong> Tabellen angelegt wer<strong>de</strong>n sollten.<br />
Wird beim Anlegen von Tabellen auf an<strong><strong>de</strong>r</strong>e Tabellen über Fremdschlüssel referenziert,<br />
muss darauf geachtet wer<strong>de</strong>n, zuerst die Tabellen anzulegen, auf die <strong>in</strong> an<strong><strong>de</strong>r</strong>en<br />
Tabellen Bezug genommen wird. Betrachten wir hierzu noch e<strong>in</strong>mal unser Beispiel mit<br />
<strong>de</strong>n Tabellen »Ort« und »Spielstaette« . Die Tabelle »Spielstaette« referenziert die<br />
Tabelle »Ort« über <strong>de</strong>n Fremdschlüssel »Plz« . Wür<strong>de</strong> man nun versuchen, zuerst die<br />
Tabelle »Spielstaette« unter Angabe <strong><strong>de</strong>r</strong> Fremdschlüsselbeziehung anzulegen, kom<strong>mt</strong><br />
es zwangsläufig zu e<strong>in</strong>er Fehlermeldung <strong>de</strong>s RDBMS, da die Tabelle »Ort« noch nicht<br />
existiert. Häufig legt man <strong>de</strong>shalb zunächst alle Tabellen ohne Fremdschlüsselbezug<br />
an, also ohne FOREIGN KEY-Bed<strong>in</strong>gung. Dies hat <strong>de</strong>n Vorteil, dass man beim Anlegen<br />
<strong><strong>de</strong>r</strong> Tabellen auf ke<strong>in</strong>e bestim<strong>mt</strong>e Reihenfolge achten muss. Danach <strong>de</strong>f<strong>in</strong>iert man über<br />
ALTER TABLE nachträglich alle referentiellen Integritätsbed<strong>in</strong>gungen. Für »Ort« und<br />
»Spielstaette« wür<strong>de</strong> das dann exemplarisch folgen<strong><strong>de</strong>r</strong>maßen aussehen:<br />
CREATE TABLE Spielstaette<br />
(<br />
Haus VARCHAR (100) NOT NULL ,<br />
Strasse VARCHAR (50) NOT NULL ,<br />
Hausnummer CHAR (6) ,<br />
Plz INTEGER ,<br />
Beschreibung CLOB(1M) ,<br />
CONSTRAINT primschluessel_Spielstaette PRIMARY KEY (Haus)<br />
)<br />
CREATE TABLE Ort<br />
(<br />
Plz INTEGER NOT NULL ,<br />
Ort VARCHAR (200) NOT NULL ,<br />
CONSTRAINT primschluessel_Ort PRIMARY KEY (Plz)
Aufgaben<br />
)<br />
ALTER TABLE Spielstaette ADD CONSTRAINT fremdschluessel_PlzOrt<br />
FOREIGN KEY (Plz) REFERENCES Ort (Plz)<br />
ON DELETE SET NULL<br />
ON UPDATE CASCADE<br />
Entsprechen<strong>de</strong>s gilt für benutzer<strong>de</strong>f<strong>in</strong>ierte Datentypen und Doma<strong>in</strong>s. Diese sollten<br />
natürlich vor <strong>de</strong>m Anlegen <strong><strong>de</strong>r</strong> Tabelle erstellt wer<strong>de</strong>n, <strong>in</strong> <strong><strong>de</strong>r</strong> sie verwen<strong>de</strong>t wer<strong>de</strong>n.<br />
Generell gilt also folgen<strong>de</strong> Vorgehensweise:<br />
1) Anlegen aller benutzer<strong>de</strong>f<strong>in</strong>ierter Datentypen und Doma<strong>in</strong>s;<br />
2) Erstellen <strong><strong>de</strong>r</strong> Tabellen ohne Berücksichtigung <strong><strong>de</strong>r</strong> referentiellen Integrität;<br />
3) Referentielle Integritätsbed<strong>in</strong>gungen nachträglich über ALTER TABLE <strong>de</strong>n Tabellen<br />
h<strong>in</strong>zufügen.<br />
6.6 Aufgaben<br />
Wie<strong><strong>de</strong>r</strong>holungsfragen<br />
1) Wie lautet <strong><strong>de</strong>r</strong> SQL-Befehl zum Anlegen e<strong>in</strong>er Tabelle?<br />
2) Wie lautet <strong><strong>de</strong>r</strong> SQL-Befehl zum Anlegen e<strong>in</strong>es e<strong>in</strong>fachen benutzer<strong>de</strong>f<strong>in</strong>ierten Datentyps?<br />
3) Welche numerischen Datentypen gibt es?<br />
4) Welche Zeichenketten-Datentypen gibt es?<br />
5) Geben Sie für folgen<strong>de</strong> Attribute e<strong>in</strong>en vor<strong>de</strong>f<strong>in</strong>ierten Datentyp an:<br />
»Vorname« , »Mitarbeiterfoto« , »Mitarbeiter_Lebenslauf« , »Plz« , »Gehalt«<br />
Übungen<br />
1) Die Firma »KartoF<strong>in</strong>ale« will zukünftig <strong>in</strong>ternational tätig se<strong>in</strong>. Dazu muss die<br />
Tabelle »Kun<strong>de</strong>« um e<strong>in</strong> Attribut für Land ergänzt wer<strong>de</strong>n. Wie lautet die SQL-Anweisung,<br />
um nachträglich diese Spalte h<strong>in</strong>zuzufügen?<br />
2) Die <strong>in</strong> Übung 1 erstellte Spalte »Land« soll wie<strong><strong>de</strong>r</strong> gelöscht wer<strong>de</strong>n, da man <strong>de</strong>n<br />
Wertebereich für »Land« e<strong>in</strong>schränken möchte. Dazu soll e<strong>in</strong>e Doma<strong>in</strong> erstellt wer<strong>de</strong>n,<br />
die nur Buchstaben zulässt. Wie sieht die SQL-Anweisung zum Löschen <strong><strong>de</strong>r</strong><br />
Spalte aus? Wie sieht die SQL-Anweisung zum Anlegen <strong><strong>de</strong>r</strong> Doma<strong>in</strong> aus?<br />
3) In <strong><strong>de</strong>r</strong> Tabelle »Veranstaltung« haben wir e<strong>in</strong>e Spalte für <strong>de</strong>n Autor vorgesehen.<br />
E<strong>in</strong>e Veranstaltung kann jedoch auch von mehreren Autoren se<strong>in</strong>. Wie lautet die<br />
SQL-Anweisung unter Verwendung e<strong>in</strong>es ARRAY zum Anlegen dieser Tabelle,<br />
wenn man maximal 8 Autoren pro Veranstaltung speichern möchte?<br />
4) Erstellen Sie alle Tabellen aus unserem Fallbeispiel!<br />
(H<strong>in</strong>weis: SQL-Skripte für das Fallbeispiel s<strong>in</strong>d im Internet unter »http://www.<br />
addison-wesley.<strong>de</strong>/DBMS« verfügbar)<br />
5) Erzeugen Sie die Tabellen zu <strong>de</strong>n Relationenmo<strong>de</strong>llen von Übung 3 aus Kapitel 4!<br />
113
7<br />
E<strong>in</strong>fuegen, Aen<strong><strong>de</strong>r</strong>n, Loeschen<br />
von Daten<br />
In Kapitel 7 sollen folgen<strong>de</strong> Fragen geklärt wer<strong>de</strong>n:<br />
� Wie fügt man e<strong>in</strong>en o<strong><strong>de</strong>r</strong> mehrere Datensätze <strong>in</strong> e<strong>in</strong>e Tabelle e<strong>in</strong>?<br />
� Wie löscht man e<strong>in</strong>en o<strong><strong>de</strong>r</strong> mehrere Datensätze aus e<strong>in</strong>er Tabelle?<br />
� Wie än<strong><strong>de</strong>r</strong>t man nachträglich die Werte von Spalten e<strong>in</strong>es o<strong><strong>de</strong>r</strong> mehrerer Datensätze?<br />
7.1 Motivation<br />
� Herr Dr. Fleissig hat die Datenbankstruktur für die Firma »KartoF<strong>in</strong>ale« erstellt. Für<br />
<strong>de</strong>n nächsten Tag hat er e<strong>in</strong>en Term<strong>in</strong> mit Frau Kart vere<strong>in</strong>bart. Als vorbildliche<br />
Mitarbeiter<strong>in</strong> möchte Frau Kart so bald wie möglich anfangen, die Datenbank zu<br />
verwen<strong>de</strong>n. Herr Fleissig erklärt ihr kurz, dass es zum E<strong>in</strong>fügen, Än<strong><strong>de</strong>r</strong>n und<br />
Löschen von E<strong>in</strong>trägen <strong>in</strong> die Tabellen Datenbankanweisungen gibt. Damit sie mit<br />
<strong>de</strong>m RDBMS »kommunizieren« kann, muss sie die Sprache <strong>de</strong>s RDBMS, nämlich<br />
SQL, erlernen.<br />
� Nach zwei Stun<strong>de</strong>n ist Frau Kart schließlich so weit und beg<strong>in</strong>nt die Kun<strong>de</strong>n-, Mitarbeiter-<br />
und Abteilungsdaten zu erfassen.<br />
7.2 E<strong>in</strong>fuegen von Datensaetzen<br />
Um Daten <strong>in</strong> e<strong>in</strong>e Tabelle e<strong>in</strong>zufügen, verwen<strong>de</strong>t man die SQL-Anweisung INSERT.<br />
Betrachten wir zunächst die e<strong>in</strong>fachste Variante von INSERT am Beispiel unserer<br />
Tabelle »Ort«. Das E<strong>in</strong>fügen <strong>de</strong>s Ortes Kohlscheidt mit <strong><strong>de</strong>r</strong> Postleitzahl 44444 sieht wie<br />
folgt aus:<br />
INSERT INTO Ort<br />
VALUES ( 44444, 'Kohlscheidt' )<br />
Um mehrere Sätze gleichzeitig e<strong>in</strong>zufügen, kann man die Werte mehrerer Sätze jeweils<br />
durch Klammern begrenzt angeben. Um zwei weitere Sätze <strong>in</strong> die Tabelle »Ort« e<strong>in</strong>zufügen,<br />
schreibt man:<br />
INSERT INTO Ort<br />
VALUES ( 22222, 'Karlstadt' ),<br />
( 33333, 'Rettrich' )<br />
Wir haben bisher Sätze e<strong>in</strong>gefügt, bei <strong>de</strong>nen wir die Werte aller Spalten und auch die<br />
Reihenfolgen <strong><strong>de</strong>r</strong> Spalten kennen mussten. Die Reihenfolge <strong><strong>de</strong>r</strong> Spalten ergibt sich aus<br />
<strong><strong>de</strong>r</strong> CREATE TABLE-Anweisung und entspricht <strong><strong>de</strong>r</strong> Reihenfolge, <strong>in</strong> <strong><strong>de</strong>r</strong> sie dort aufgeführt<br />
wur<strong>de</strong>n. Um nicht immer die Reihenfolge beachten zu müssen, ist es möglich,<br />
115
116<br />
7 E<strong>in</strong>fügen, Än<strong><strong>de</strong>r</strong>n, Löschen von Daten<br />
h<strong>in</strong>ter <strong>de</strong>m Tabellennamen die Spaltennamen <strong>in</strong> Klammern aufzuführen, <strong><strong>de</strong>r</strong>en Werte<br />
h<strong>in</strong>ter <strong>de</strong>m Schlüsselwort VALUES folgen. Betrachten wir hierzu die Tabelle Kun<strong>de</strong>.<br />
Wir wollen die Kund<strong>in</strong> Frieda Wiegerich <strong>in</strong> die Tabelle Kun<strong>de</strong> e<strong>in</strong>fügen. Da beim Anlegen<br />
<strong><strong>de</strong>r</strong> Tabelle Kun<strong>de</strong> das Geschlecht ‚W' für weiblich als Vorgabewert <strong>de</strong>f<strong>in</strong>iert<br />
wur<strong>de</strong>, brauchen wir diese Spalte beim E<strong>in</strong>fügen nicht mit anzugeben. Die Hausnummer<br />
dieser Kund<strong>in</strong> ist uns nicht bekannt, also lassen wir diese vorerst weg. Die SQL-<br />
Anweisung dazu lautet:<br />
INSERT INTO Kun<strong>de</strong> (Name, Vorname, Strasse, Plz, Kun<strong>de</strong>nnummer)<br />
VALUES ( 'Wiegerich', 'Frieda', 'Wan<strong><strong>de</strong>r</strong>str.', 33333, 3 )<br />
Unsere Tabelle Kun<strong>de</strong> sieht danach wie folgt aus:<br />
Kun<strong>de</strong>nnummer<br />
3<br />
Name<br />
Wiegerich<br />
Vorname<br />
Frieda<br />
Abbildung 7.1: Tabelle Kun<strong>de</strong><br />
Die Kun<strong>de</strong>nnummer ist <strong>in</strong> dieser INSERT-Anweisung zum Schluss aufgeführt, also<br />
entspricht die Zahl 3 <strong><strong>de</strong>r</strong> Kun<strong>de</strong>nnummer. Ohne Angabe <strong><strong>de</strong>r</strong> Spaltennamen hätte <strong><strong>de</strong>r</strong><br />
Wert für die Kun<strong>de</strong>nnummer <strong>in</strong> <strong><strong>de</strong>r</strong> SQL-Anweisung an erster Stelle stehen müssen.<br />
Doch wie kann <strong><strong>de</strong>r</strong> Satz ohne Angabe <strong><strong>de</strong>r</strong> Spaltennamen e<strong>in</strong>gefügt wer<strong>de</strong>n. Dazu verwen<strong>de</strong>t<br />
man das Schlüsselwort DEFAULT, um explizit <strong>de</strong>n Vorgabewert zu verwen<strong>de</strong>n<br />
o<strong><strong>de</strong>r</strong> das Schlüsselwort NULL, um e<strong>in</strong>en Wert als unbekannt zu kennzeichnen. Die folgen<strong>de</strong><br />
INSERT-Anweisung entspricht damit <strong><strong>de</strong>r</strong> oberen, ist nur etwas länger:<br />
INSERT INTO Kun<strong>de</strong><br />
VALUES ( 3, 'Wiegerich', 'Frieda',<br />
DEFAULT, 'Wan<strong><strong>de</strong>r</strong>str.', NULL, 33333 )<br />
Geschlecht Strasse<br />
Hausnummer<br />
Plz<br />
W Wan<strong><strong>de</strong>r</strong>str. NULL 33333<br />
Was geschieht aber nun, wenn e<strong>in</strong> Kun<strong>de</strong> mit e<strong>in</strong>er Postleitzahl e<strong>in</strong>gefügt wird, die als<br />
Primärschlüssel <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »Ort« noch nicht e<strong>in</strong>gefügt ist? Die Antwort hierzu sollte<br />
nicht schwer fallen: Das E<strong>in</strong>fügen wird natürlich vom RDBMS zurückgewiesen, da die<br />
referentielle Integrität verletzt wur<strong>de</strong>. Sie sehen also, wie wichtig es ist, solche Integritätsregeln<br />
im RDBMS zu <strong>de</strong>klarieren. Je mehr das RDBMS an Geschäftsregeln kennt,<br />
um so besser kann es die Datenbank vor <strong>in</strong>konsistenten Daten schützen. Referentielle<br />
Integrität ist dabei natürlich nur e<strong>in</strong>e Möglichkeit, Geschäftsregeln <strong>de</strong>m RDBMS<br />
bekannt zu geben. Wir wer<strong>de</strong>n im weiteren Verlauf <strong>de</strong>s Buches viele Möglichkeiten<br />
kennen lernen, solche E<strong>in</strong>schränkungen im RDBMS umzuzsetzen.<br />
Zur Übung wollen wir nun noch drei weitere Kun<strong>de</strong>n e<strong>in</strong>fügen. Die Anweisung dazu<br />
sieht folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
INSERT INTO Kun<strong>de</strong> (Kun<strong>de</strong>nnummer, Name, Vorname, Geschlecht,<br />
Strasse, Hausnummer, Plz)<br />
VALUES ( 1, 'Bolte', 'Bertram', 'M', 'Busweg', '12', 44444 ),<br />
( 2, 'Muster', 'Hans', 'M', 'Musterweg', '12', 22222 ),<br />
( 4, 'Carlson', 'Peter', 'M', 'Petristr.', '201', 44444 )
Löschen von Datensätzen<br />
Unsere Kun<strong>de</strong>ntabelle besteht zur Zeit aus vier Datensätzen und sieht folgen<strong><strong>de</strong>r</strong>maßen<br />
aus:<br />
Kun<strong>de</strong>nnummer<br />
1<br />
2<br />
3<br />
4<br />
7.3 Löschen von Datensätzen<br />
Nach<strong>de</strong>m wir das E<strong>in</strong>fügen von Datensätzen gelernt haben, wollen wir uns nun<br />
anschauen, wie man Sätze wie<strong><strong>de</strong>r</strong> aus e<strong>in</strong>er Tabelle löscht. Hierfür gibt es die SQL-<br />
Anweisung DELETE. In <strong><strong>de</strong>r</strong> e<strong>in</strong>fachsten Form sieht die DELETE-Anweisung wie folgt<br />
aus:<br />
DELETE FROM Kun<strong>de</strong><br />
Name<br />
Bolte<br />
Muster<br />
Wiegerich<br />
Carlson<br />
Vorname<br />
Bertram<br />
Hans<br />
Frieda<br />
Peter<br />
Abbildung 7.2: Kun<strong>de</strong>ntabelle<br />
Diese SQL-Anweisung sollte mit e<strong>in</strong>er gewissen Vorsicht verwen<strong>de</strong>t wer<strong>de</strong>n, da sie alle<br />
Sätze <strong><strong>de</strong>r</strong> Tabelle Kun<strong>de</strong> löscht. Wür<strong>de</strong> man diese SQL-Anweisung ausführen, so wäre<br />
die Tabelle danach wie<strong><strong>de</strong>r</strong> leer und wür<strong>de</strong> ke<strong>in</strong>e Kun<strong>de</strong>ndaten mehr enthalten.<br />
H<strong>in</strong>ter <strong><strong>de</strong>r</strong> Angabe <strong><strong>de</strong>r</strong> Tabelle, aus <strong><strong>de</strong>r</strong> Datensätze gelöscht wer<strong>de</strong>n sollen, kann<br />
genauer spezifiziert wer<strong>de</strong>n, welche Datensätze gelöscht wer<strong>de</strong>n sollen. Dazu verwen<strong>de</strong>t<br />
man das Schlüsselwort WHERE. Um z.B. alle Datensätze zu löschen, bei <strong>de</strong>nen die<br />
Hausnummer <strong><strong>de</strong>r</strong> Zeichenfolge ‚12' entspricht, wür<strong>de</strong> die SQL-Anweisung folgen<strong><strong>de</strong>r</strong>maßen<br />
aussehen:<br />
DELETE FROM Kun<strong>de</strong> WHERE Hausnummer = '12'<br />
Geschlecht<br />
Strasse<br />
Busweg<br />
Musterweg<br />
Wan<strong><strong>de</strong>r</strong>str.<br />
Petristr.<br />
Diese SQL-Anweisung bewirkt, dass die Sätze mit <strong>de</strong>n Kun<strong>de</strong>nnummern 1 und 2<br />
gelöscht wer<strong>de</strong>n, da bei diesen bei<strong>de</strong>n Sätzen die Hausnummer 12 ist. H<strong>in</strong>ter <strong><strong>de</strong>r</strong><br />
WHERE-Klausel können Bed<strong>in</strong>gungen beliebig mite<strong>in</strong>an<strong><strong>de</strong>r</strong> verknüpft wer<strong>de</strong>n. Hier<br />
gibt es sehr viele Möglichkeiten, genau zu spezifizieren, welche Sätze ausgewählt wer<strong>de</strong>n<br />
sollen. Da wir dies noch genauer beim Abfragen von Datensätzen ab Kapitel 8 kennen<br />
lernen wer<strong>de</strong>n, wollen wir uns vorerst e<strong>in</strong>fach drei Beispiele ansehen und es damit<br />
erst e<strong>in</strong>mal belassen:<br />
DELETE FROM Kun<strong>de</strong> WHERE Hausnummer = '12' AND Name = 'Bolte'<br />
DELETE FROM Kun<strong>de</strong> WHERE Hausnummer = '12' OR Plz = 44444<br />
DELETE FROM Kun<strong>de</strong> WHERE Plz IN ( 44444, 22222 )<br />
Hausnummer<br />
12<br />
12<br />
NULL<br />
201<br />
Die erste Anweisung löscht alle Sätze, bei <strong>de</strong>nen die Hausnummer 12 ist und gleichzeitig<br />
<strong><strong>de</strong>r</strong> Kun<strong>de</strong> <strong>de</strong>n Nachnamen Bolte hat. Die zweite Anweisung löscht alle Kun<strong>de</strong>n,<br />
die <strong>in</strong> e<strong>in</strong>em Ort mit <strong><strong>de</strong>r</strong> Postleitzahl 44444 wohnen und alle Kun<strong>de</strong>n mit <strong><strong>de</strong>r</strong> Haus-<br />
M<br />
M<br />
W<br />
M<br />
Plz<br />
44444<br />
22222<br />
33333<br />
44444<br />
117
118<br />
7 E<strong>in</strong>fügen, Än<strong><strong>de</strong>r</strong>n, Löschen von Daten<br />
nummer 12. Die letzte Anweisung löscht schließlich alle Kun<strong>de</strong>n, die <strong>in</strong> Orten mit <strong>de</strong>n<br />
Postleitzahlen 44444 o<strong><strong>de</strong>r</strong> 22222 wohnen.<br />
Abschließend noch <strong><strong>de</strong>r</strong> H<strong>in</strong>weis, dass z.B. das Löschen e<strong>in</strong>es Ortes mit e<strong>in</strong>er Postleitzahl,<br />
die noch von e<strong>in</strong>em Kun<strong>de</strong>nsatz verwen<strong>de</strong>t wird, vom RDBMS abgelehnt wird.<br />
Auch hier greift natürlich wie<strong><strong>de</strong>r</strong> die Beziehung zwischen Primär- und Fremdschlüssel.<br />
7.4 Än<strong><strong>de</strong>r</strong>n von Datensätzen<br />
In Abschnitt 7.1 haben wir die Kund<strong>in</strong> Frieda Wiegerich <strong>in</strong> die Kun<strong>de</strong>ntabelle e<strong>in</strong>gefügt,<br />
ohne <strong><strong>de</strong>r</strong>en Hausnummer zu kennen. Inzwischen haben wir erfahren, dass die<br />
Hausnummer <strong><strong>de</strong>r</strong> Kund<strong>in</strong> <strong>de</strong>n Wert 89 hat. Dies wollen wir jetzt nachträglich e<strong>in</strong>tragen.<br />
Hierzu verwen<strong>de</strong>n wir die SQL-Anweisung UPDATE. Die e<strong>in</strong>fachste Form <strong><strong>de</strong>r</strong><br />
UPDATE-Anweisung wird, wie bei <strong><strong>de</strong>r</strong> DELETE-Anweisung auch, ohne die WHERE-<br />
Klausel verwen<strong>de</strong>t, so dass e<strong>in</strong>e Än<strong><strong>de</strong>r</strong>ung sich auf alle Sätze bezieht. Die Anweisung<br />
UPDATE Kun<strong>de</strong><br />
SET Geschlecht = 'M'<br />
setzt <strong>de</strong>mnach das Geschlecht aller Kun<strong>de</strong>n auf ‚M' für männlich. Entsprechend sollte<br />
man genau überlegen, wann die Anweisung UPDATE <strong>in</strong> dieser Form angewen<strong>de</strong>t wer<strong>de</strong>n<br />
soll.<br />
Doch zurück zu unserer Kund<strong>in</strong> Frau Wiegerich. Zum Än<strong><strong>de</strong>r</strong>n <strong><strong>de</strong>r</strong> Hausnummer lautet<br />
die SQL-Anweisung:<br />
UPDATE Kun<strong>de</strong><br />
SET Hausnummer = '89'<br />
WHERE Name = 'Wiegerich'<br />
Doch was wür<strong>de</strong> passieren, gäbe es mehrere Kun<strong>de</strong>n mit <strong>de</strong>m Nachnamen Wiegerich?<br />
Alle Kun<strong>de</strong>n, die diesen Nachnamen besitzen, bekämen als Adresse die Hausnummer<br />
89 zugewiesen. Zur Vermeidung dieses Problems kom<strong>mt</strong> <strong><strong>de</strong>r</strong> Primärschlüssel wie<strong><strong>de</strong>r</strong><br />
zum Tragen. Um für e<strong>in</strong>en ganz bestim<strong>mt</strong>en Kun<strong>de</strong>n Werte zu än<strong><strong>de</strong>r</strong>n, sollte man <strong>de</strong>n<br />
Primärschlüssel <strong>in</strong> <strong><strong>de</strong>r</strong> Bed<strong>in</strong>gung h<strong>in</strong>ter <strong><strong>de</strong>r</strong> WHERE-Klausel verwen<strong>de</strong>n. Die folgen<strong>de</strong><br />
Anweisung wäre <strong>de</strong>shalb besser geeignet, die Hausnummer von Frieda Wiegerich<br />
zu än<strong><strong>de</strong>r</strong>n:<br />
UPDATE Kun<strong>de</strong><br />
SET Hausnummer = '89'<br />
WHERE Kun<strong>de</strong>nnummer = 3<br />
Da Kun<strong>de</strong>nnummer <strong><strong>de</strong>r</strong> Primärschlüssel <strong><strong>de</strong>r</strong> Tabelle Kun<strong>de</strong> ist, kann e<strong>in</strong> Kun<strong>de</strong> mit <strong><strong>de</strong>r</strong><br />
Kun<strong>de</strong>nnummer 3 nur e<strong>in</strong>mal vorkommen. Schließlich ist <strong><strong>de</strong>r</strong> Primärschlüssel, wie wir<br />
ja gelernt haben, immer e<strong>in</strong><strong>de</strong>utig und darf niemals NULL se<strong>in</strong>. Entsprechend hat<br />
durch die obige SQL-Anweisung auch nur e<strong>in</strong> Satz die Hausnummer 89 zugewiesen<br />
bekommen.
Än<strong><strong>de</strong>r</strong>n von Datensätzen<br />
Um mehrere Spalten e<strong>in</strong>es Satzes zu än<strong><strong>de</strong>r</strong>n gibt es zwei Möglichkeiten. Entwe<strong><strong>de</strong>r</strong><br />
schreibt man durch Kommata getrennt, die Spalten und jeweiligen Werte o<strong><strong>de</strong>r</strong> man<br />
verwen<strong>de</strong>t das Schlüsselwort ROW, mit <strong>de</strong>m man e<strong>in</strong>en ganzen Satz komplett än<strong><strong>de</strong>r</strong>n<br />
kann. Frau Wiegerich ist umgezogen und ihre Adresse soll geän<strong><strong>de</strong>r</strong>t wer<strong>de</strong>n. Außer<strong>de</strong>m<br />
s<strong>in</strong>d Vor- und Nachname falsch geschrieben. Das Ergebnis folgen<strong><strong>de</strong>r</strong> SQL-Anweisungen<br />
ist i<strong>de</strong>ntisch:<br />
UPDATE Kun<strong>de</strong><br />
SET Kun<strong>de</strong>nnummer = 3,<br />
Name = 'Wegerich',<br />
Vorname = 'Frida',<br />
Geschlecht = 'W',<br />
Strasse = 'Spatzenweg',<br />
Hausnummer = '81',<br />
Plz = 33333<br />
WHERE Kun<strong>de</strong>nnummer = 3<br />
UPDATE Kun<strong>de</strong><br />
SET ROW =<br />
ROW(3, 'Wegerich', 'Frida', 'W', 'Spatzenweg', '81', 33333)<br />
WHERE Kun<strong>de</strong>nnummer = 3<br />
Wie auch für die DELETE-Anweisung gilt, dass <strong><strong>de</strong>r</strong> WHERE-Klausel wesentlich kompliziertere<br />
Bed<strong>in</strong>gungen zur E<strong>in</strong>schränkung <strong><strong>de</strong>r</strong> Ergebnismenge folgen können. Da wir<br />
dies jedoch ausführlich beim Abfragen von Tabellen behan<strong>de</strong>ln, wollen wir exemplarisch<br />
nur drei weitere Beispiele betrachten:<br />
UPDATE Werbeartikel<br />
SET Lagerbestand = Lagerbestand – 6<br />
WHERE Artikelnummer = 1001<br />
UPDATE Werbeartikel<br />
SET Preis = Preis * 1.10<br />
WHERE Preis < 9.99<br />
UPDATE Bestellung<br />
SET Datum = CURRENT_DATE,<br />
Personalnummer = 2<br />
WHERE Kun<strong>de</strong>nnummer = 3<br />
Im ersten Beispiel können wir sehen, dass man <strong>in</strong> SQL-Anweisungen auch e<strong>in</strong>fache<br />
Berechnungen vornehmen kann. In diesem Beispiel wird <strong><strong>de</strong>r</strong> Lagerbestand für <strong>de</strong>n<br />
Artikel mit <strong><strong>de</strong>r</strong> Artikelnummer 1001 um 6 reduziert. Im zweiten Fall wer<strong>de</strong>n alle<br />
Datensätze geän<strong><strong>de</strong>r</strong>t, bei <strong>de</strong>nen <strong><strong>de</strong>r</strong> Artikel mehr als 9.99 Euro kostet und <strong><strong>de</strong>r</strong> Preis um<br />
10 Prozent erhöht.<br />
Das dritte Beispiel schließlich soll noch e<strong>in</strong>mal die Verwendung von vor<strong>de</strong>f<strong>in</strong>ierten Werten<br />
ver<strong>de</strong>utlichen. Anstatt das aktuelle Datum direkt als Literal anzugeben, kann das<br />
aktuelle Datum über CURRENT_DATE <strong>in</strong> <strong><strong>de</strong>r</strong> UPDATE-Anweisung ermittelt wer<strong>de</strong>n.<br />
119
7.5 Zusammenfassung<br />
120<br />
7 E<strong>in</strong>fügen, Än<strong><strong>de</strong>r</strong>n, Löschen von Daten<br />
Wir haben <strong>in</strong> diesem Kapitel alle SQL-Anweisungen zum E<strong>in</strong>fügen, Än<strong><strong>de</strong>r</strong>n und<br />
Löschen von Datensätzen kennen gelernt. Allgeme<strong>in</strong> bezeichnet man diese Gruppe<br />
von SQL-Anweisungen auch als »Data Manipulation Language« (DML).<br />
Zum E<strong>in</strong>fügen von Datensätzen verwen<strong>de</strong>t man die INSERT-Anweisung. Entwe<strong><strong>de</strong>r</strong><br />
kann man <strong>in</strong> dieser Anweisung explizit die Spalten aufführen, für die Werte angeben<br />
wer<strong>de</strong>n sollen o<strong><strong>de</strong>r</strong> man führt alle Werte für e<strong>in</strong>en Datensatz auf, <strong>in</strong> <strong><strong>de</strong>r</strong> Reihenfolge, <strong>in</strong><br />
<strong><strong>de</strong>r</strong> die Spalten <strong>in</strong> <strong><strong>de</strong>r</strong> CREATE TABLE-Anweisung angegeben wur<strong>de</strong>n. Um <strong>de</strong>n Vorgabewert<br />
e<strong>in</strong>zufügen, verwen<strong>de</strong>t man das Schlüsselwort DEFAULT, um e<strong>in</strong>en Wert als<br />
nicht bekannt zu kennzeichnen, NULL.<br />
Zum Löschen von Datensätzen ist die DELETE-Anweisung geeignet. Ohne Verwendung<br />
<strong><strong>de</strong>r</strong> WHERE-Klausel wer<strong>de</strong>n alle Datensätze e<strong>in</strong>er Tabelle gelöscht. Durch die<br />
Angabe von Bed<strong>in</strong>gungen h<strong>in</strong>ter <strong><strong>de</strong>r</strong> WHERE-Klausel wird festgelegt, welche Datensätze<br />
gelöscht wer<strong>de</strong>n sollen.<br />
Als letzte SQL-Anweisung haben wir zum Än<strong><strong>de</strong>r</strong>n von Datensätzen UPDATE kennen<br />
gelernt. Wie bei <strong><strong>de</strong>r</strong> DELETE-Anweisung auch, schränkt man die Anzahl <strong><strong>de</strong>r</strong> zu<br />
än<strong><strong>de</strong>r</strong>n<strong>de</strong>n Sätze durch die WHERE-Klausel e<strong>in</strong>.<br />
Für alle Anweisungen gilt, dass das E<strong>in</strong>fügen, Än<strong><strong>de</strong>r</strong>n o<strong><strong>de</strong>r</strong> Löschen von Datensätzen<br />
vom RDBMS zurückgewiesen wird, sofern festgelegte Integritätsbed<strong>in</strong>gungen verletzt<br />
wer<strong>de</strong>n. Dadurch wird verh<strong>in</strong><strong><strong>de</strong>r</strong>t, dass die Datenbank <strong>in</strong>konsistent o<strong><strong>de</strong>r</strong> <strong>in</strong>korrekt<br />
wird. Bevor also z.B. e<strong>in</strong> Kun<strong>de</strong> e<strong>in</strong>gefügt wird, muss sichergestellt se<strong>in</strong>, dass <strong><strong>de</strong>r</strong> Ort,<br />
<strong>in</strong> <strong>de</strong>m <strong><strong>de</strong>r</strong> Kun<strong>de</strong> wohnhaft ist, bereits <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle Ort existiert. An<strong><strong>de</strong>r</strong>nfalls muss<br />
<strong><strong>de</strong>r</strong> Ort neu e<strong>in</strong>gefügt wer<strong>de</strong>n, damit die referentielle Integrität gewährleistet ist.<br />
7.6 Aufgaben<br />
Wie<strong><strong>de</strong>r</strong>holungsfragen<br />
1) Wie lauten die SQL-Anweisungen zum Löschen, Än<strong><strong>de</strong>r</strong>n und E<strong>in</strong>fügen von Datensätzen<br />
<strong>in</strong> Tabellen?<br />
2) Was ist mit <strong>de</strong>m Schlüsselwort DEFAULT geme<strong>in</strong>t und <strong>in</strong> welchen <strong><strong>de</strong>r</strong> drei kennen<br />
gelernten SQL-Anweisungen kann es verwen<strong>de</strong>t wer<strong>de</strong>n?<br />
3) Was ist mit NULL geme<strong>in</strong>t?<br />
Übungen<br />
1) Der Preis für Sitzplätze <strong><strong>de</strong>r</strong> Reihen 1-3 soll um 15% erhöht wer<strong>de</strong>n. Wie lautet die<br />
SQL-Anweisung?<br />
2) Der Sitzplatz (Reihe 6, Sitz 2) im Bereich »Parkett« für die Vorstellung mit <strong><strong>de</strong>r</strong> Nummer<br />
22 soll als »belegt« gekennzeichnet wer<strong>de</strong>n. Wie lautet die SQL-Anweisung?<br />
3) Die Spielstätte »Vergissme<strong>in</strong>nicht« hat Konkurs angemel<strong>de</strong>t. Alle Vorstellungen<br />
s<strong>in</strong>d abgesagt wor<strong>de</strong>n. Wie lautet die SQL-Anweisung zum Löschen <strong><strong>de</strong>r</strong> Spielstätte?<br />
Was geschieht mit <strong>de</strong>n Sätzen <strong><strong>de</strong>r</strong> Vorstellungen, die sich auf diese Spielstätte<br />
beziehen. Müssen diese explizit gelöscht wer<strong>de</strong>n?
Aufgaben<br />
1) Die Firma »KartoF<strong>in</strong>ale« will mit ihrer neu entwickelten Datenbank <strong>in</strong> Produktion<br />
gehen. Dazu müssen zunächst die Kun<strong>de</strong>n- und Vorstellungsdaten <strong>in</strong> die Datenbank<br />
e<strong>in</strong>gefügt wer<strong>de</strong>n. Fügen Sie die folgen<strong>de</strong>n Datensätze <strong>in</strong> die jeweiligen Tabellen<br />
e<strong>in</strong>. Beachten Sie die referenzielle Integrität, d.h. bevor Sie z.B. e<strong>in</strong>e Vorstellung<br />
e<strong>in</strong>fügen können, muss die entsprechen<strong>de</strong> Veranstaltung e<strong>in</strong>gefügt se<strong>in</strong> und die<br />
Spielstätte, <strong>in</strong> <strong><strong>de</strong>r</strong> die Vorstellung stattf<strong>in</strong><strong>de</strong>t.<br />
Kun<strong>de</strong><br />
Kun<strong>de</strong>nnummer<br />
1<br />
2<br />
3<br />
4<br />
K<strong>in</strong>d<br />
Kun<strong>de</strong>nnummer<br />
1<br />
1<br />
1<br />
3<br />
3<br />
Mitarbeiter<br />
Personalnummer<br />
3<br />
5<br />
6<br />
Abteilung<br />
Abteilungsbezeichnung<br />
Vertrieb<br />
Name<br />
Kart<br />
Kle<strong>in</strong><br />
Kowalski<br />
Geschäftsführung<br />
Name<br />
Bolte<br />
Muster<br />
Wiegerich<br />
Carlson<br />
Vorname<br />
Katja<br />
Ursula<br />
Karl<br />
Ursula<br />
Enzo<br />
Vorname<br />
Karen<br />
Karl<br />
Karsten<br />
Abteilungsnummer<br />
1<br />
2<br />
Vorname<br />
Bertram<br />
Hans<br />
Frieda<br />
Peter<br />
Geburtsdatum<br />
1988-12-31<br />
1990-05-08<br />
2001-05-21<br />
1992-08-19<br />
1990-05-12<br />
Geschlecht<br />
W<br />
M<br />
M<br />
Geschlecht<br />
M<br />
M<br />
W<br />
M<br />
Personalnummer-<br />
Abteilungsleiter<br />
3<br />
6<br />
Strasse<br />
Pantherstr.<br />
M<strong>in</strong>imalweg<br />
Geschlecht<br />
W<br />
W<br />
M<br />
W<br />
M<br />
Blankeneser Weg<br />
Strasse<br />
Busweg<br />
Musterweg<br />
Wan<strong><strong>de</strong>r</strong>str.<br />
Petristr.<br />
Hausnummer<br />
12<br />
Abbildung 7.3: Datensätze<br />
1<br />
2<br />
Strassennummer<br />
Plz<br />
22222<br />
22222<br />
22287<br />
12<br />
12<br />
NULL<br />
201<br />
Plz<br />
44444<br />
22222<br />
33333<br />
44444<br />
Abteilungsbezeichnung<br />
Vertrieb<br />
Vertrieb<br />
Geschäftsführung<br />
Geburtsdatum<br />
1945-12-02<br />
1953-02-21<br />
1963-08-18<br />
1971-09-26<br />
Personalnummervorgesetzter<br />
6<br />
3<br />
NULL<br />
Gehalt<br />
3000<br />
2050<br />
4000<br />
121
Ort Spielstaette<br />
122<br />
Plz<br />
44444<br />
22222<br />
33333<br />
22287<br />
25746<br />
Ort<br />
Kohlscheidt<br />
Karlstadt<br />
Rettrich<br />
Hamburg<br />
Hei<strong>de</strong><br />
Veranstaltung<br />
Veranstaltungsnummer<br />
1<br />
4<br />
3<br />
8<br />
7 E<strong>in</strong>fügen, Än<strong><strong>de</strong>r</strong>n, Löschen von Daten<br />
Haus<br />
Deutsche Staatsoper<br />
Bezeichnung<br />
Don Giovanni<br />
Operettenhaus<br />
Sokratesbühne<br />
Nordseehalle<br />
Kongresshalle<br />
Phil Coll<strong>in</strong>s LIVE<br />
Zauberlehrl<strong>in</strong>g<br />
Mutter Courage<br />
Strasse<br />
Opernstr.<br />
Bahndamm<br />
Musterweg<br />
Nordfeldweg<br />
Hausnummer<br />
Abbildung 7.4: Weitere Datensätze<br />
1<br />
88<br />
81<br />
200<br />
Plz<br />
22287<br />
22287<br />
22222<br />
25746<br />
Beschreibung<br />
NULL<br />
NULL<br />
NULL<br />
NULL<br />
Hahndamm 21 33333 NULL<br />
Autor<br />
Ama<strong>de</strong>us Mozart<br />
Phil Coll<strong>in</strong>s<br />
Ama<strong>de</strong>us Mozart<br />
Brecht<br />
7 Cats<br />
Webber<br />
Vorstellung<br />
Vorstellungsnummer<br />
11<br />
12<br />
13<br />
31<br />
Datum<br />
2002-07-21<br />
2002-07-28<br />
2002-08-04<br />
2002-01-05<br />
Uhrzeit<br />
20.00<br />
19.30<br />
19.30<br />
21.30<br />
32 2002-01-06<br />
21.30<br />
41 2002-07-21<br />
18.45<br />
42 2002-08-01<br />
19.00<br />
44 2002-09-18<br />
19.15<br />
81 2002-01-31<br />
19.30<br />
82 2002-02-28<br />
19.30<br />
85 2002-03-31<br />
20.00<br />
86 2002-04-30<br />
20.00<br />
87 2002-05-31<br />
20.00<br />
Beschreibung<br />
NULL<br />
NULL<br />
NULL<br />
NULL<br />
NULL<br />
Veranstaltungsnummer<br />
1<br />
1<br />
1<br />
3<br />
3<br />
4<br />
4<br />
4<br />
8<br />
8<br />
8<br />
8<br />
8<br />
Haus<br />
Hamburg Opernhaus<br />
Hamburg Opernhaus<br />
Hamburg Opernhaus<br />
Operettenhaus<br />
Operettenhaus<br />
Nordseehalle<br />
Kongresshalle<br />
Hamburg Opernhaus<br />
Sokratesbühne<br />
Sokratesbühne<br />
Sokratesbühne<br />
Sokratesbühne<br />
Sokratesbühne
Artikel<br />
Artikelnummer<br />
1001<br />
1003<br />
1012<br />
1081<br />
1078<br />
1077<br />
1101<br />
1102<br />
1103<br />
1104<br />
1105<br />
1201<br />
1202<br />
1203<br />
1204<br />
1205<br />
4101<br />
4102<br />
4103<br />
4104<br />
4105<br />
4106<br />
Bestellung<br />
Bestellnummer<br />
1<br />
3<br />
8<br />
Bezeichnung<br />
Noten Don Giovanni<br />
Mozart T-Shirt<br />
CD: Phil Coll<strong>in</strong>s<br />
Zauberstock<br />
Opernführer<br />
Cats-Plakat<br />
Don Giovanni<br />
Don Giovanni<br />
Don Giovanni<br />
Don Giovanni<br />
Don Giovanni<br />
Don Giovanni<br />
Don Giovanni<br />
Don Giovanni<br />
Don Giovanni<br />
Don Giovanni<br />
Konzert von Phil Coll<strong>in</strong>s<br />
Konzert von Phil Coll<strong>in</strong>s<br />
Konzert von Phil Coll<strong>in</strong>s<br />
Konzert von Phil Coll<strong>in</strong>s<br />
Konzert von Phil Coll<strong>in</strong>s<br />
Konzert von Phil Coll<strong>in</strong>s<br />
Datum<br />
2002-01-26<br />
2002-02-08<br />
2001-12-21<br />
Kun<strong>de</strong>nnummer<br />
1<br />
3<br />
2<br />
Werbeartikel<br />
Artikelnummer<br />
1001<br />
1003<br />
1012<br />
1081<br />
1077<br />
Sitzplatz<br />
Artikelnummer<br />
1101<br />
1102<br />
1103<br />
1104<br />
1105<br />
1201<br />
1202<br />
1203<br />
1204<br />
1205<br />
Aufgaben<br />
Beschreibung<br />
Noten f. Klavier<br />
T-Shirt Farbe: rot<br />
Phil Coll<strong>in</strong>s <strong>in</strong> Concert<br />
Schwarzer Zauberstock<br />
Plakat mit <strong>de</strong>n Musical-Katzen<br />
Bereich<br />
Parkett<br />
Parkett<br />
1. Rang<br />
2. Rang<br />
3. Rang<br />
Parkett<br />
Parkett<br />
1. Rang<br />
2. Rang<br />
3. Rang<br />
Reihe<br />
Abbildung 7.5: Artikel und Bestellung<br />
2<br />
4<br />
1<br />
3<br />
7<br />
2<br />
4<br />
1<br />
3<br />
7<br />
Sitz<br />
8<br />
11<br />
12<br />
2<br />
1<br />
8<br />
11<br />
12<br />
2<br />
1<br />
Preis<br />
89.00<br />
29.99<br />
20.00<br />
5.99<br />
33.50<br />
1078 Opernführer 19.99<br />
Preis<br />
89.00<br />
89.00<br />
120.00<br />
75.00<br />
60.00<br />
89.00<br />
89.00<br />
120.00<br />
75.00<br />
60.00<br />
4101 Parkett 1 1 120.00<br />
4102 Parkett 1 2 120.00<br />
4103 Parkett 1 3 120.00<br />
4104 Parkett 11 14 60.00<br />
4105 Parkett 3 21 90.00<br />
4106 Parkett 8 26 85.99<br />
Personalnummer<br />
NULL<br />
NULL<br />
NULL<br />
Bestellposten<br />
Bestellnummer<br />
1<br />
1<br />
1<br />
1<br />
1<br />
8<br />
Positionsnummer<br />
1<br />
1<br />
1<br />
2<br />
3<br />
1<br />
Lagerbestand<br />
Zustand<br />
belegt<br />
frei<br />
frei<br />
belegt<br />
reserviert<br />
belegt<br />
frei<br />
frei<br />
belegt<br />
reserviert<br />
frei<br />
frei<br />
frei<br />
frei<br />
frei<br />
frei<br />
26<br />
11<br />
21<br />
32<br />
89<br />
9999<br />
Artikelnummer<br />
1101<br />
1102<br />
1103<br />
1001<br />
1003<br />
4101<br />
Vorstellungs<br />
-nummer<br />
11<br />
11<br />
11<br />
11<br />
11<br />
12<br />
12<br />
12<br />
12<br />
12<br />
41<br />
41<br />
41<br />
41<br />
41<br />
41<br />
Menge<br />
8 2 1012 2<br />
1<br />
1<br />
1<br />
2<br />
3<br />
1<br />
123
8 E<strong>in</strong>e Tabelle abfragen<br />
In Kapitel 8 sollen folgen<strong>de</strong> Fragen geklärt wer<strong>de</strong>n:<br />
� Wie wer<strong>de</strong>n Tabellen e<strong>in</strong>er Datenbank generell abgefragt?<br />
� Wie sieht <strong><strong>de</strong>r</strong> Aufbau <strong><strong>de</strong>r</strong> SQL-Anweisung zur Abfrage aus?<br />
� Wie gibt man <strong>de</strong>n Inhalt e<strong>in</strong>er Tabelle aus?<br />
� Wie gibt man an, welche Spalten e<strong>in</strong>er Tabelle man ausgegeben haben möchte?<br />
� Welche Funktionen kann man auf Spalten anwen<strong>de</strong>n?<br />
� Wie sagt man <strong>de</strong>m RDBMS, welche Sätze es f<strong>in</strong><strong>de</strong>n soll?<br />
� Welche Bed<strong>in</strong>gungsausdrücke gibt es?<br />
� Wie sortiert man die Ergebnismenge?<br />
� Wie gruppiert man Sätze <strong><strong>de</strong>r</strong> Ergebnismenge?<br />
8.1 Motivation<br />
Inzwischen ist e<strong>in</strong>e Woche vergangen und Frau Kart hat alle Kun<strong>de</strong>n, Mitarbeiter, Vorstellungen<br />
und Bestellungen <strong><strong>de</strong>r</strong> Firma »KartoF<strong>in</strong>ale« <strong>in</strong> die Datenbank übernommen.<br />
Mit Herrn Dr. Fleissig hat sie <strong>de</strong>shalb für heute e<strong>in</strong>en Term<strong>in</strong> vere<strong>in</strong>bart, damit er ihr<br />
erklärt, wie man nun Informationen aus <strong><strong>de</strong>r</strong> Datenbank abfragt.<br />
Herr Fleissig erklärt Frau Kart, dass die Sprache SQL hierfür nur SELECT als e<strong>in</strong>zige<br />
SQL-Anweisung vorsieht. Unter an<strong><strong>de</strong>r</strong>em erklärt er ihr, dass man nicht nur bestim<strong>mt</strong>e<br />
Tabellen nach bestim<strong>mt</strong>en Werten abfragen kann, son<strong><strong>de</strong>r</strong>n dass man auch Listen über<br />
Kun<strong>de</strong>n nach Umsatz sortiert erstellen kann. Nach<strong>de</strong>m ihr Herr Fleissig die grundlegen<strong>de</strong>n<br />
Eigenschaften <strong><strong>de</strong>r</strong> SELECT-Anweisung erklärt hat, beg<strong>in</strong>nt Frau Kart, verschie<strong>de</strong>ne<br />
Abfragen auszuprobieren. Dabei bemerkt sie, dass sie sehr viele Informationen erhalten<br />
kann, die vorher nur mit großem Aufwand zu beschaffen waren. Erfreut darüber teilt<br />
Frau Kart dies <strong>de</strong>m Geschäftsführer Herrn Kowalski mit, <strong><strong>de</strong>r</strong> von <strong>de</strong>n Möglichkeiten<br />
und natürlich von <strong><strong>de</strong>r</strong> vorbildlichen E<strong>in</strong>stellung Frau Karts begeistert ist. Er beauftragt<br />
Frau Kart <strong>de</strong>shalb, mehrere Informationen aus <strong><strong>de</strong>r</strong> Datenbank für ihn abzufragen:<br />
� Was kostet e<strong>in</strong> Werbeartikel im Durchschnitt?<br />
� Welcher Werbeartikel wur<strong>de</strong> am häufigsten verkauft?<br />
� Welche Vorstellungen f<strong>in</strong><strong>de</strong>n im Mai statt?<br />
� Wie viele Vorstellungen f<strong>in</strong><strong>de</strong>n im Jahr 2002 jeweils <strong>in</strong> <strong>de</strong>n e<strong>in</strong>zelnen Monaten statt?<br />
� Welcher Kun<strong>de</strong> hat die höchste Anzahl an Artikeln gekauft?<br />
� Welcher Artikel wur<strong>de</strong> am wenigsten bestellt?<br />
Frau Kart, noch etwas unsicher, ob sie alle diese Fragen beantworten kann, macht sich<br />
an die Arbeit.<br />
125
126<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
8.2 Allgeme<strong>in</strong>er Aufbau e<strong>in</strong>er Abfrage<br />
Bevor wir uns mit <strong>de</strong>m allgeme<strong>in</strong>en Aufbau <strong><strong>de</strong>r</strong> SELECT-Anweisung beschäftigen,<br />
wollen wir uns noch e<strong>in</strong>mal kurz die Grundlagen <strong>de</strong>s Relationenmo<strong>de</strong>lls vor Augen<br />
führen. SQL basiert ja auf <strong><strong>de</strong>r</strong> Mengenlehre bzw. <strong>de</strong>n Grundlagen <strong>de</strong>s Relationenmo<strong>de</strong>lls<br />
nach E.F.Codd. Neben <strong>de</strong>n Grundlagen <strong>de</strong>s Relationenmo<strong>de</strong>lls, die wir <strong>in</strong> Kapitel<br />
4 kennen gelernt haben, enthält das Relationenmo<strong>de</strong>ll auch mathematische Grundlagen,<br />
um Tabellen und <strong>in</strong> Beziehung stehen<strong>de</strong> Tabellen abzufragen. Diese mathematischen<br />
Grundlagen zur Abfrage wer<strong>de</strong>n als Relationenalgebra und als Relationenkalkül<br />
bezeichnet. Auf die mathematischen Grundlagen brauchen wir hier nicht weiter e<strong>in</strong>zugehen,<br />
da sie zur Verwendung von SQL nicht unbed<strong>in</strong>gt notwendig s<strong>in</strong>d.<br />
Doch kommen wir zu SQL zurück. SQL wur<strong>de</strong> gemäß <strong><strong>de</strong>r</strong> Relationenalgebra als <strong>de</strong>klarative<br />
(beschreiben<strong>de</strong>) Programmiersprache konzipiert. Im Gegensatz zu <strong>de</strong>klarativen<br />
Programmiersprachen gibt es prozedurale Programmiersprachen. Um <strong>de</strong>n Unterschied<br />
zwischen bei<strong>de</strong>n Arten von Programmiersprachen zu verstehen, wollen wir uns e<strong>in</strong> Beispiel<br />
aus <strong><strong>de</strong>r</strong> realen Welt ansehen:<br />
Der Geschäftsführer e<strong>in</strong>er Firma geht zum Leiter <strong>de</strong>s Rechnungswesens, um von diesem<br />
e<strong>in</strong>e Liste anzufor<strong><strong>de</strong>r</strong>n. Er hat zwei Möglichkeiten, <strong>de</strong>m Leiter <strong>de</strong>s Rechnungswesens<br />
se<strong>in</strong> Anliegen zu erklären.<br />
Entwe<strong><strong>de</strong>r</strong> sagt er ihm: »Erstellen Sie e<strong>in</strong>e Liste aller Kun<strong>de</strong>n, die <strong>in</strong> <strong>de</strong>n letzten drei<br />
Monaten für mehr als 700 Euro E<strong>in</strong>trittskarten gekauft haben und aus Regionen kommen,<br />
die mit <strong><strong>de</strong>r</strong> Postleitzahl 2 beg<strong>in</strong>nen.«<br />
O<strong><strong>de</strong>r</strong> er sagt ihm: »Holen Sie <strong>de</strong>n Ordner mit <strong>de</strong>n Bestellungen. Suchen Sie dann alle<br />
Bestellungen <strong><strong>de</strong>r</strong> letzten 3 Monate heraus. Aus diesen Bestellungen suchen Sie wie<strong><strong>de</strong>r</strong>um<br />
die Bestellungen heraus, die von Kun<strong>de</strong>n aus <strong><strong>de</strong>r</strong> Postleitzahlregion mit <strong><strong>de</strong>r</strong><br />
Zahl 2 stammen. Danach sortieren Sie die Bestellungen nach Kun<strong>de</strong>n und addieren<br />
dann die Bestellungen pro Kun<strong>de</strong> zusammen. Den Betrag und <strong>de</strong>n Kun<strong>de</strong>nnamen<br />
schreiben Sie auf e<strong>in</strong>e Liste. Schließlich streichen Sie die Kun<strong>de</strong>n aus <strong><strong>de</strong>r</strong> Liste, <strong><strong>de</strong>r</strong>en<br />
Bestellsumme kle<strong>in</strong>er als 700 Euro ist.«<br />
In bei<strong>de</strong>n Fällen erhält <strong><strong>de</strong>r</strong> Geschäftsführer nach e<strong>in</strong>er gewissen Zeit se<strong>in</strong>e Ergebnisliste,<br />
die, je nach<strong>de</strong>m, wie er die Aufgabe formuliert hat, i<strong>de</strong>ntisch se<strong>in</strong> sollte. Im ersten<br />
Fall hat er <strong>de</strong>m Leiter <strong>de</strong>s Rechnungswesens beschrieben, was er als Ergebnisliste<br />
haben möchte. Im zweiten Fall hat er ihm beschrieben, <strong>in</strong> welchen Schritten <strong><strong>de</strong>r</strong> Rechnungsleiter<br />
vorgehen soll, um die Ergebnisliste zu erstellen.<br />
Der erste Fall entspricht e<strong>in</strong>er <strong>de</strong>klarativen Sprache, da beschrieben wird, was man als<br />
Ergebnis haben möchte. Der zweite Fall entspricht e<strong>in</strong>er prozeduralen Sprache, da<br />
beschrieben wird, wie man zu e<strong>in</strong>em Ergebnis kom<strong>mt</strong>. Deklarative Programmiersprachen<br />
beschreiben also das Problem, prozedurale Programmiersprachen dagegen geben<br />
e<strong>in</strong> schrittweises Verfahren zur Problemlösung vor.<br />
Wie Sie sicherlich bemerkt haben, ist die erste Vorgehensweise für <strong>de</strong>n Geschäftsführer<br />
e<strong>in</strong><strong>de</strong>utig e<strong>in</strong>facher, da er nicht je<strong>de</strong>n Schritt e<strong>in</strong>zeln aufführen muss. Bei<strong>de</strong> Arten von<br />
Sprachen haben jedoch ihre Berechtigung, je nach<strong>de</strong>m welche Probleme man lösen<br />
möchte.
Spalten auswählen<br />
Bei SQL nun han<strong>de</strong>lte es sich ursprünglich um e<strong>in</strong>e <strong>de</strong>klarative Programmiersprache.<br />
In SQL formuliert man also, was man vom RDBMS als Ergebnismenge geliefert bekommen<br />
möchte. Ab Anfang <strong><strong>de</strong>r</strong> 90er Jahre begannen die Hersteller von RDBMS-Produkten<br />
jedoch, auch prozedurale Sprachelemente <strong>in</strong> ihre Produkte e<strong>in</strong>zubauen. Diese<br />
Sprachelemente wur<strong>de</strong>n 1996 als neuer Bestandteil <strong>de</strong>m damaligen SQL-92 Standard<br />
vom ANSI unter <strong><strong>de</strong>r</strong> Bezeichnung SQL/PSM h<strong>in</strong>zugefügt. Dadurch ist SQL heute<br />
sowohl e<strong>in</strong>e prozedurale als auch e<strong>in</strong>e <strong>de</strong>klarative Programmiersprache. Wir wollen<br />
uns <strong>in</strong> diesem und <strong>in</strong> <strong>de</strong>n nächsten Kapiteln zunächst mit <strong>de</strong>n <strong>de</strong>klarativen Sprachelementen<br />
von SQL beschäftigen.<br />
Wir können also festhalten, dass man durch SQL <strong>de</strong>m RDBMS <strong>in</strong> textueller Form mitteilt,<br />
was man von ihm wissen möchte, genauso wie <strong><strong>de</strong>r</strong> Geschäftsführer dies <strong>de</strong>m Leiter<br />
<strong>de</strong>s Rechnungswesens mitteilt. Das RDBMS entschei<strong>de</strong>t dann selbständig, ob und<br />
wie es diese Informationen f<strong>in</strong><strong>de</strong>t.<br />
Da SQL-Abfragen auf <strong><strong>de</strong>r</strong> Mengenlehre basieren, ist das Ergebnis e<strong>in</strong>er Abfrage auch<br />
wie<strong><strong>de</strong>r</strong>um e<strong>in</strong>e Menge bzw. e<strong>in</strong>e Tabelle. Mengen kennen ke<strong>in</strong>e bestim<strong>mt</strong>en Reihenfolgen.<br />
Das Ergebnis e<strong>in</strong>er SQL-Abfrage <strong>in</strong> Form e<strong>in</strong>er Tabelle ist also nicht sortiert, es sei<br />
<strong>de</strong>nn man gibt dies explizit an.<br />
In <strong>de</strong>n folgen<strong>de</strong>n drei Kapiteln wer<strong>de</strong>n wir uns mit <strong><strong>de</strong>r</strong> SQL-Anweisung zum Abfragen<br />
von Tabellen, <strong><strong>de</strong>r</strong> SELECT-Anweisung, beschäftigen. Der allgeme<strong>in</strong>e Aufbau <strong><strong>de</strong>r</strong><br />
SELECT-Anweisung sieht folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
SELECT spaltenliste<br />
[ FROM tabellenliste ]<br />
[ WHERE bed<strong>in</strong>gungsausdruck ]<br />
[ GROUP BY spaltenliste ]<br />
[ HAVING bed<strong>in</strong>gungsausdruck ]<br />
[ ORDER BY spaltenliste ]<br />
Die Angaben <strong>in</strong> eckigen Klammern s<strong>in</strong>d optional, also nicht zw<strong>in</strong>gend erfor<strong><strong>de</strong>r</strong>lich.<br />
8.3 Spalten auswählen<br />
E<strong>in</strong> e<strong>in</strong>faches Beispiel <strong><strong>de</strong>r</strong> SELECT-Anweisung sieht wie folgt aus:<br />
SELECT Plz<br />
FROM Ort<br />
Die SELECT-Klausel führt alle Spalten auf, die <strong>in</strong> <strong><strong>de</strong>r</strong> Ergebnisliste ersche<strong>in</strong>en sollen.<br />
Danach folgt das Schlüsselwort FROM, h<strong>in</strong>ter <strong>de</strong>m man die Tabellen angibt, <strong>in</strong> <strong>de</strong>nen<br />
sich die zu suchen<strong>de</strong>n Daten bef<strong>in</strong><strong>de</strong>n. Unser Beispiel gibt also alle Postleitzahlen aus,<br />
die <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »Ort« gespeichert s<strong>in</strong>d.<br />
127
Plz<br />
-----<br />
44444<br />
22222<br />
33333<br />
22287<br />
25746<br />
128<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
Alle Spalten, die wir von e<strong>in</strong>er Tabelle als Ergebnis erhalten möchten, wer<strong>de</strong>n h<strong>in</strong>ter<br />
SELECT aufgeführt. S<strong>in</strong>d es mehr als e<strong>in</strong>e Spalte, so wer<strong>de</strong>n diese durch Kommata<br />
vone<strong>in</strong>an<strong><strong>de</strong>r</strong> getrennt. Um Ort und Plz auszugeben, sieht die SELECT-Anweisung folgen<strong><strong>de</strong>r</strong>maßen<br />
aus:<br />
SELECT Ort, Plz<br />
FROM Ort<br />
Als Ergebnis erhält man e<strong>in</strong>e Tabelle, die die Spalten <strong>in</strong> <strong><strong>de</strong>r</strong> Reihenfolge aufführt, <strong>in</strong> <strong><strong>de</strong>r</strong><br />
sie h<strong>in</strong>ter <strong><strong>de</strong>r</strong> SELECT-Anweisung angegeben s<strong>in</strong>d.<br />
Ort Plz<br />
----------- -----<br />
Karlstadt 22222<br />
Hamburg 22287<br />
Hei<strong>de</strong> 25746<br />
Rettrich 33333<br />
Kohlscheidt 44444<br />
SQL kennt so genannte Platzhalter-Zeichen. E<strong>in</strong>es dieser Platzhalter-Zeichen ist <strong><strong>de</strong>r</strong> »*« .<br />
Möchte man <strong>de</strong>n Inhalt e<strong>in</strong>er Tabelle ausgegeben haben, so ist es bei Tabellen mit vielen<br />
Spalten häufig mühselig, alle Spalten e<strong>in</strong>er Tabelle h<strong>in</strong>tere<strong>in</strong>an<strong><strong>de</strong>r</strong> aufzuführen. Deshalb<br />
kann anstelle <strong><strong>de</strong>r</strong> Spaltenliste das »*« -Zeichen als Platzhalter für alle Spalten h<strong>in</strong>ter <strong><strong>de</strong>r</strong><br />
SELECT-Anweisung ersche<strong>in</strong>en. Dabei wer<strong>de</strong>n die Spalten <strong>in</strong> <strong><strong>de</strong>r</strong> Reihenfolge ausgegeben,<br />
<strong>in</strong> <strong><strong>de</strong>r</strong> sie <strong>in</strong> <strong><strong>de</strong>r</strong> CREATE TABLE-Anweisung e<strong>in</strong>mal angelegt wur<strong>de</strong>n.<br />
SELECT *<br />
FROM Ort<br />
Das Ergebnis sieht wie bei <strong><strong>de</strong>r</strong> vorherigen Abfrage aus, nur diesmal ersche<strong>in</strong>t zuerst<br />
die Spalte »Plz« und dann die Spalte »Ort« , da die Spalten <strong>in</strong> <strong><strong>de</strong>r</strong> CREATE TABLE-<br />
Anweisung <strong>in</strong> dieser Reihenfolge angelegt wur<strong>de</strong>n.<br />
Um die Lesbarkeit von Spalten zu verbessern, kann man Spalten <strong>in</strong> <strong><strong>de</strong>r</strong> Ergebnistabelle<br />
auch an<strong><strong>de</strong>r</strong>e Namen geben. Angenommen, Sie möchten statt Plz lieber Postleitzahl als<br />
Spaltenbezeichnung, so sieht die SELECT-Anweisung wie folgt aus:<br />
SELECT Plz AS 'Postleitzahl', Ort<br />
FROM Ort<br />
Das Umbenennen von Spalten über das Schlüsselwort AS ist beson<strong><strong>de</strong>r</strong>s dann wichtig,<br />
wenn man mit Spalten rechnet. Denn auch das ist möglich: Sie können Berechnungen
Spalten auswählen<br />
mit beliebigen Spalten durchführen. Angenommen, Sie möchten e<strong>in</strong>e Liste aller Werbeartikel<br />
ausgeben und die Liste soll mit Preisen angezeigt wer<strong>de</strong>n, die um 10% erhöht<br />
s<strong>in</strong>d, dann sieht die SELECT-Anweisung dazu folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
SELECT Beschreibung, Preis, Preis * 1.10 AS 'Preis + 10%'<br />
FROM Werbeartikel<br />
Das Ergebnis <strong><strong>de</strong>r</strong> Tabelle erhält <strong>de</strong>n erhöhten berechneten Preis, <strong><strong>de</strong>r</strong> hier mit vier Nachkommastellen<br />
angezeigt wird. Allerd<strong>in</strong>gs haben wir das Attribut Preis <strong><strong>de</strong>r</strong> Tabelle Werbartikel<br />
mit <strong>de</strong>m Datentyp DECIMAL(8, 2) <strong>de</strong>klariert, also nur mit zwei Nachkommastellen.<br />
SQL konvertiert bei Berechnungen Zahlen automatisch <strong>in</strong> an<strong><strong>de</strong>r</strong>e Datentypen,<br />
um korrekte Berechnungen darzustellen, <strong>in</strong> diesem Fall mit vier Nachkommastellen.<br />
Wir wer<strong>de</strong>n im Abschnitt über Funktionen sehen, dass man bei SQL e<strong>in</strong>e solche Datenkonvertierung<br />
aber auch explizit angeben kann, d.h. <strong>in</strong> diesem Fall könnten wir die<br />
Berechnung dann wie<strong><strong>de</strong>r</strong> auf zwei Nachkommastellen begrenzen. Generell wählt SQL<br />
allerd<strong>in</strong>gs automatisch e<strong>in</strong>en Datentyp mit e<strong>in</strong>em größeren Wertebereich, sofern bei<br />
Berechnungen e<strong>in</strong> Wertebereich überschritten wird. Entsprechend sieht die Ergebnistabelle<br />
<strong><strong>de</strong>r</strong> Abfrage dann wie folgt aus:<br />
Beschreibung Preis Preis + 10%<br />
------------------------- ----- -----------<br />
Noten f. Klavier 89.00 97.9000<br />
T-Shirt Farbe: rot 29.99 32.9890<br />
Phil Coll<strong>in</strong>s <strong>in</strong> Concert 20.00 22.0000<br />
Plakat mit Musical-Katzen 33.50 36.8500<br />
Schwarzer Zauberstock 5.99 6.5890<br />
Dieses Beispiel zeigt Berechnungen mit konstanten Werten. Man kann aber auch<br />
Berechnungen mit mehreren Spalten vornehmen. Möchte man z.B. wissen, welchen<br />
Gesa<strong>mt</strong>preis e<strong>in</strong> Werbeartikel hat, <strong><strong>de</strong>r</strong> auf Lager liegt, so wird <strong><strong>de</strong>r</strong> Lagerbestand mit<br />
<strong>de</strong>m E<strong>in</strong>zelpreis multipliziert. Die SELECT-Anweisung dazu lautet:<br />
SELECT Beschreibung, Preis * Lagerbestand AS 'Artikel Gesa<strong>mt</strong>wert'<br />
FROM Werbeartikel<br />
Hier hat das Ergebnis <strong><strong>de</strong>r</strong> Berechnung nur zwei Nachkommastellen, da Lagerbestand<br />
e<strong>in</strong>e Ganzzahl ist, und damit die Anzahl <strong><strong>de</strong>r</strong> Nachkommastellen durch die Berechnung<br />
auch nicht überschritten wer<strong>de</strong>n kann.<br />
Beschreibung Artikel Gesa<strong>mt</strong>wert<br />
------------------------- ------------------<br />
Noten f. Klavier 2314.00<br />
T-Shirt Farbe: rot 329.89<br />
Phil Coll<strong>in</strong>s <strong>in</strong> Concert 420.00<br />
Plakat mit Musical-Katzen 2981.50<br />
Schwarzer Zauberstock 191.68<br />
129
130<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
Da <strong><strong>de</strong>r</strong> Preis <strong>in</strong> Euro <strong>in</strong> unsere Datenbank e<strong>in</strong>gegeben wur<strong>de</strong>, fehlt nun noch die Währungse<strong>in</strong>heit<br />
h<strong>in</strong>ter <strong>de</strong>m Preis. Als Spaltenliste h<strong>in</strong>ter <strong>de</strong>m Schlüsselwort SELECT können<br />
auch konstante Werte wie z.B. »EUR« aufgeführt wer<strong>de</strong>n. Diese ersche<strong>in</strong>en <strong>in</strong> je<strong><strong>de</strong>r</strong><br />
Ergebniszeile mit <strong>de</strong>m gleichen Wert. Das ist genau das, was wir brauchen.<br />
SELECT Beschreibung, Preis, 'EUR' AS 'Währung'<br />
FROM Werbeartikel<br />
Damit sieht unsere Ergebnistabelle folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
Beschreibung Preis Währung<br />
------------------------- ----- -------<br />
Noten f. Klavier 89.00 EUR<br />
T-Shirt Farbe: rot 29.99 EUR<br />
Phil Coll<strong>in</strong>s <strong>in</strong> Concert 20.00 EUR<br />
Plakat mit Musical-Katzen 33.50 EUR<br />
Schwarzer Zauberstock 5.99 EUR<br />
Gemäß <strong>de</strong>m Relationenmo<strong>de</strong>ll darf e<strong>in</strong> Element <strong><strong>de</strong>r</strong> Ergebnismenge nur e<strong>in</strong>mal vorkommen.<br />
Mit an<strong><strong>de</strong>r</strong>en Worten: Je<strong>de</strong> Zeile e<strong>in</strong>er Tabelle darf nur e<strong>in</strong> e<strong>in</strong>ziges Mal auftreten.<br />
SQL ist <strong>in</strong> diesem Punkt nicht so konsequent wie das Relationenmo<strong>de</strong>ll. Betrachten<br />
wir dazu folgen<strong>de</strong> SELECT-Anweisung und <strong><strong>de</strong>r</strong>en Ergebnistabelle:<br />
SELECT Haus<br />
FROM Vorstellung<br />
Haus<br />
-----------------<br />
Deutsche Staatsoper<br />
Deutsche Staatsoper<br />
Deutsche Staatsoper<br />
Operettenhaus<br />
Operettenhaus<br />
Nordseehalle<br />
Kongresshalle<br />
Deutsche Staatsoper<br />
Sokratesbühne<br />
Sokratesbühne<br />
Sokratesbühne<br />
Sokratesbühne<br />
Sokratesbühne<br />
Am Beispiel dieser e<strong>in</strong>fachen Abfrage können wir sehen, dass Sätze mit gleichen Werten<br />
<strong>in</strong> e<strong>in</strong>er Ergebnistabelle mehrfach vorkommen können. Generell gilt, dass die Ergebnistabelle<br />
nicht unbed<strong>in</strong>gt <strong>de</strong>n Normalformen <strong>de</strong>s Relationenmo<strong>de</strong>lls entsprechen muss.<br />
Um nun <strong>de</strong>nnoch zu erreichen, dass Sätze <strong><strong>de</strong>r</strong> Ergebnistabelle nicht mehrfach angezeigt<br />
wer<strong>de</strong>n, verwen<strong>de</strong>t man das Schlüsselwort DISTINCT direkt h<strong>in</strong>ter <strong>de</strong>m Schlüsselwort<br />
SELECT. DISTINCT filtert Sätze mit gleichen Werten aus <strong><strong>de</strong>r</strong> Ergebnistabelle aus.
SELECT DISTINCT Haus<br />
FROM Vorstellung<br />
Haus<br />
-----------------<br />
Deutsche Staatsoper<br />
Kongresshalle<br />
Nordseehalle<br />
Operettenhaus<br />
Sokratesbühne<br />
Spalten auswählen<br />
Unsere Ergebnistabelle ist jetzt korrekt, alle Spielstätten, <strong>in</strong> <strong>de</strong>nen Vorstellungen stattf<strong>in</strong><strong>de</strong>n,<br />
wer<strong>de</strong>n nur noch e<strong>in</strong>mal aufgeführt.<br />
Wir haben uns bis hierher vorwiegend damit beschäftigt, wie man die gewünschten<br />
Spalten e<strong>in</strong>er Tabelle ausgeben kann. Mathematisch wird die Auswahl <strong><strong>de</strong>r</strong> Spalten<br />
gemäß <strong>de</strong>m Relationenmo<strong>de</strong>ll als Projektion bezeichnet. Abschließend wollen wir uns<br />
die Projektion noch e<strong>in</strong>mal grafisch am Beispiel <strong><strong>de</strong>r</strong> Tabelle Werbeartikel anschauen,<br />
bevor wir zu Funktionen übergehen, die man auf Spalten anwen<strong>de</strong>n kann.<br />
SELECT Bezeichnung, Lagerbestand<br />
FROM Werbeartikel<br />
Artikelnummer<br />
1001<br />
1003<br />
1012<br />
1081<br />
1077<br />
Beschreibung<br />
Noten f. Klavier<br />
T-Shirt Farbe: rot<br />
Phil Coll<strong>in</strong>s <strong>in</strong> Concert<br />
Schwarzer Zauberstock<br />
Plakat mit <strong>de</strong>n Musical-Katzen<br />
Beschreibung<br />
Noten f. Klavier<br />
T-Shirt Farbe: rot<br />
Phil Coll<strong>in</strong>s <strong>in</strong> Concert<br />
Schwarzer Zauberstock<br />
Plakat mit <strong>de</strong>n Musical-Katzen<br />
Preis<br />
89.00<br />
29.99<br />
20.00<br />
5.99<br />
33.50<br />
Lagerbestand<br />
26<br />
11<br />
21<br />
32<br />
89<br />
Abbildung 8.1: Projektion (Auswahl von Spalten)<br />
Lagerbestand<br />
26<br />
11<br />
21<br />
32<br />
89<br />
131
132<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
8.4 »Built-<strong>in</strong>«-Funktionen<br />
8.4.1 Grundlagen<br />
SQL:1999 legt <strong>in</strong> se<strong>in</strong>em Standard mehrere Gruppen von e<strong>in</strong>gebauten Funktionen<br />
(»Built-<strong>in</strong>« -Funktionen) fest. Funktionen führen bestim<strong>mt</strong>e immer wie<strong><strong>de</strong>r</strong>kehren<strong>de</strong><br />
Aufgaben aus, wie z.B. das Umwan<strong>de</strong>ln e<strong>in</strong>er Zeichenkette <strong>in</strong> Großbuchstaben. Funktionen<br />
haben die Eigenschaft, dass ihnen Werte übergeben wer<strong>de</strong>n können, die Funktionen<br />
diese Werte verarbeiten und e<strong>in</strong> Ergebnis zurückliefern. Damit s<strong>in</strong>d Funktionen<br />
nützliche, aber auch sehr wichtige »Helfer« für <strong>de</strong>n SQL-Programmierer. Funktionen<br />
können <strong>in</strong> SQL-Ausdrücken auf Spalten o<strong><strong>de</strong>r</strong> auf Literale angewen<strong>de</strong>t wer<strong>de</strong>n.<br />
Betrachten wir hierzu exemplarisch die e<strong>in</strong>fache Funktion UPPER. Der Funktion<br />
UPPER wird e<strong>in</strong>e Zeichenkette übergeben, die diese <strong>in</strong> Großbuchstaben umwan<strong>de</strong>lt<br />
und dann wie<strong><strong>de</strong>r</strong> zurückliefert. In e<strong>in</strong>er e<strong>in</strong>fachen SELECT-Anweisung könnten wir so<br />
z.B. alle Orte <strong>in</strong> Großbuchstaben ausgeben:<br />
SELECT UPPER(Ort)AS 'Ortsname'<br />
FROM Ort<br />
Ortsname<br />
-----------<br />
KARLSTADT<br />
HAMBURG<br />
HEIDE<br />
RETTRICH<br />
KOHLSCHEIDT<br />
SQL:1999 kennt <strong>in</strong>gesa<strong>mt</strong> folgen<strong>de</strong> Gruppen von Funktionen, wobei gera<strong>de</strong> <strong><strong>de</strong>r</strong> Funktionsumfang<br />
bei <strong>de</strong>n e<strong>in</strong>zelnen RDBMS-Produkten sehr groß ist und vor allem Unterschie<strong>de</strong><br />
<strong>in</strong> <strong><strong>de</strong>r</strong> Syntax bestehen:<br />
� Wertfunktionen mit numerischem Rückgabewert (»Numeric Value Functions« );<br />
� Wertfunktionen mit Zeichenkette als Rückgabewert (»Str<strong>in</strong>g Value Functions« );<br />
� Wertfunktionen mit Datums-/Zeit-Rückgabewert (»Datetime Value Functions« );<br />
� Wertfunktionen mit Zeit<strong>in</strong>tervall-Rückgabewert (»Interval Value Functions« );<br />
� NULL-Funktionen und Datentypkonvertierung;<br />
� Mengenfunktionen (»Set Functions« ).<br />
Wir wollen uns im Folgen<strong>de</strong>n mit <strong>de</strong>n wichtigsten Funktionen von SQL beschäftigen<br />
und <strong><strong>de</strong>r</strong>en Anwendung <strong>in</strong> Zusammenhang mit <strong><strong>de</strong>r</strong> SELECT-Anweisung kennen lernen.<br />
8.4.2 »Numeric Value Functions«<br />
Wertfunktionen mit numerischem Rückgabewert liefern als Ergebnis immer e<strong>in</strong>e Zahl<br />
und haben daher ihren Namen. Die ersten bei<strong>de</strong>n Funktionen, die wir uns ansehen
»Built-<strong>in</strong>«-Funktionen<br />
wollen, s<strong>in</strong>d die Funktionen ABS und MOD. Bei<strong>de</strong>n wer<strong>de</strong>n numerische Werte übergeben.<br />
ABS liefert als Ergebnis <strong>de</strong>n absoluten Wert e<strong>in</strong>er Zahl, MOD entspricht mathematisch<br />
<strong><strong>de</strong>r</strong> Modulofunktion und liefert <strong>de</strong>n Rest e<strong>in</strong>er Division zurück.<br />
Betrachten wir hierzu e<strong>in</strong> Beispiel:<br />
SELECT ABS(-26.00) AS 'Absoluter Wert'<br />
Absoluter Wert<br />
--------------<br />
26.00<br />
Dieses recht e<strong>in</strong>fache Beispiel übergibt e<strong>in</strong>en konstanten Wert -26.00 und bekom<strong>mt</strong> als<br />
Ergebnis <strong>de</strong>n absoluten positiven Wert 26.00 zurückgeliefert.<br />
Genauso wird die Modulofunktion MOD verwen<strong>de</strong>t. Diesmal wollen wir die Funktion<br />
allerd<strong>in</strong>gs nicht auf e<strong>in</strong>en konstanten Wert anwen<strong>de</strong>n, son<strong><strong>de</strong>r</strong>n auf e<strong>in</strong>e Spalte. Wir<br />
wollen ermitteln, welche Werbeartikel <strong>in</strong> e<strong>in</strong>er gera<strong>de</strong>n Anzahl im Lager vorhan<strong>de</strong>n<br />
s<strong>in</strong>d. Ergibt also <strong><strong>de</strong>r</strong> Rest e<strong>in</strong>er Division durch 2 die Zahl 1, so han<strong>de</strong>lt es sich um e<strong>in</strong>e<br />
ungera<strong>de</strong> Menge, ist <strong><strong>de</strong>r</strong> Rest 0 um e<strong>in</strong>e gera<strong>de</strong> Menge. Die SELECT-Anweisung hierzu<br />
sieht wie folgt aus:<br />
SELECT Lagerbestand, MOD( Lagerbestand, 2 ) AS 'Divisionsrest'<br />
FROM Werbeartikel<br />
Lagerbestand Divisionsrest<br />
------------ -------------<br />
26 0<br />
11 1<br />
21 1<br />
89 1<br />
32 0<br />
Der Funktion CHAR_LENGTH o<strong><strong>de</strong>r</strong> CHARACTER_LENGTH wird, wie <strong><strong>de</strong>r</strong> Name<br />
schon sagt, e<strong>in</strong>e Zeichenkette als Wert übergeben. Als Ergebnis liefert die Funktion die<br />
Länge <strong><strong>de</strong>r</strong> Zeichenkette. Das folgen<strong>de</strong> Beispiel gibt die Namen aller Orte, sowie die<br />
Länge <strong>de</strong>s Ortsnamens aus:<br />
SELECT Ort, CHARACTER_LENGTH(Ort)<br />
FROM Ort<br />
Ort<br />
------------ -------------<br />
Karlstadt 9<br />
Hamburg 7<br />
Hei<strong>de</strong> 5<br />
Rettrich 8<br />
Kohlscheidt 11<br />
133
134<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
Die Funktion POSITION sucht <strong>in</strong>nerhalb e<strong>in</strong>er Zeichenkette nach <strong>de</strong>m Auftreten e<strong>in</strong>er<br />
an<strong><strong>de</strong>r</strong>en Zeichenkette. Angenommen, Sie möchten die Position <strong><strong>de</strong>r</strong> Zeichenkette 'stadt'<br />
<strong>in</strong>nerhalb je<strong>de</strong>s Ortsnamens ermitteln, so sieht die entsprechen<strong>de</strong> SELECT-Anweisung<br />
wie folgt aus:<br />
SELECT Ort, POSITION('stadt' IN Ort)<br />
FROM Ort<br />
Ort<br />
------------ -------------<br />
Karlstadt 5<br />
Hamburg 0<br />
Hei<strong>de</strong> 0<br />
Rettrich 0<br />
Kohlscheidt 0<br />
Die Zeichenfolge »stadt« wur<strong>de</strong> nur im ersten Ortsnamen Karlstadt gefun<strong>de</strong>n und<br />
beg<strong>in</strong>nt dort an <strong><strong>de</strong>r</strong> fünften Stelle. Für alle an<strong><strong>de</strong>r</strong>en Datensätze wur<strong>de</strong> im jeweiligen<br />
Ortsnamen die Zeichenfolge nicht gefun<strong>de</strong>n und damit <strong><strong>de</strong>r</strong> Wert 0 von <strong><strong>de</strong>r</strong> Funktion<br />
POSITION zurückgeliefert.<br />
Als letzte numerische Wertfunktionen wollen wir uns die Funktion EXTRACT ansehen.<br />
Sie extrahiert aus e<strong>in</strong>em Datumswert <strong>de</strong>n Tag, Monat o<strong><strong>de</strong>r</strong> das Jahr e<strong>in</strong>es Datums.<br />
Die folgen<strong>de</strong> SELECT-Anweisung gibt das Bestelldatum jeweils getrennt nach Tag,<br />
Monat und Jahr <strong>in</strong> e<strong>in</strong>er e<strong>in</strong>zelnen Spalte aus:<br />
SELECT EXTRACT (DAY FROM Datum) AS 'Tag',<br />
EXTRACT (MONTH FROM Datum) AS 'Monat',<br />
EXTRACT (YEAR FROM Datum) AS 'Jahr'<br />
FROM Bestellung<br />
Tag Monat Jahr<br />
--- ----- ----<br />
26 1 2002<br />
8 2 2002<br />
21 12 2001<br />
8.4.3 »Str<strong>in</strong>g Value Functions«<br />
»Str<strong>in</strong>g Value Functions« liefern als Ergebnis immer e<strong>in</strong>e Zeichenkette. E<strong>in</strong> e<strong>in</strong>faches<br />
Beispiel so e<strong>in</strong>er Funktion haben wir bereits kennen gelernt, die Funktion UPPER, welche<br />
Zeichenketten <strong>in</strong> Großbuchstaben umwan<strong>de</strong>lt. Analog zur UPPER-Funktion gibt es<br />
auch e<strong>in</strong>e LOWER-Funktion, die Zeichenketten <strong>in</strong> Kle<strong>in</strong>buchstaben umwan<strong>de</strong>lt. Neben<br />
diesen bei<strong>de</strong>n eher unwichtigen Funktionen ist vor allem die Funktion TRIM von<br />
Be<strong>de</strong>utung. Mit TRIM können Leerzeichen o<strong><strong>de</strong>r</strong> auch an<strong><strong>de</strong>r</strong>e Zeichen vor und h<strong>in</strong>ter<br />
e<strong>in</strong>er Zeichenkette entfernt wer<strong>de</strong>n. Im ersten Moment mag dies für Sie auch e<strong>in</strong>e relativ<br />
unwichtige Funktion se<strong>in</strong>, doch hier kom<strong>mt</strong> <strong><strong>de</strong>r</strong> Datentyp CHARACTER <strong>in</strong>s Spiel.<br />
Wir haben ja gelernt, dass Werte von Spalten <strong>de</strong>s Datentyps CHARACTER immer
»Built-<strong>in</strong>«-Funktionen<br />
genau die angegebene Anzahl an Zeichen belegen, die h<strong>in</strong>ter CHARACTER angegeben<br />
wird. Angenommen, Sie haben die Spalte Vorname mit CHARACTER(20) <strong>de</strong>f<strong>in</strong>iert, so<br />
wird e<strong>in</strong> Vorname wie »Hans« <strong>in</strong> dieser Spalte nicht 4 Zeichen, son<strong><strong>de</strong>r</strong>n immer 20 Zeichen<br />
belegen. Dabei füllt SQL <strong>de</strong>n Rest <strong>de</strong>s Wertes mit Leerzeichen auf. H<strong>in</strong>ter <strong>de</strong>m<br />
Wort »Hans« wür<strong>de</strong>n also noch 16 Leerzeichen folgen. Um diese Leerzeichen bei<br />
Abfragen wie<strong><strong>de</strong>r</strong> zu entfernen, eignet sich die Funktion TRIM. Neben <strong><strong>de</strong>r</strong> Zeichenkette,<br />
aus <strong><strong>de</strong>r</strong> die Leerzeichen entfernt wer<strong>de</strong>n sollen, gibt man <strong><strong>de</strong>r</strong> Funktion noch<br />
bekannt, ob führen<strong>de</strong> (LEADING), nachfolgen<strong>de</strong> (TRAILING) o<strong><strong>de</strong>r</strong> führen<strong>de</strong> und<br />
nachfolgen<strong>de</strong> (BOTH) Leerzeichen entfernt wer<strong>de</strong>n sollen. Um die Leerzeichen bei Vorund<br />
Nachname e<strong>in</strong>es Kun<strong>de</strong>n zu entfernen, schreiben wir:<br />
SELECT TRIM( TRAILING ' ' FROM Name ),<br />
TRIM( TRAILING ' ' FROM Vorname)<br />
FROM Kun<strong>de</strong><br />
Folgen<strong>de</strong>s weiteres Beispiel soll noch e<strong>in</strong>mal die verschie<strong>de</strong>nen Varianten von TRIM<br />
ver<strong>de</strong>utlichen. Es entfernt Semikolons vor o<strong><strong>de</strong>r</strong> h<strong>in</strong>ter e<strong>in</strong>em konstanten Text.<br />
SELECT TRIM( TRAILING ';' FROM ';;;Test;;;' ),<br />
TRIM( LEADING ';' FROM ';;;Test;;;' ),<br />
TRIM( BOTH ';' FROM ';;;Test;;;' )<br />
------- ------- -------<br />
;;;Test Test;;; Test<br />
Mit <strong><strong>de</strong>r</strong> Funktion SUBSTRING kann e<strong>in</strong> Teil aus e<strong>in</strong>er Zeichenkette herausgetrennt<br />
wer<strong>de</strong>n. Angenommen, wir haben beim Autor e<strong>in</strong>er Veranstaltung Vor- und Nachnamen<br />
<strong>in</strong> e<strong>in</strong>er Spalte gespeichert (was man ja nach <strong><strong>de</strong>r</strong> 1. Normalform eigentlich nicht<br />
machen sollte). Wir möchten nun alle Veranstaltungen ausgeben, sowie die Nachnamen<br />
<strong><strong>de</strong>r</strong> Autoren. E<strong>in</strong> Autor ist Phil Coll<strong>in</strong>s, <strong>de</strong>ssen Nachname beg<strong>in</strong>nt ab <strong><strong>de</strong>r</strong> sechsten<br />
Stelle und en<strong>de</strong>t an <strong><strong>de</strong>r</strong> zwölften Stelle, also nach sieben Zeichen. Mit Hilfe <strong><strong>de</strong>r</strong><br />
Funktion SUBSTRING ist folgen<strong>de</strong> SELECT-Anweisung möglich:<br />
SELECT Autor, SUBSTRING( Autor FROM 6 FOR 7 ) AS 'Nachname'<br />
FROM Veranstaltung<br />
Autor Nachname<br />
--------------- --------<br />
Ama<strong>de</strong>us Mozart us Moza<br />
Ama<strong>de</strong>us Mozart us Moza<br />
Phil Coll<strong>in</strong>s Coll<strong>in</strong>s<br />
Webber r<br />
Brecht t<br />
Das Ergebnis ist allerd<strong>in</strong>gs nicht beson<strong><strong>de</strong>r</strong>s zufrie<strong>de</strong>n stellend, da nur für Phil Coll<strong>in</strong>s<br />
gilt, dass <strong><strong>de</strong>r</strong> Nachname ab <strong><strong>de</strong>r</strong> sechsten Stelle beg<strong>in</strong>nt. Für Ama<strong>de</strong>us Mozart wird zum<br />
Beispiel ab <strong><strong>de</strong>r</strong> sechsten bis zur zwölften Stelle nur die Zeichenfolge »us Moza« ausgegeben.<br />
135
136<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
Man kann nun aber Funktionen <strong>in</strong>e<strong>in</strong>an<strong><strong>de</strong>r</strong> schachteln und entsprechend zuerst die<br />
Position ermitteln, ab <strong><strong>de</strong>r</strong> das Leerzeichen ersche<strong>in</strong>t und diese Position <strong>in</strong> <strong><strong>de</strong>r</strong> Funktion<br />
SUBSTRING verwen<strong>de</strong>n:<br />
SELECT Autor,<br />
SUBSTRING(Autor FROM POSITION( ' ' IN Autor)+1 ) AS 'Nachname'<br />
FROM Veranstaltung<br />
Autor Nachname<br />
--------------- --------<br />
Ama<strong>de</strong>us Mozart Mozart<br />
Ama<strong>de</strong>us Mozart Mozart<br />
Phil Coll<strong>in</strong>s Coll<strong>in</strong>s<br />
Webber Webber<br />
Brecht Brecht<br />
Betrachten wir dazu die <strong>in</strong>e<strong>in</strong>an<strong><strong>de</strong>r</strong> geschachtelten Funktionen SUBSTRING und POSI-<br />
TION. Zunächst wird die Position <strong>de</strong>s Leerzeichens über POSITION( ' ' IN Autor)<br />
ermittelt. Für <strong>de</strong>n Namen Phil Coll<strong>in</strong>s wür<strong>de</strong> diese Funktionen die Position 5 zurückliefern.<br />
Um das Leerzeichen selbst zu überspr<strong>in</strong>gen wird 1 dazu addiert. Dieser Wert<br />
wird dann an SUBSTRING übergeben und entsprechend für die Zeichenfolge Phil Coll<strong>in</strong>s<br />
die Funktion SUBSTRING( Autor FROM 6 ) ausgeführt.<br />
Die letzte Zeichenkettenfunktion, die wir betrachten wollen, dient zum Ersetzen e<strong>in</strong>er<br />
Zeichenfolge durch e<strong>in</strong>e an<strong><strong>de</strong>r</strong>e Zeichenfolge. E<strong>in</strong> e<strong>in</strong>faches Beispiel um das Kürzel<br />
»z.B.« durch die Zeichenfolge »zum Beispiel« zu ersetzen, sieht wie folgt aus:<br />
SELECT OVERLAY( 'z.B. Saft' PLACING 'zum Beispiel' FROM 1 FOR 4)<br />
----------------zum<br />
Beispiel Saft<br />
Die Zeichenkette »z.B. Saft« wur<strong>de</strong> durch die Funktion OVERLAY geän<strong><strong>de</strong>r</strong>t <strong>in</strong> »zum<br />
Beispiel Saft« .<br />
Betrachten wir noch e<strong>in</strong> Beispiel, <strong>in</strong> <strong>de</strong>m wir wie<strong><strong>de</strong>r</strong> Funktionen schachteln. Wir haben<br />
<strong>in</strong> <strong><strong>de</strong>r</strong> Spalte Beschreibung unserer Werbeartikel die Abkürzung »f.« für das Wort »für«<br />
verwen<strong>de</strong>t. Bei <strong><strong>de</strong>r</strong> Ausgabe unserer Ergebnistabelle möchten wir aber anstelle <strong><strong>de</strong>r</strong><br />
Abkürzung das Wort »für« ausgeben. Dazu verwen<strong>de</strong>n wir die Funktion OVERLAY<br />
zusammen mit <strong><strong>de</strong>r</strong> Funktion POSITION wie folgt:<br />
SELECT Beschreibung,<br />
OVERLAY( Beschreibung PLACING 'für'<br />
FROM POSITION( 'f.' IN Beschreibung) FOR 2 )<br />
AS 'Beschreibung ohne Kürzel'<br />
FROM Werbeartikel
»Built-<strong>in</strong>«-Funktionen<br />
Beschreibung Beschreibung ohne Kürzel<br />
------------------------- -------------------------<br />
Noten f. Klavier Noten für Klavier<br />
T-Shirt Farbe: rot T-Shirt Farbe: rot<br />
Phil Coll<strong>in</strong>s <strong>in</strong> Concert Phil Coll<strong>in</strong>s <strong>in</strong> Concert<br />
Plakat mit Musical-Katzen Plakat mit Musical-Katzen<br />
Schwarzer Zauberstock Schwarzer Zauberstock<br />
8.4.4 »Datetime Value Functions«<br />
Funktionen aus <strong><strong>de</strong>r</strong> Gruppe <strong><strong>de</strong>r</strong> Wertfunktionen, die e<strong>in</strong> Datums-/Zeitwert zurückliefern,<br />
haben wir bereits <strong>in</strong> Kapitel 6 beim Anlegen von Tabellen über CREATE TABLE<br />
kennen gelernt, und zwar die Funktionen CURRENT_DATE, CURRENT_TIME und<br />
CURRENT_TIMESTAMP. Diese Funktionen liefern e<strong>in</strong>fach das aktuelle Datum, die<br />
aktuelle Uhrzeit o<strong><strong>de</strong>r</strong> aber bei<strong>de</strong>s zurück. Folgen<strong>de</strong>s Beispiel ver<strong>de</strong>utlicht noch e<strong>in</strong>mal<br />
die Verwendung <strong><strong>de</strong>r</strong> drei Funktionen:<br />
SELECT CURRENT_DATE() AS 'Aktuelles Datum',<br />
CURRENT_TIME(2) AS 'Aktuelle Zeit',<br />
CURRENT_TIMESTAMP(6) AS 'Aktuelles Datum/Zeit'<br />
Aktuelles Datum Aktuelle Zeit Aktuelles Datum/Zeit<br />
--------------- ------------- -----------------------<br />
2002-10-15 09:25:12.92 2002-10-15 09:25:12.920<br />
8.4.5 NULL-Funktionen und Datentypkonvertierung<br />
Oft wer<strong>de</strong>n <strong>in</strong> Datenbanken anstelle von NULL an<strong><strong>de</strong>r</strong>e Daten verwen<strong>de</strong>t, um anzuzeigen,<br />
dass e<strong>in</strong> Wert nicht vorhan<strong>de</strong>n o<strong><strong>de</strong>r</strong> unbekannt ist. Angenommen, <strong>in</strong> unserem Fallbeispiel<br />
hätte Frau Kart bei <strong>de</strong>m Lagerbestand für die Werbeartikel immer die Zahl<br />
9999 anstelle von NULL verwen<strong>de</strong>t, um anzuzeigen, dass <strong><strong>de</strong>r</strong> Lagerbestand zur Zeit<br />
unbekannt ist. Wür<strong>de</strong>n wir die Tabelle Werbartikel abfragen, so erhielten wir überall<br />
dort, wo <strong><strong>de</strong>r</strong> Wert von Lagerbestand 9999 ist, nicht NULL für unbekannt son<strong><strong>de</strong>r</strong>n 9999.<br />
Um bei e<strong>in</strong>er Abfrage Werte, die für unbekannt stehen, als NULL auszugeben, gibt es<br />
die Funktion NULLIF. Der Funktion NULLIF wer<strong>de</strong>n zwei Werte übergeben, s<strong>in</strong>d diese<br />
bei<strong>de</strong>n Werte i<strong>de</strong>ntisch, so wird e<strong>in</strong>fach NULL zurückgegeben. Sehen wir uns hierzu<br />
unser Beispiel mit <strong>de</strong>n Werbeartikeln an:<br />
SELECT Beschreibung,<br />
Lagerbestand,<br />
NULLIF(Lagerbestand, 9999) AS 'Lagerbestand'<br />
FROM Werbeartikel<br />
137
138<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
Beschreibung Lagerbestand Lagerbestand<br />
------------------------- ------------ ------------<br />
Noten f. Klavier 26 26<br />
T-Shirt Farbe: rot 11 11<br />
Phil Coll<strong>in</strong>s <strong>in</strong> Concert 21 21<br />
Plakat mit Musical-Katzen 89 89<br />
Opernführer 9999 NULL<br />
Schwarzer Zauberstock 32 32<br />
Als Ergebnis erhalten wir <strong>de</strong>n Lagerbestand, wie er <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »Werbeartikel«<br />
gespeichert ist und <strong>de</strong>n Lagerbestand, wenn die Zahl 9999 als NULL <strong>in</strong>terpretiert wer<strong>de</strong>n<br />
soll. Für <strong>de</strong>n Werbeartikel mit <strong><strong>de</strong>r</strong> Beschreibung »Opernführer« wur<strong>de</strong> als Lagerbestand<br />
9999 e<strong>in</strong>getragen Über die Funktion NULLIF wird er als NULL und damit<br />
unbekannt ausgegeben.<br />
E<strong>in</strong>e weitere Funktion, die man auf Spalten mit NULL anwen<strong>de</strong>t, ist COALESCE. Der<br />
Funktion COALESCE kann man e<strong>in</strong>e beliebige Anzahl an Spalten o<strong><strong>de</strong>r</strong> Konstanten<br />
übergeben. Als Rückgabe wird <strong><strong>de</strong>r</strong> erste Wert <strong><strong>de</strong>r</strong> übergebenen Parameter zurückgegeben,<br />
<strong><strong>de</strong>r</strong> nicht NULL ist. COALESCE( NULL, 'Zweiter') wür<strong>de</strong> also <strong>de</strong>n Wert »Zweiter«<br />
zurückliefern. COALESCE wird dort e<strong>in</strong>gesetzt, wo man bei e<strong>in</strong>er Abfrage für NULL<br />
z.B. e<strong>in</strong> Fragezeichen o<strong><strong>de</strong>r</strong> das Wort »Unbekannt« ausgeben möchte. Sollen z.B. alle<br />
Kun<strong>de</strong>nnamen und <strong><strong>de</strong>r</strong>en Strasse und Hausnummer, <strong>in</strong> <strong><strong>de</strong>r</strong> sie wohnen, ausgegeben<br />
wer<strong>de</strong>n und für Strassennamen und Hausnummern, die nicht bekannt s<strong>in</strong>d, das Wort<br />
»Unbekannt« , so sieht die Abfrage folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
SELECT Name,<br />
COALESCE( Strasse, '' ),<br />
COALESCE( Hausnummer, '' )<br />
FROM Kun<strong>de</strong><br />
Name<br />
--------- ---------- ----------------------<br />
Bolte Busweg 12<br />
Muster Musterweg 12<br />
Wiegerich Wan<strong><strong>de</strong>r</strong>str. <br />
Carlson Petristr. 201<br />
Die dritte Funktion, die wir uns <strong>in</strong> diesem Abschnitt ansehen wollen, dient zur Konvertierung<br />
von Werten e<strong>in</strong>es bestim<strong>mt</strong>en Datentyps <strong>in</strong> e<strong>in</strong>en an<strong><strong>de</strong>r</strong>en Datentyp. In<br />
Abschnitt 8.3 haben wir gesehen, dass man mit Spalten auch rechnen kann. In e<strong>in</strong>er<br />
Abfrage haben wir e<strong>in</strong>e Ergebnistabelle ausgegeben, die <strong>de</strong>n Preis um 10% erhöht<br />
anzeigt. Die Abfrage dazu lautete:<br />
SELECT Beschreibung, Preis, Preis * 1.10 AS 'Preis + 10%'<br />
FROM Werbeartikel<br />
Zwar wur<strong>de</strong> <strong><strong>de</strong>r</strong> Preis mit <strong>de</strong>m Datentyp DECIMAL(8, 2) <strong>de</strong>klariert, durch die Multiplikation<br />
ergab sich jedoch e<strong>in</strong> Ergebnis, das mehr als zwei Nachkommastellen benötigte.<br />
Diese Konvertierung <strong>in</strong> e<strong>in</strong>en Datentyp mit e<strong>in</strong>em größeren Wertebereich wur<strong>de</strong>
»Built-<strong>in</strong>«-Funktionen<br />
vom RDBMS selbständig durchgeführt. Da e<strong>in</strong> Preis mit vier Nachkommastellen <strong>in</strong> <strong><strong>de</strong>r</strong><br />
Regel nicht gewollt ist, kann man diesen Datentyp explizit <strong>in</strong> e<strong>in</strong>en ganz bestim<strong>mt</strong>en<br />
Datentyp konvertieren. Dazu verwen<strong>de</strong>t man die Funktion CAST. Betrachten wir<br />
zunächst e<strong>in</strong> e<strong>in</strong>faches Beispiel:<br />
SELECT CAST( 9.98 AS INTEGER),<br />
CAST( 1 AS DECIMAL(6,3)),<br />
CAST( '12' AS INTEGER ) * 3<br />
----- ----- -----<br />
9 1.000 36<br />
Wir können erkennen, dass die erste Zahl 9.98 e<strong>in</strong>em numerischem Datentyp mit Nachkommastellen<br />
entspricht. E<strong>in</strong>e Konvertierung <strong>in</strong> e<strong>in</strong>e Ganzzahl, <strong>in</strong> diesem Fall <strong>de</strong>m<br />
Datentyp INTEGER, »schnei<strong>de</strong>t« sozusagen die Nachkommastellen ab, um <strong>de</strong>n Wert <strong>in</strong><br />
e<strong>in</strong>e Ganzzahl zu konvertieren. Die zweite Spalte zeigt die Ganzzahl 1 als 1.000, die <strong>in</strong><br />
<strong>de</strong>n Datentyp DECIMAL(6, 3) konvertiert wur<strong>de</strong>, und <strong>de</strong>shalb drei Nachkommastellen<br />
erhalten hat. Das letzte Beispiel schließlich wan<strong>de</strong>lt e<strong>in</strong>e Zeichenkette <strong>in</strong> e<strong>in</strong>e Ganzzahl<br />
um, so dass mit dieser gerechnet wer<strong>de</strong>n kann (die Konvertierung von '12' ergibt die<br />
Zahl 12, die dann mit 3 multipliziert 36 ergibt).<br />
Betrachten wir nun noch e<strong>in</strong>mal unser obiges Beispiel mit <strong>de</strong>m erhöhten Preis. Um das<br />
Ergebnis <strong><strong>de</strong>r</strong> Berechnung auf zwei Nachkommastellen zu begrenzen, müssen wir e<strong>in</strong>fach<br />
das Ergebnis <strong>in</strong> <strong>de</strong>n Datentyp DECIMAL(8, 2) konvertieren:<br />
SELECT Beschreibung, Preis,<br />
CAST( Preis * 1.10 AS DECIMAL(8, 2) ) AS 'Preis + 10%'<br />
FROM Werbeartikel<br />
Beschreibung Preis Preis + 10%<br />
------------------------- ----- -----------<br />
Noten f. Klavier 89.00 97.90<br />
T-Shirt Farbe: rot 29.99 32.99<br />
Phil Coll<strong>in</strong>s <strong>in</strong> Concert 20.00 22.00<br />
Plakat mit Musical-Katzen 33.50 36.85<br />
Opernführer 19.99 21.99<br />
Schwarzer Zauberstock 5.99 6.59<br />
8.4.6 »Set Functions«<br />
Mengenfunktionen o<strong><strong>de</strong>r</strong> »Set Functions« beziehen sich, wie <strong><strong>de</strong>r</strong> Name schon sagt,<br />
immer auf e<strong>in</strong>e Menge von Werten und berechnen aus dieser Menge je nach Funktion<br />
e<strong>in</strong> bestim<strong>mt</strong>es Ergebnis. So gibt es Mengenfunktionen, um die Werte e<strong>in</strong>er Spalte aufzusummieren,<br />
<strong>de</strong>n Durchschnittswert zu berechnen, <strong>de</strong>n kle<strong>in</strong>sten o<strong><strong>de</strong>r</strong> größten Wert<br />
e<strong>in</strong>er Spalte zu ermitteln o<strong><strong>de</strong>r</strong> e<strong>in</strong>fach nur um die Anzahl <strong><strong>de</strong>r</strong> Werte festzustellen. Da<br />
Mengenfunktionen Werte aggregieren, wer<strong>de</strong>n sie häufig auch als Aggregatfunktionen<br />
bezeichnet.<br />
139
140<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
Um z.B. <strong>de</strong>n Durchschnittspreis e<strong>in</strong>es Werbeartikels zu ermitteln, wür<strong>de</strong> das RDBMS<br />
mit Hilfe <strong><strong>de</strong>r</strong> Mengenfunktion AVG folgen<strong><strong>de</strong>r</strong>maßen vorgehen:<br />
Schauen wir uns als Erstes die Funktion COUNT an. Der Funktion COUNT wird <strong>in</strong> <strong><strong>de</strong>r</strong><br />
Regel <strong><strong>de</strong>r</strong> Name e<strong>in</strong>er Spalte übergeben. COUNT ermittelt dann, wie viele Sätze es gibt,<br />
die e<strong>in</strong>en Wert <strong>in</strong> dieser Spalte haben.<br />
Betrachten wir hierzu die Tabelle »Kun<strong>de</strong>« . Wir wissen, dass die Tabelle »Kun<strong>de</strong>« vier<br />
Datensätze enthält, da wir diese <strong>in</strong> Kapitel 7 über die INSERT-Anweisung e<strong>in</strong>gefügt<br />
haben. Um nun die Anzahl <strong><strong>de</strong>r</strong> Zeilen über e<strong>in</strong>e SELECT-Anweisung zu erhalten,<br />
geben wir e<strong>in</strong>:<br />
SELECT COUNT(Kun<strong>de</strong>nnummer) AS 'Satzanzahl'<br />
FROM Kun<strong>de</strong><br />
Satzanzahl<br />
----------<br />
4<br />
SELECT AVG( Preis ) AS 'Durchschnitt'<br />
FROM Werbeartikel<br />
Beschreibung<br />
Noten f. Klavier<br />
T-Shirt Farbe: rot<br />
Phil Coll<strong>in</strong>s <strong>in</strong> Concert<br />
Schwarzer Zauberstock<br />
Plakat mit <strong>de</strong>n Musical-Katzen<br />
Preis<br />
89.00<br />
29.99<br />
20.00<br />
5.99<br />
33.50<br />
AVG(Preis)<br />
� � ����� � �����<br />
� ����� � ����<br />
� ����� ����<br />
������<br />
Abbildung 8.2: Verwendung von Mengenfunktionen (z.B. AVG)<br />
Mengenfunktionen berücksichtigen bei ihren Berechnungen ke<strong>in</strong>e NULL-Werte. Wäre<br />
also die Kun<strong>de</strong>nnummer e<strong>in</strong>es Datensatzes <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle unbekannt, so wür<strong>de</strong> die<br />
obige Anweisung als Ergebnis 3 zurückgeben. Wir wissen aber, dass »Kun<strong>de</strong>nnummer«<br />
als Primärschlüssel <strong>de</strong>f<strong>in</strong>iert wur<strong>de</strong>. Da Primärschlüssel immer e<strong>in</strong><strong>de</strong>utig se<strong>in</strong><br />
müssen, können hier niemals NULL-Werte auftreten. Wür<strong>de</strong>n wir jedoch anstatt <strong><strong>de</strong>r</strong><br />
»Kun<strong>de</strong>nnummer« die Spalte »Hausnummer« an die Funktion übergeben, wäre das<br />
Ergebnis 3, da bei <strong><strong>de</strong>r</strong> Kund<strong>in</strong> Frieda Wiegerich die Hausnummer nicht e<strong>in</strong>getragen,<br />
also NULL ist.<br />
Als e<strong>in</strong>zige Mengenfunktion bietet COUNT die Möglichkeit, anstelle e<strong>in</strong>es Spaltennamens<br />
auch das Platzhaltersymbol »*« zu verwen<strong>de</strong>n. In diesem Fall wird bei<br />
COUNT immer die komplette Anzahl Sätze zurückgegeben, da COUNT dann alle<br />
Spaltenwerte beim Zählen berücksichtigt.<br />
Die Mengenfunktionen MAX und MIN geben <strong>de</strong>n höchsten und <strong>de</strong>n niedrigsten Wert<br />
e<strong>in</strong>er Spalte zurück. Um z.B. <strong>de</strong>n Werbeartikel mit <strong>de</strong>m höchsten Preis und <strong>de</strong>n Werbeartikel<br />
mit <strong>de</strong>m niedrigsten Preis zu ermitteln, lautet die SELECT-Anweisung:<br />
Preis<br />
35.696
SELECT MAX( Preis ), MIN( Preis )<br />
FROM Werbeartikel<br />
----- -----<br />
89.00 5.99<br />
»Built-<strong>in</strong>«-Funktionen<br />
Der teuerste Werbeartikel kostet also 89.00 Eur und <strong><strong>de</strong>r</strong> günstigste 5.99 Eur.<br />
MIN und MAX funktionieren nicht nur auf Spalten mit numerischem Datentyp. Um<br />
<strong>de</strong>n Namen e<strong>in</strong>es Kun<strong>de</strong>n zu erhalten, <strong><strong>de</strong>r</strong> alphabetisch an erster bzw. an letzter Stelle<br />
steht, lautet die SQL-Anweisung:<br />
SELECT MAX( Name), MIN( Name)<br />
FROM Kun<strong>de</strong><br />
--------- ------<br />
Wiegerich Bolte<br />
Um <strong>de</strong>n Durchschnitt <strong><strong>de</strong>r</strong> Werte e<strong>in</strong>er Spalte zu berechnen, gibt es die Funktion AVG<br />
(»Average« ) und um die Werte e<strong>in</strong>er Spalte aufzusummieren SUM.<br />
Betrachten wir hierzu jeweils e<strong>in</strong> Beispiel. Der Durchschnittspreis aller Werbeartikel<br />
ergibt sich durch folgen<strong>de</strong> SELECT-Anweisung:<br />
SELECT AVG( Preis )<br />
FROM Werbeartikel<br />
----------<br />
33.078333<br />
Durch Anwendung <strong><strong>de</strong>r</strong> Funktion CAST, die wir im vorherigen Abschnitt kennen<br />
gelernt haben, könnten wir zusätzlich noch die Nachkommastellen auf zwei<br />
begrenzen, <strong>in</strong><strong>de</strong>m wir das Ergebnis von AVG(Preis) an die Funktion CAST übergeben:<br />
CAST( AVG( Preis ) AS DECIMAL(8, 2))<br />
Ebenso kann e<strong>in</strong>e Spalte über die Funktion SUM aufsummiert wer<strong>de</strong>n. Als Beispiel<br />
wollen wir e<strong>in</strong>mal <strong>de</strong>n Gesa<strong>mt</strong>wert aller Werbeartikel ausgeben. Der Gesa<strong>mt</strong>wert e<strong>in</strong>es<br />
e<strong>in</strong>zelnen Werbeartikels ergibt sich aus <strong>de</strong>m Preis multipliziert mit <strong>de</strong>m Lagerbestand.<br />
Auf diesen berechneten Wert muss dann die SUM-Funktion wie folgt angewen<strong>de</strong>t wer<strong>de</strong>n:<br />
SELECT SUM( Preis * Lagerbestand ) AS 'Gesa<strong>mt</strong>wert'<br />
FROM Werbeartikel<br />
Gesa<strong>mt</strong>wert<br />
----------<br />
206117.08<br />
141
142<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
Doch halt, diese Summe ersche<strong>in</strong>t etwas hoch! Im letzten Abschnitt haben wir gesehen,<br />
dass Frau Kart für Werbeartikel, <strong><strong>de</strong>r</strong>en Lagerbestand nicht bekannt war, die Zahl 9999<br />
e<strong>in</strong>getragen hat, d.h. 9999 steht für unbekannt, für NULL. Die Funktion SUM weiß<br />
natürlich nicht, dass mit 9999 eigentlich unbekannt geme<strong>in</strong>t ist und betrachtet dies als<br />
<strong>de</strong>n Lagerbestand für <strong>de</strong>n Opernführer. Um das korrekte Ergebnis zu erhalten, müssen<br />
wir die Funktion NULLIF auf Lagerbestand <strong>in</strong>nerhalb <strong><strong>de</strong>r</strong> Berechnung wie folgt verwen<strong>de</strong>n:<br />
SELECT SUM( Preis * NULLIF(Lagerbestand, 9999) ) AS 'Gesa<strong>mt</strong>wert'<br />
FROM Werbeartikel<br />
Gesa<strong>mt</strong>wert<br />
----------<br />
6237.07<br />
Als Ergebnis erhalten wir die korrekte Gesa<strong>mt</strong>summe von 6237,07 Eur. Wir erkennen<br />
hier also e<strong>in</strong> Problem mit unbekannten Werten: Mengenfunktionen berücksichtigen bei<br />
ihren Berechnungen NULL nicht, was ja auch durchaus e<strong>in</strong>leuchtend ersche<strong>in</strong>t. Wur<strong>de</strong><br />
nun aber <strong>in</strong>nerhalb e<strong>in</strong>er Spalte e<strong>in</strong> Wert verwen<strong>de</strong>t, <strong><strong>de</strong>r</strong> semantisch für unbekannt<br />
steht, so kann dies zu falschen Ergebnissen führen. In unserem Fall wäre es also s<strong>in</strong>nvoll,<br />
anstelle <strong><strong>de</strong>r</strong> Zahl 9999 die Kennung NULL zu verwen<strong>de</strong>n.<br />
8.5 Ausdrücke<br />
Wir haben Ausdrücke bereits <strong>in</strong>direkt <strong>in</strong> <strong>de</strong>n bisherigen Anweisungen kennen gelernt.<br />
Der Vollständigkeit halber wollen wir sie hier noch e<strong>in</strong>mal zusammenfassen, ohne im<br />
Detail darauf e<strong>in</strong>zugehen, da sie sich <strong>in</strong> <strong><strong>de</strong>r</strong> Regel aus <strong>de</strong>n Beispielen ergeben.<br />
Mit numerischen Datentypen kann gerechnet wer<strong>de</strong>n. Dementsprechend gibt es Operatoren<br />
für Addition, Subtraktion, Division, Multiplikation sowie Klammern zur Festlegung<br />
<strong><strong>de</strong>r</strong> Berechnungs-Reihenfolge.<br />
Ausdruck Beschreibung Beispiel<br />
+ Addition Preis + 1.00<br />
- Subtraktion Lagerbestand – 6<br />
* Multiplikation Preis * 1.10<br />
/ Division Gesa<strong>mt</strong>wert / Produktanzahl<br />
( ) Klammern (Lagerbestand – 6 ) * 7<br />
Tabelle 8.1: Numerische Ausdrücke<br />
Zeichenketten kennen nur e<strong>in</strong>en e<strong>in</strong>zigen Ausdruck, nämlich <strong>de</strong>n zum Verb<strong>in</strong><strong>de</strong>n von<br />
Zeichenketten. Um z.B. <strong>in</strong>nerhalb e<strong>in</strong>er Abfrage Vor- und Nachname <strong>in</strong> e<strong>in</strong>er Spalte <strong>in</strong><br />
<strong><strong>de</strong>r</strong> Ergebnistabelle auszugeben, verb<strong>in</strong><strong>de</strong>t man diese bei<strong>de</strong>n Spalten über die bei<strong>de</strong>n<br />
Zeichen || mite<strong>in</strong>an<strong><strong>de</strong>r</strong>:
SELECT Name || ', ' || Vorname<br />
FROM Kun<strong>de</strong><br />
-----------------<br />
Bolte, Bertram<br />
Muster, Hans<br />
Wiegerich, Frieda<br />
Carlson, Peter<br />
Sätze auswählen<br />
Ausdruck Beschreibung Beispiel<br />
|| Zeichenketten verb<strong>in</strong><strong>de</strong>n Name || ', ' || Vorname<br />
Zu Datums- und Zeitwerten können Zeit<strong>in</strong>tervalle addiert o<strong><strong>de</strong>r</strong> aber subtrahiert wer<strong>de</strong>n.<br />
Neben <strong>de</strong>n dargestellten Ausdrücken gibt es noch so genannte logische Ausdrücke. Da<br />
diese aber eher beim Auswählen von Zeilen von Be<strong>de</strong>utung s<strong>in</strong>d, wer<strong>de</strong>n wir sie auch<br />
dort behan<strong>de</strong>ln.<br />
Wir haben bisher gelernt, wie man über die SELECT-Anweisung angibt, welche Spalten<br />
e<strong>in</strong>er Tabelle man als Ergebnis erhalten möchte und wie man die unterschiedlichsten<br />
Funktionen auf die angegebenen Spalten anwen<strong>de</strong>n kann. Wie die e<strong>in</strong>zelnen Zeilen<br />
ausgewählt wer<strong>de</strong>n, die man als Ergebnistabelle erhalten möchte, wollen wir uns im<br />
nächsten Abschnitt ansehen.<br />
8.6 Sätze auswählen<br />
8.6.1 Grundlagen<br />
Der allgeme<strong>in</strong>e Aufbau <strong><strong>de</strong>r</strong> SELECT-Anweisung sieht, wie wir bereits kennen gelernt<br />
haben, wie folgt aus:<br />
SELECT spaltenliste<br />
[ FROM tabellenliste ]<br />
[ WHERE bed<strong>in</strong>gungsausdruck ]<br />
[ GROUP BY spaltenliste ]<br />
[ HAVING bed<strong>in</strong>gungsausdruck ]<br />
[ ORDER BY spaltenliste ]<br />
Tabelle 8.2: Zeichenketten Ausdrücke<br />
Ausdruck Beschreibung Beispiel<br />
+ Addition Datum + INTERVAL '7' DAY<br />
- Subtraktion Term<strong>in</strong> – INTERVAL '2' HOUR<br />
Tabelle 8.3: Datum/Zeit Ausdrücke<br />
143
144<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
H<strong>in</strong>ter <strong>de</strong>m Schlüsselwort SELECT wird angegeben, welche Spalten man als Ergebnistabelle<br />
erhalten möchte und h<strong>in</strong>ter <strong>de</strong>m Schlüsselwort FROM, <strong>in</strong> welcher Tabelle sich<br />
die angegebenen Spalten bef<strong>in</strong><strong>de</strong>n. Über das Schlüsselwort WHERE wer<strong>de</strong>n nun die<br />
Zeilen ausgewählt, die <strong>in</strong> <strong><strong>de</strong>r</strong> Ergebnistabelle ausgegeben wer<strong>de</strong>n sollen. Nehmen wir<br />
dazu e<strong>in</strong> e<strong>in</strong>faches Beispiel: Sie möchten die Tabelle »Werbeartikel« ausgeben, jedoch<br />
nur die Zeilen, bei <strong>de</strong>nen <strong><strong>de</strong>r</strong> Artikel mehr als 20.00 Eur kostet. Die folgen<strong>de</strong> Abbildung<br />
ver<strong>de</strong>utlicht das Vorgehen:<br />
SELECT *<br />
FROM Werbeartikel<br />
WHERE Preis > 20.00<br />
Beschreibung<br />
Noten f. Klavier<br />
T-Shirt Farbe: rot<br />
Phil Coll<strong>in</strong>s <strong>in</strong> Concert<br />
Schwarzer Zauberstock<br />
Plakat mit <strong>de</strong>n Musical-Katzen<br />
Preis<br />
89.00<br />
29.99<br />
20.00<br />
5.99<br />
33.50<br />
Filter<br />
����� �<br />
�����<br />
Abbildung 8.3: Selektion (Auswahl von Datensätzen)<br />
Zunächst gibt man h<strong>in</strong>ter <strong><strong>de</strong>r</strong> SELECT-Anweisung an, welche Spalten ausgegeben wer<strong>de</strong>n<br />
sollen. In diesem Fall alle, also wird das Platzhaltersymbol »*« verwen<strong>de</strong>t. Danach<br />
muss h<strong>in</strong>ter FROM bestim<strong>mt</strong> wer<strong>de</strong>n, <strong>in</strong> welcher Tabelle sich die gewünschten Spalten<br />
bef<strong>in</strong><strong>de</strong>n, hier: »FROM Werbeartikel« . Nun soll die Ergebnistabelle noch auf die Zeilen<br />
beschränkt wer<strong>de</strong>n, <strong><strong>de</strong>r</strong>en Preis größer als 20.00 Eur ist. Dafür gibt man h<strong>in</strong>ter WHERE<br />
<strong>de</strong>n entsprechen<strong>de</strong>n Bed<strong>in</strong>gungsausdruck »Preis > 20.00« an. Je<strong>de</strong> Zeile <strong><strong>de</strong>r</strong> Tabelle<br />
Werbeartikel wird nun auf diese Bed<strong>in</strong>gung h<strong>in</strong> überprüft. Der erste Artikel kostet<br />
89.00, damit durchläuft er die Bed<strong>in</strong>gung, die <strong>in</strong> diesem Fall »wahr« ergibt. Dasselbe<br />
gilt für <strong>de</strong>n zweiten Artikel mit e<strong>in</strong>em Preis von 29.99. Der dritte Artikel kostet genau<br />
20.00 Eur. Als Bed<strong>in</strong>gung haben wir angegeben, dass <strong><strong>de</strong>r</strong> Preis größer als 20.00 Eur se<strong>in</strong><br />
soll, daher ergibt die Bed<strong>in</strong>gung hier »falsch« und <strong><strong>de</strong>r</strong> Satz wird nicht <strong>in</strong> die Ergebnistabelle<br />
übernommen.<br />
E<strong>in</strong> Bed<strong>in</strong>gungsausdruck kann aus e<strong>in</strong>er o<strong><strong>de</strong>r</strong> mehreren Bed<strong>in</strong>gungen bestehen, die<br />
über logische Verknüpfungsausdrücke wie OR o<strong><strong>de</strong>r</strong> AND mite<strong>in</strong>an<strong><strong>de</strong>r</strong> verbun<strong>de</strong>n<br />
s<strong>in</strong>d. Der Bed<strong>in</strong>gungsausdruck wird für je<strong>de</strong>n e<strong>in</strong>zelnen Satz auf »wahr« o<strong><strong>de</strong>r</strong> »falsch«<br />
überprüft. Ergibt die Überprüfung »wahr« , so wird er Satz <strong>in</strong> die Ergebnistabelle übernommen,<br />
an<strong><strong>de</strong>r</strong>nfalls nicht. Operatoren von Bed<strong>in</strong>gungen, die als Ergebnis »wahr« ,<br />
»falsch« o<strong><strong>de</strong>r</strong> »unbekannt« zurückliefern, wer<strong>de</strong>n als Prädikate bezeichnet.<br />
Wir wollen uns zunächst mit Bed<strong>in</strong>gungsausdrücken mit nur e<strong>in</strong>er e<strong>in</strong>zigen Bed<strong>in</strong>gung<br />
ause<strong>in</strong>an<strong><strong>de</strong>r</strong>setzen. Danach wer<strong>de</strong>n wir sehen, wie man die e<strong>in</strong>zelnen Bed<strong>in</strong>gungen<br />
mite<strong>in</strong>an<strong><strong>de</strong>r</strong> verknüpft.<br />
8.6.2 Vergleichsprädikate und IS NULL<br />
Beschreibung<br />
Noten f. Klavier<br />
T-Shirt Farbe: rot<br />
Plakat mit <strong>de</strong>n Musical-Katzen<br />
E<strong>in</strong> Vergleichsprädikat haben wir bereits im e<strong>in</strong>leiten<strong>de</strong>n Beispiel kennen gelernt, das<br />
»>« -Zeichen. Insgesa<strong>mt</strong> gibt es sechs Vergleichsprädikate. Für die Überprüfung auf<br />
unbekannte Werte, also auf NULL, gibt es e<strong>in</strong> geson<strong><strong>de</strong>r</strong>tes Prädikat.<br />
Preis<br />
89.00<br />
29.99<br />
33.50
Sätze auswählen<br />
Vergleichsprädikat Beschreibung Beispiel<br />
= gleich Name = 'Muster'<br />
ungleich Lagerbestand 0<br />
> größer als Preis > 20.00<br />
< kle<strong>in</strong>er als Preis < 20.00<br />
>= größer als o<strong><strong>de</strong>r</strong> gleich Preis >= 20.00<br />
SELECT Name, Vorname<br />
FROM Kun<strong>de</strong><br />
WHERE Name LIKE 'B%'<br />
146<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
Möchte man dagegen alle Kun<strong>de</strong>n ausgegeben haben, die an e<strong>in</strong>er beliebigen Stelle <strong>in</strong><br />
ihrem Nachnamen die Zeichen »er« stehen haben, so lautet die Anweisung:<br />
SELECT Name, Vorname<br />
FROM Kun<strong>de</strong><br />
WHERE Name LIKE '%er%'<br />
Der erste Teil <strong>de</strong>s Namens kann beliebige Zeichenfolgen enthalten, dann müssen die<br />
Zeichen »er« folgen und anschließend wie<strong><strong>de</strong>r</strong> e<strong>in</strong>e beliebige Zeichenfolge, was durch<br />
das Platzhaltersymbol »%« ange<strong>de</strong>utet wird.<br />
LIKE kennt neben »%« noch e<strong>in</strong> weiteres Platzhaltersymbol, <strong>de</strong>n Unterstrich. Er steht<br />
im Gegensatz zum »%« -Symbol für genau e<strong>in</strong> e<strong>in</strong>ziges beliebiges Zeichen. Um also alle<br />
Kun<strong>de</strong>n auszugeben, <strong><strong>de</strong>r</strong>en Nachname ab <strong><strong>de</strong>r</strong> dritten Stelle die bei<strong>de</strong>n Buchstaben »lt«<br />
enthält, müssen h<strong>in</strong>ter LIKE zwei Unterstriche für zwei beliebige Buchstaben angegeben<br />
wer<strong>de</strong>n:<br />
SELECT Name, Vorname<br />
FROM Kun<strong>de</strong><br />
WHERE Name LIKE '_ _lt%'<br />
Allerd<strong>in</strong>gs haben wir nun noch e<strong>in</strong> Problem mit <strong>de</strong>m LIKE-Prädikat: Was ist, wenn wir<br />
nach e<strong>in</strong>er Zeichenkette suchen, die das »%« -Zeichen selbst enthält. Dazu bietet das<br />
LIKE-Prädikat über das Schlüsselwort ESCAPE die Möglichkeit, e<strong>in</strong> Zeichen zu <strong>de</strong>f<strong>in</strong>ieren,<br />
das man vor e<strong>in</strong>em Platzhaltersymbol schreiben kann, wenn dieses <strong>in</strong> die Suche<br />
mite<strong>in</strong>bezogen wer<strong>de</strong>n soll. Um also <strong>in</strong> <strong><strong>de</strong>r</strong> Bezeichnung e<strong>in</strong>er Veranstaltung nach <strong><strong>de</strong>r</strong><br />
Zeichenfolge »hun<strong><strong>de</strong>r</strong>t%ig gut« zu suchen, lautet <strong><strong>de</strong>r</strong> SELECT-Befehl:<br />
SELECT Bezeichnung<br />
FROM Veranstaltung<br />
WHERE Bezeichnung LIKE '%hun<strong><strong>de</strong>r</strong>t#%ig gut%' ESCAPE '#'<br />
Das Prädikat LIKE ist zwar sehr nützlich, aber nicht immer ausreichend. Deshalb kennt<br />
SQL:1999 e<strong>in</strong> weitere Prädikat zum Vergleichen von Zeichenketten: SIMILAR. Wer sich<br />
mit UNIX auskennt, hat dort vielleicht schon e<strong>in</strong>mal mit regulären Ausdrücken gearbeitet.<br />
Mit regulären Ausdrücken kann für je<strong>de</strong> Position <strong>in</strong>nerhalb e<strong>in</strong>er Zeichenkette genau<br />
angegeben wer<strong>de</strong>n, welches Zeichen man suchen möchte. Hier soll nicht <strong>de</strong>tailliert auf<br />
das Prädikat SIMILAR e<strong>in</strong>gegangen, son<strong><strong>de</strong>r</strong>n nur kurz e<strong>in</strong> Beispiel erläutert wer<strong>de</strong>n. Um<br />
z.B. nach e<strong>in</strong>er Postleitzahl zu suchen, die als erste Zahl e<strong>in</strong>e 2 o<strong><strong>de</strong>r</strong> 3, dann drei beliebige<br />
Zahlen und als letzte Stelle e<strong>in</strong>e 6 o<strong><strong>de</strong>r</strong> 3 hat, lautet die SELECT-Anweisung:<br />
SELECT Plz<br />
FROM Spielstaette<br />
WHERE Plz SIMILAR TO '[23][0-9][0-9][0-9][63]'
Plz<br />
-----<br />
33333<br />
25746<br />
Sätze auswählen<br />
Für je<strong>de</strong> Position <strong>in</strong>nerhalb <strong><strong>de</strong>r</strong> Suchzeichenkette gibt man <strong>in</strong> eckigen Klammern an,<br />
welchen Wert diese Stelle annehmen darf. Dabei s<strong>in</strong>d auch Bereichsangaben, wie z.B.<br />
0-9, möglich. Hiermit soll beispielhaft gezeigt wer<strong>de</strong>n, wie leistungsfähig reguläre Ausdrücke<br />
s<strong>in</strong>d. Über die Suchzeichenkette, also <strong>de</strong>n regulären Ausdruck, können noch<br />
wesentlich genauere Suchangaben gemacht wer<strong>de</strong>n, als hier vorgestellt. Als kurze E<strong>in</strong>führung<br />
soll dies jedoch ausreichen.<br />
8.6.4 BETWEEN-Prädikat<br />
Um <strong>in</strong>nerhalb e<strong>in</strong>er Abfrage Spalten nach bestim<strong>mt</strong>en Wertebereichen und nicht nur<br />
nach e<strong>in</strong>em e<strong>in</strong>zelnen Wert abzufragen, kennt SQL das BETWEEN-Prädikat. Hiermit<br />
können z.B. Fragen wie »Welche Werbeartikel gibt es, die zwischen 20.00 und 60.00 Eur<br />
kosten?« beantwortet wer<strong>de</strong>n. Betrachten wir die SELECT-Anweisung hierzu:<br />
SELECT Beschreibung, Preis<br />
FROM Werbeartikel<br />
WHERE Preis BETWEEN 20.00 AND 60.00<br />
Beschreibung Preis<br />
------------------------- -----<br />
T-Shirt Farbe: rot 29.99<br />
Phil Coll<strong>in</strong>s <strong>in</strong> Concert 20.00<br />
Plakat mit Musical-Katzen 33.50<br />
Über BETWEEN… AND wird <strong><strong>de</strong>r</strong> Bereich angegeben, <strong>in</strong> <strong>de</strong>m die gesuchten Werte liegen<br />
sollen. Das Prädikat BETWEEN kann auch negiert wer<strong>de</strong>n, d.h. will man alle Werbeartikel<br />
ausgeben, die im Preis nicht zwischen 20.00 und 60.00 Eur liegen, so lautet die<br />
SQL-Anweisung:<br />
SELECT Beschreibung, Preis<br />
FROM Werbeartikel<br />
WHERE Preis NOT BETWEEN 20.00 AND 60.00<br />
8.6.5 IN-Prädikat<br />
Mit <strong>de</strong>m Prädikat IN kann e<strong>in</strong>e bestim<strong>mt</strong>e Spalte auf mehrere Werte h<strong>in</strong> überprüft wer<strong>de</strong>n.<br />
Möchte man z.B. die Postleitzahl von <strong>de</strong>n Orten Rettrich, Karlstadt o<strong><strong>de</strong>r</strong> Kohlscheidt<br />
ermitteln, so lautet die SELECT-Anweisung mit <strong>de</strong>m IN-Prädikat:<br />
SELECT *<br />
FROM Ort<br />
WHERE Ort IN ( 'Rettrich', 'Karlstadt', 'Kohlscheidt')<br />
147
Plz Ort<br />
----- ---------<br />
22222 Karlstadt<br />
33333 Rettrich<br />
44444 Kohlscheidt<br />
148<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
Wie beim BETWEEN-Prädikat auch, kann das IN-Prädikat über das Schlüsselwort<br />
NOT negiert wer<strong>de</strong>n.<br />
8.6.6 Logische Operatoren<br />
Bisher haben wir uns ausschließlich Beispiele mit e<strong>in</strong>er e<strong>in</strong>zigen Bed<strong>in</strong>gung angesehen.<br />
Bed<strong>in</strong>gungen können jedoch über die logischen Operatoren AND, OR und NOT mite<strong>in</strong>an<strong><strong>de</strong>r</strong><br />
verbun<strong>de</strong>n wer<strong>de</strong>n. Um z.B. alle Kun<strong>de</strong>n auszugeben, die männlich s<strong>in</strong>d und<br />
<strong>in</strong> e<strong>in</strong>em Ort mit <strong><strong>de</strong>r</strong> Postleitzahl 44444 wohnen, lautet die SELECT-Anweisung:<br />
SELECT Name, Geschlecht, Plz<br />
FROM Kun<strong>de</strong><br />
WHERE Geschlecht = 'M' AND Plz = '44444'<br />
Name Geschlecht Plz<br />
------- ---------- -----<br />
Bolte M 44444<br />
Carlson M 44444<br />
Möchte man dagegen alle Kun<strong>de</strong>n ausgegeben haben, die entwe<strong><strong>de</strong>r</strong> männlich s<strong>in</strong>d<br />
o<strong><strong>de</strong>r</strong> <strong>in</strong> e<strong>in</strong>em Ort mit <strong><strong>de</strong>r</strong> Postleitzahl 44444 wohnen, so verknüpft man die bei<strong>de</strong>n<br />
Bed<strong>in</strong>gungen wie folgt mit OR:<br />
SELECT Name, Geschlecht, Plz<br />
FROM Kun<strong>de</strong><br />
WHERE Geschlecht = 'M' OR Plz = '44444'<br />
Name Geschlecht Plz<br />
------- ---------- -----<br />
Muster M 22222<br />
Bolte M 44444<br />
Carlson M 44444<br />
Bed<strong>in</strong>gungen können beliebig mit AND, OR o<strong><strong>de</strong>r</strong> NOT verknüpft wer<strong>de</strong>n. Um die Reihenfolge<br />
<strong><strong>de</strong>r</strong> Auswertung <strong><strong>de</strong>r</strong> Ausdrücke zu bestimmen, verwen<strong>de</strong>t man Klammern.<br />
Betrachten wir hierzu e<strong>in</strong> weiteres Beispiel. Wir möchten alle Kun<strong>de</strong>n ausgegeben<br />
haben, die männlich s<strong>in</strong>d o<strong><strong>de</strong>r</strong> <strong>in</strong> e<strong>in</strong>em Ort mit <strong><strong>de</strong>r</strong> Postleitzahl 44444 wohnen und<br />
<strong><strong>de</strong>r</strong>en Name an e<strong>in</strong>er beliebigen Stelle e<strong>in</strong> »e« enthält.<br />
SELECT Name, Geschlecht, Plz<br />
FROM Kun<strong>de</strong><br />
WHERE ( Geschlecht = 'M' OR Plz = '44444' ) AND Name LIKE '%e%'
Name Geschlecht Plz<br />
------- ---------- -----<br />
Muster M 22222<br />
Bolte M 44444<br />
Sätze zusammenfassen<br />
Diesmal fällt <strong><strong>de</strong>r</strong> Kun<strong>de</strong> Carlson aus <strong><strong>de</strong>r</strong> Ergebnismenge heraus. Zunächst überprüft das<br />
RDBMS die Bed<strong>in</strong>gung <strong>in</strong> <strong><strong>de</strong>r</strong> Klammer. Diesen Bed<strong>in</strong>gungsausdruck erfüllt Herr Carlson.<br />
In <strong><strong>de</strong>r</strong> zweiten Bed<strong>in</strong>gung wird geprüft, ob <strong><strong>de</strong>r</strong> Name <strong>de</strong>s Kun<strong>de</strong>n e<strong>in</strong> »e« enthält.<br />
Diese Bed<strong>in</strong>gung erfüllt Herr Carlson nicht. Da nun bei<strong>de</strong> Ergebnisse über <strong>de</strong>n AND-<br />
Operator verknüpft wer<strong>de</strong>n, Herr Carlson aber nur <strong>de</strong>n ersten Bed<strong>in</strong>gungsausdruck<br />
erfüllt und nicht <strong>de</strong>n zweiten, ersche<strong>in</strong>t er letztendlich nicht <strong>in</strong> <strong><strong>de</strong>r</strong> Ergebnistabelle.<br />
Sehen wir uns nun e<strong>in</strong>mal an, wie das Ergebnis aussieht, wenn wir die Klammern weglassen:<br />
SELECT Name, Geschlecht, Plz<br />
FROM Kun<strong>de</strong><br />
WHERE Geschlecht = 'M' OR Plz = '44444' AND Name LIKE '%e%'<br />
Name Geschlecht Plz<br />
------- ---------- -----<br />
Muster M 22222<br />
Bolte M 44444<br />
Carlson M 44444<br />
Jetzt ist Herr Carlson wie<strong><strong>de</strong>r</strong> <strong>in</strong> <strong><strong>de</strong>r</strong> Ergebnistabelle enthalten. Der Grund hierfür liegt<br />
<strong>in</strong> <strong><strong>de</strong>r</strong> Vorgehensweise von SQL bei <strong><strong>de</strong>r</strong> Auswertung <strong>de</strong>s Bed<strong>in</strong>gungsausdrucks. Ohne<br />
Klammerung hat <strong><strong>de</strong>r</strong> AND-Operator Vorrang vor <strong>de</strong>m OR-Operator. Zunächst wer<strong>de</strong>n<br />
alle Kun<strong>de</strong>n herausgesucht, <strong><strong>de</strong>r</strong>en Name e<strong>in</strong> »e« enthält und die gleichzeitig aus e<strong>in</strong>em<br />
Ort mit <strong><strong>de</strong>r</strong> Postleitzahl 44444 stammen. Danach wer<strong>de</strong>n alle Kun<strong>de</strong>n gesucht, die<br />
männlich s<strong>in</strong>d. Diese Bed<strong>in</strong>gung erfüllt Herr Carlson wie<strong><strong>de</strong>r</strong> und da die Verknüpfung<br />
durch OR erfolgt, ersche<strong>in</strong>t er auch <strong>in</strong> <strong><strong>de</strong>r</strong> Ergebnistabelle.<br />
Wir haben nun die wichtigsten Sprachelemente <strong><strong>de</strong>r</strong> SELECT-Anweisung kennen<br />
gelernt, die sich auf e<strong>in</strong>e e<strong>in</strong>zige Tabelle beziehen. In <strong>de</strong>n letzten bei<strong>de</strong>n Abschnitten<br />
wollen wir noch e<strong>in</strong>mal sehen, wie man die Ergebnistabelle sortiert o<strong><strong>de</strong>r</strong> nach bestim<strong>mt</strong>en<br />
Spalten gruppiert.<br />
8.7 Sätze zusammenfassen<br />
Betrachten wir zunächst wie<strong><strong>de</strong>r</strong> <strong>de</strong>n allgeme<strong>in</strong>en Aufbau <strong><strong>de</strong>r</strong> SELECT-Anweisung:<br />
SELECT spaltenliste<br />
[ FROM tabellenliste ]<br />
[ WHERE bed<strong>in</strong>gungsausdruck ]<br />
[ GROUP BY spaltenliste ]<br />
[ HAVING bed<strong>in</strong>gungsausdruck ]<br />
[ ORDER BY spaltenliste ]<br />
149
150<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
Bisher haben wir gesehen, wie man Spalten h<strong>in</strong>ter <strong>de</strong>m Schlüsselwort SELECT, Tabellen<br />
h<strong>in</strong>ter <strong>de</strong>m Schlüsselwort FROM und Zeilen aufgrund von Bed<strong>in</strong>gungsausdrücken<br />
h<strong>in</strong>ter <strong>de</strong>m Schlüsselwort WHERE auswählt. Damit s<strong>in</strong>d wir schon <strong>in</strong> <strong><strong>de</strong>r</strong> Lage, die<br />
unterschiedlichsten Informationen aus e<strong>in</strong>er Datenbank, bezogen auf e<strong>in</strong>e e<strong>in</strong>zige<br />
Tabelle, herauszusuchen.<br />
Neben <strong>de</strong>m re<strong>in</strong>en Suchen und F<strong>in</strong><strong>de</strong>n von Daten kann man mit <strong><strong>de</strong>r</strong> SELECT-Anweisung<br />
aber auch Daten kumulieren. Damit dient die SELECT-Anweisung u.a. auch <strong><strong>de</strong>r</strong><br />
Analyse von Daten, <strong>in</strong><strong>de</strong>m sie Werte aggregiert. Hierzu kennt die SELECT-Anweisung<br />
die Schlüsselwörter GROUP BY. Über GROUP BY kann man die Daten nach bestim<strong>mt</strong>en<br />
Spalten gruppieren, d.h. es wer<strong>de</strong>n Gruppen mit gleichen Werten gebil<strong>de</strong>t. Für<br />
diese Gruppen wird <strong>in</strong> <strong><strong>de</strong>r</strong> Regel e<strong>in</strong>e Berechnung durchgeführt. Berechnungen auf<br />
mehrere Werte e<strong>in</strong>er Spalte haben wir bisher nur bei <strong>de</strong>n Mengen- o<strong><strong>de</strong>r</strong> Aggregatfunktionen<br />
kennen gelernt. GROUP BY ist <strong>in</strong> <strong><strong>de</strong>r</strong> Regel auch nur <strong>in</strong> Zusammenhang mit<br />
e<strong>in</strong>er Mengenfunktion s<strong>in</strong>nvoll.<br />
Betrachten wir e<strong>in</strong> e<strong>in</strong>faches Beispiel: Wir wollen Gruppen von Kun<strong>de</strong>n bil<strong>de</strong>n, die aus<br />
<strong>de</strong>m gleichen Ort stammen, die also die gleiche Postleitzahl haben. Um alle Postleitzahlen<br />
auszugeben, sieht die SELECT-Anweisung folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
SELECT Plz<br />
FROM Kun<strong>de</strong><br />
Plz<br />
-----<br />
44444<br />
22222<br />
33333<br />
44444<br />
In <strong><strong>de</strong>r</strong> Ergebnistabelle wer<strong>de</strong>n Postleitzahlen auch doppelt aufgeführt, da zwei Kun<strong>de</strong>n<br />
(Bolte und Carlson) aus <strong>de</strong>m gleichen Ort mit <strong><strong>de</strong>r</strong> Postleitzahl 44444 stammen. Um<br />
doppelte Werte zu entfernen, haben wir vorher bereits das Schüsselwort DISTINCT<br />
kennen gelernt. Fügen wir also direkt h<strong>in</strong>ter SELECT das Schlüsselwort DISTINCT e<strong>in</strong>,<br />
so wird die Postleitzahl 44444 nur e<strong>in</strong>mal aufgeführt. Doch es gibt noch e<strong>in</strong>e an<strong><strong>de</strong>r</strong>e<br />
Möglichkeit: Wir können gleiche Werte über GROUP BY zusammenfassen. Das Ganze<br />
sieht dann wie folgt aus:<br />
SELECT Plz<br />
FROM Kun<strong>de</strong><br />
GROUP BY Plz<br />
Plz<br />
-----<br />
22222<br />
33333<br />
44444
Sätze zusammenfassen<br />
Damit haben wir zunächst das gleiche Ergebnis erzielt wie mit <strong>de</strong>m Schlüsselwort DIS-<br />
TINCT. Hier wer<strong>de</strong>n jetzt aber die Mengenfunktionen <strong>in</strong>teressant. Normalerweise<br />
kann man Mengenfunktionen <strong>in</strong> <strong><strong>de</strong>r</strong> Spaltenliste nicht mit Spaltennamen komb<strong>in</strong>ieren.<br />
Folgen<strong>de</strong> SELECT-Anweisung wür<strong>de</strong> also e<strong>in</strong>e Fehlermeldung erzeugen:<br />
SELECT COUNT(Plz), Name -- falsche SELECT-Anweisung<br />
FROM Kun<strong>de</strong><br />
Das ist auch e<strong>in</strong>leuchtend, <strong>de</strong>nn COUNT(Plz) wür<strong>de</strong> nur e<strong>in</strong>e Zeile, nämlich die Zahl 4<br />
zurückliefern. Name dagegen wür<strong>de</strong> vier Werte zurückliefern, nämlich Bolte, Muster,<br />
Wiegerich und Carlson.<br />
Wir können nun aber bei<strong>de</strong> Abfragen mite<strong>in</strong>an<strong><strong>de</strong>r</strong> komb<strong>in</strong>ieren, <strong>in</strong><strong>de</strong>m wir zum e<strong>in</strong>en<br />
die Anzahl <strong><strong>de</strong>r</strong> Plz über COUNT zählen, gruppiert nach <strong>de</strong>n unterschiedlichen Plz. Die<br />
folgen<strong>de</strong> SELECT-Anweisung gibt alle unterschiedlichen Postleitzahlen, und die<br />
Anzahl <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n zurück, die <strong>in</strong> <strong>de</strong>m Ort mit <strong><strong>de</strong>r</strong> jeweiligen Postleitzahl wohnen:<br />
SELECT Plz, COUNT(Plz) AS 'Anzahl Kun<strong>de</strong>n/Plz'<br />
FROM Kun<strong>de</strong><br />
GROUP BY Plz<br />
Plz Anzahl Kun<strong>de</strong>n/Plz<br />
----- -----------------<br />
22222 1<br />
33333 1<br />
44444 2<br />
Grafisch sieht das Ganze wie folgt aus:<br />
SELECT Plz, COUNT(Plz)<br />
FROM Kun<strong>de</strong><br />
GROUP BY Plz<br />
Name<br />
Bolte<br />
Muster<br />
Wiegerich<br />
Carlson<br />
Strasse<br />
Busweg<br />
Musterweg<br />
Wan<strong><strong>de</strong>r</strong>str.<br />
Petristr.<br />
Hausnummer<br />
12<br />
12<br />
NULL<br />
201<br />
Plz<br />
44444<br />
22222<br />
33333<br />
44444<br />
44444<br />
44444<br />
Abbildung 8.4: Zusammenfassen von Sätzen<br />
Wir sehen also, dass unsere Kun<strong>de</strong>n aus Orten mit <strong>de</strong>n Postleitzahlen 22222, 33333 und<br />
44444 kommen. Zwei Kun<strong>de</strong>n wohnen <strong>in</strong> <strong>de</strong>m Ort mit <strong><strong>de</strong>r</strong> Postleitzahl 44444 und je e<strong>in</strong><br />
Kun<strong>de</strong> <strong>in</strong> <strong>de</strong>n Orten mit <strong>de</strong>n an<strong><strong>de</strong>r</strong>en bei<strong>de</strong>n Postleitzahlen.<br />
Betrachten wir noch e<strong>in</strong>mal <strong>de</strong>n allgeme<strong>in</strong>en Aufbau <strong><strong>de</strong>r</strong> SELECT-Anweisung am<br />
Anfang diese Abschnitts 8.7, so sehen wir unmittelbar unter <strong><strong>de</strong>r</strong> GROUP BY-Klausel<br />
Plz<br />
22222<br />
33333<br />
} }<br />
Plz<br />
22222<br />
33333<br />
44444<br />
COUNT(Plz)<br />
1<br />
1<br />
2<br />
151
152<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
das Schlüsselwort HAVING. Mit HAVING kann die Ergebnistabelle e<strong>in</strong>er GROUP BY-<br />
Abfrage e<strong>in</strong>geschränkt wer<strong>de</strong>n. Angenommen es sollen alle Postleitzahlen und die<br />
Anzahl <strong><strong>de</strong>r</strong> <strong>in</strong> diesen Orten wohnen<strong>de</strong>n Kun<strong>de</strong>n ermittelt wer<strong>de</strong>n, aber nur wenn die<br />
Anzahl <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n pro Ort größer als 1 ist, so lautet die SELECT-Anweisung:<br />
SELECT Plz, COUNT(Plz) AS 'Anzahl Kun<strong>de</strong>n/Plz'<br />
FROM Kun<strong>de</strong><br />
GROUP BY Plz<br />
HAVING COUNT(Plz) > 1<br />
Plz Anzahl Kun<strong>de</strong>n/Plz<br />
----- -----------------<br />
44444 2<br />
Jetzt wer<strong>de</strong>n nur die Postleitzahlen von Orten angezeigt, wo m<strong>in</strong><strong>de</strong>stens zwei Kun<strong>de</strong>n<br />
wohnen. Wie wür<strong>de</strong> nun die Abfrage lauten, wenn man die Anzahl <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n pro<br />
Ort ermitteln möchte, diesmal aber nur für Postleitzahlen größer 22222? Hierfür gibt es<br />
zwei Möglichkeiten: Entwe<strong><strong>de</strong>r</strong> über die HAVING-Klausel, wie wir es gera<strong>de</strong> am Beispiel<br />
gesehen haben, o<strong><strong>de</strong>r</strong> aber über die WHERE-Klausel. Die bei<strong>de</strong>n folgen<strong>de</strong>n<br />
SELECT-Anweisungen s<strong>in</strong>d i<strong>de</strong>ntisch und liefern die gleiche Ergebnistabelle:<br />
SELECT Plz, COUNT(Plz) AS 'Anzahl Kun<strong>de</strong>n/Plz'<br />
FROM Kun<strong>de</strong><br />
GROUP BY Plz<br />
HAVING Plz > '22222'<br />
SELECT Plz, COUNT(Plz) AS 'Anzahl Kun<strong>de</strong>n/Plz'<br />
FROM Kun<strong>de</strong><br />
WHERE Plz > '22222'<br />
GROUP BY Plz<br />
Die GROUP BY-Klausel dient <strong>in</strong> <strong><strong>de</strong>r</strong> Regel analytischen Zwecken, um z.B. <strong>de</strong>n Umsatz<br />
<strong><strong>de</strong>r</strong> letzten drei Monate gruppiert nach Kun<strong>de</strong>ngruppen o.ä. auszugeben. Man spricht<br />
<strong>de</strong>shalb <strong>in</strong> diesem Zusammenhang auch von OLAP (»OnL<strong>in</strong>e Analytical Process<strong>in</strong>g« ):<br />
Mengen von Daten wer<strong>de</strong>n zusammengefasst und analysiert. OLAP enthält jedoch viel<br />
mehr Eigenschaften als das re<strong>in</strong>e Zusammenfassen und Gruppieren von Werten. Der<br />
SQL:1999 Standard sieht <strong>de</strong>shalb e<strong>in</strong>en eigenen Teil für OLAP vor, <strong><strong>de</strong>r</strong> allerd<strong>in</strong>gs nicht<br />
Bestandteil dieses Buches ist.<br />
SQL:1999 kennt jedoch noch zwei weitere grundlegen<strong>de</strong> Schlüsselwörter, die man <strong>in</strong><br />
Zusammenhang mit <strong><strong>de</strong>r</strong> GROUP BY-Klausel verwen<strong>de</strong>t: ROLLUP und CUBE.<br />
Bei Verwendung <strong><strong>de</strong>r</strong> GROUP BY-Klausel haben wir bisher immer nur nach e<strong>in</strong>em ganz<br />
bestim<strong>mt</strong>en Wert gruppiert. Haben wir z.B. als Gruppierungsspalte die bei<strong>de</strong>n Attribute<br />
Plz und Geschlecht angegeben, so wur<strong>de</strong>n immer alle Datensätze zusammengefasst,<br />
für die bei<strong>de</strong> Werte i<strong>de</strong>ntisch s<strong>in</strong>d. ROLLUP ist dann s<strong>in</strong>nvoll, wenn man nach<br />
mehr als e<strong>in</strong>er e<strong>in</strong>zigen Spalte gruppieren möchte, <strong>in</strong> diesem Fall also nach Plz und<br />
Geschlecht. Um e<strong>in</strong>e Liste gruppiert nach Plz, e<strong>in</strong>e weitere Liste gruppiert nach
Sätze zusammenfassen<br />
Geschlecht und e<strong>in</strong>e dritte Liste gruppiert nach bei<strong>de</strong>n Spalten zu erhalten, müssten<br />
folgen<strong>de</strong> drei SELECT-Anweisungen geschrieben wer<strong>de</strong>n:<br />
SELECT Geschlecht, COUNT(*) AS 'Anzahl Kun<strong>de</strong>n'<br />
FROM Kun<strong>de</strong><br />
GROUP BY Geschlecht<br />
SELECT Plz, COUNT(*) AS 'Anzahl Kun<strong>de</strong>n'<br />
FROM Kun<strong>de</strong><br />
GROUP BY Plz<br />
SELECT Geschlecht, Plz, COUNT(*) AS 'Anzahl Kun<strong>de</strong>n'<br />
FROM Kun<strong>de</strong><br />
GROUP BY Geschlecht, Plz<br />
Die erste Abfrage gibt die Anzahl <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n bezogen auf ihr Geschlecht zurück, die<br />
zweite die Anzahl <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n bezogen auf <strong>de</strong>n Wohnort und die letzte Abfrage die<br />
Anzahl <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n bezogen auf bei<strong>de</strong> Attribute.<br />
Die Ergebnistabellen sehen also wie folgt aus:<br />
Geschlecht Anzahl Kun<strong>de</strong>n<br />
---------- -------------<br />
M 3<br />
W 1<br />
Plz Anzahl Kun<strong>de</strong>n<br />
----- -------------<br />
22222 1<br />
33333 1<br />
44444 2<br />
Geschlecht Plz Anzahl Kun<strong>de</strong>n<br />
---------- ----- -------------<br />
M 22222 1<br />
W 33333 1<br />
M 44444 2<br />
Um nun nicht drei verschie<strong>de</strong>ne Abfragen zu erstellen verwen<strong>de</strong>t man ROLLUP und<br />
CUBE, um aus diesen drei Ergebnistabellen e<strong>in</strong>e e<strong>in</strong>zige zu erzeugen. Mit ROLLUP<br />
kann man die erste und dritte Abfrage <strong>in</strong> e<strong>in</strong>er Abfrage ausdrücken. Die SELECT-<br />
Anweisung und die dazugehörige Ergebnistabelle sehen dann wie folgt aus:<br />
SELECT Geschlecht, Plz, COUNT(*) AS 'Anzahl Kun<strong>de</strong>n'<br />
FROM Kun<strong>de</strong><br />
GROUP BY ROLLUP( Geschlecht, Plz )<br />
153
Geschlecht Plz Anzahl Kun<strong>de</strong>n<br />
---------- ----- -------------<br />
M 22222 1<br />
M 44444 2<br />
M NULL 3<br />
W 33333 1<br />
W NULL 1<br />
NULL NULL 4<br />
154<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
Aus dieser Ergebnistabelle s<strong>in</strong>d fast die gleichen Informationen herauszulesen, wie aus<br />
<strong>de</strong>n oberen drei Tabellen. Insgesa<strong>mt</strong> gibt es 4 Kun<strong>de</strong>n, 1 weiblichen und 3 männliche<br />
Kun<strong>de</strong>n. Aus <strong>de</strong>m Wohnort mit <strong><strong>de</strong>r</strong> Postleitzahl 44444 kommen 2 männliche Kun<strong>de</strong>n,<br />
ansonsten gibt es ke<strong>in</strong>e Kun<strong>de</strong>n, die <strong>in</strong> e<strong>in</strong>em Ort mit <strong><strong>de</strong>r</strong> gleichen Postleitzahl wohnen.<br />
Allerd<strong>in</strong>gs fehlt <strong>in</strong> diesem Ergebnis die Gruppierung nach <strong><strong>de</strong>r</strong> Postleitzahl. ROLLUP<br />
gruppiert nach bei<strong>de</strong>n Attributen und zusätzlich nach <strong>de</strong>m ersten angegebenen Attribut<br />
h<strong>in</strong>ter GROUP BY.<br />
Um nun zusätzlich auch nach <strong>de</strong>m zweiten Attribut, also Plz geson<strong><strong>de</strong>r</strong>t zu gruppieren,<br />
verwen<strong>de</strong>t man CUBE. Die SELECT-Anweisung und die dazugehörige Ergebnistabelle<br />
sehen dann folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
SELECT Geschlecht, Plz, COUNT(*) AS 'Anzahl Kun<strong>de</strong>n'<br />
FROM Kun<strong>de</strong><br />
GROUP BY CUBE( Geschlecht, Plz )<br />
Geschlecht Plz Anzahl Kun<strong>de</strong>n<br />
---------- ----- -------------<br />
M 22222 1<br />
M 44444 2<br />
M NULL 3<br />
W 33333 1<br />
W NULL 1<br />
NULL NULL 4<br />
NULL 22222 1<br />
NULL 33333 1<br />
NULL 44444 2<br />
8.8 Sätze sortieren<br />
Die Reihenfolge <strong><strong>de</strong>r</strong> Datensätze unserer bisherigen Ergebnistabellen waren bisher eher<br />
zufällig. Da SQL mathematisch auf <strong><strong>de</strong>r</strong> Mengenlehre basiert, kennt es generell ke<strong>in</strong>e<br />
Reihenfolgen von Spalten o<strong><strong>de</strong>r</strong> Sätzen. SQL bietet <strong>de</strong>shalb die Möglichkeit, die Ergebnistabelle<br />
zu sortieren. Betrachten wir hierzu noch e<strong>in</strong>mal <strong>de</strong>n allgeme<strong>in</strong>en Aufbau <strong><strong>de</strong>r</strong><br />
SELECT-Anweisung:
SELECT spaltenliste<br />
[ FROM tabellenliste ]<br />
[ WHERE bed<strong>in</strong>gungsausdruck ]<br />
[ GROUP BY spaltenliste ]<br />
[ HAVING bed<strong>in</strong>gungsausdruck ]<br />
[ ORDER BY spaltenliste ]<br />
Sätze sortieren<br />
Die ORDER BY-Klausel ersche<strong>in</strong>t immer am En<strong>de</strong> e<strong>in</strong>er SELECT-Anweisung und dient<br />
zum Sortieren <strong><strong>de</strong>r</strong> Ergebnistabelle. H<strong>in</strong>ter ORDER BY folgt e<strong>in</strong>e Spaltenliste, nach <strong><strong>de</strong>r</strong><br />
die Ergebnistabelle sortiert wer<strong>de</strong>n soll. H<strong>in</strong>ter je<strong><strong>de</strong>r</strong> Spalte wie<strong><strong>de</strong>r</strong>um kann über die<br />
Schlüsselwörter ASC (»ascend<strong>in</strong>g« ) o<strong><strong>de</strong>r</strong> DESC (»<strong>de</strong>scend<strong>in</strong>g« ) festgelegt wer<strong>de</strong>n, ob<br />
nach dieser Spalte aufsteigend o<strong><strong>de</strong>r</strong> absteigend sortiert wer<strong>de</strong>n soll.<br />
Betrachten wir hierzu e<strong>in</strong> e<strong>in</strong>faches Beispiel: Wir wollen Name, Vorname und Plz aller<br />
Kun<strong>de</strong>n ausgeben, sortiert nach <strong><strong>de</strong>r</strong> Spalte »Plz« <strong>in</strong> aufsteigen<strong><strong>de</strong>r</strong> Reihenfolge.<br />
SELECT Plz, Name, Vorname<br />
FROM Kun<strong>de</strong><br />
ORDER BY Plz<br />
Plz Name Vorname<br />
----- --------- -------<br />
22222 Muster Hans<br />
33333 Wiegerich Frieda<br />
44444 Carlson Peter<br />
44444 Bolte Bertram<br />
Möchte man aufsteigend sortieren, kann man auf das Schlüsselwort ASC verzichten,<br />
wie <strong>in</strong> <strong><strong>de</strong>r</strong> SELECT-Anweisung zu sehen. Anstatt e<strong>in</strong>en Spaltennamen anzugeben,<br />
kann auch e<strong>in</strong>e Zahl als Spalte angeben wer<strong>de</strong>n. Diese Zahl entspricht <strong><strong>de</strong>r</strong> Rangfolge<br />
<strong><strong>de</strong>r</strong> Spalten, wie sie h<strong>in</strong>ter <strong><strong>de</strong>r</strong> SELECT-Anweisung aufgeführt wer<strong>de</strong>n. Um z.B. absteigend<br />
nach Name zu sortieren, kann man schreiben:<br />
SELECT Plz, Name, Vorname<br />
FROM Kun<strong>de</strong><br />
ORDER BY 2 DESC<br />
Plz Name Vorname<br />
----- --------- -------<br />
33333 Wiegerich Frieda<br />
22222 Muster Hans<br />
44444 Carlson Peter<br />
44444 Bolte Bertram<br />
Generell ist es allerd<strong>in</strong>gs vorteilhafter, <strong>de</strong>n Namen e<strong>in</strong>er Spalte zu verwen<strong>de</strong>n. Än<strong><strong>de</strong>r</strong>t<br />
man nämlich die Reihenfolge <strong><strong>de</strong>r</strong> Spalten h<strong>in</strong>ter SELECT, muss auch die Zahl zur Sortierung<br />
geän<strong><strong>de</strong>r</strong>t wer<strong>de</strong>n. Dieser zweite Arbeitsschritt entfällt bei Verwendung <strong>de</strong>s<br />
Spaltennamens.<br />
155
156<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
Ergebnistabellen können auch nach berechneten Spalten sortiert wer<strong>de</strong>n. Da berechnete<br />
Spalten normalerweise ke<strong>in</strong>en eigenen Spaltennamen haben, muss e<strong>in</strong>e Zahl als<br />
Sortierspalte angeben wer<strong>de</strong>n. Besser ist jedoch, <strong><strong>de</strong>r</strong> berechneten Spalte über das<br />
Schlüsselwort AS e<strong>in</strong>en Namen zu geben und diesen bei <strong><strong>de</strong>r</strong> Sortierung zu verwen<strong>de</strong>n.<br />
Um z.B. <strong>de</strong>n Gesa<strong>mt</strong>wert e<strong>in</strong>es je<strong>de</strong>n Werbeartikels auszugeben und nach diesem zu<br />
sortieren, schreibt man folgen<strong>de</strong> SELECT-Anweisung:<br />
SELECT Beschreibung, Preis * Lagerbestand AS 'Gesa<strong>mt</strong>wert'<br />
FROM Werbeartikel<br />
ORDER BY Gesa<strong>mt</strong>wert<br />
Beschreibung Gesa<strong>mt</strong>wert<br />
------------------------- ----------<br />
Schwarzer Zauberstock 191.68<br />
T-Shirt Farbe: rot 329.89<br />
Phil Coll<strong>in</strong>s <strong>in</strong> Concert 420.00<br />
Noten f. Klavier 2314.00<br />
Plakat mit Musical-Katzen 2981.50<br />
Innerhalb <strong><strong>de</strong>r</strong> ORDER BY-Klausel können auch Berechnungen durchgeführt und nach<br />
diesen Berechnungen sortiert wer<strong>de</strong>n. Spalten, nach <strong>de</strong>nen sortiert wur<strong>de</strong>, müssen<br />
nicht unbed<strong>in</strong>gt h<strong>in</strong>ter SELECT aufgeführt se<strong>in</strong>. Um also die Werbeartikel nach ihrem<br />
Gesa<strong>mt</strong>wert zu sortieren, kann man auch schreiben:<br />
SELECT Beschreibung<br />
FROM Werbeartikel<br />
ORDER BY Preis * Lagerbestand<br />
8.9 Zusammenfassung<br />
In diesem Kapitel haben wir gesehen, wie man Daten aus e<strong>in</strong>er Tabelle abfragen kann<br />
und dass die Ergebnisse auch als Tabellen ausgegeben wer<strong>de</strong>n. Die SQL-Anweisung<br />
zum Abfragen von Tabellen lautet SELECT. Ihr allgeme<strong>in</strong>er Aufbau sieht folgen<strong><strong>de</strong>r</strong>maßen<br />
aus:<br />
SELECT spaltenliste -- Spaltenauswahl<br />
[ FROM tabellenliste ] -- Tabellenauswahl<br />
[ WHERE bed<strong>in</strong>gungsausdruck ] -- Zeilenauswahl<br />
[ GROUP BY spaltenliste ] -- Gruppieren/Aggregieren<br />
[ HAVING bed<strong>in</strong>gungsausdruck ] -- Gruppenauswahl<br />
[ ORDER BY spaltenliste ] -- Sortieren<br />
Wir haben uns <strong>in</strong> diesem Kapitel mit <strong>de</strong>n e<strong>in</strong>zelnen Bestandteilen <strong><strong>de</strong>r</strong> SELECT-Anweisung<br />
ause<strong>in</strong>an<strong><strong>de</strong>r</strong>gesetzt.<br />
Über SELECT wer<strong>de</strong>n Spalten auswählt, die <strong>in</strong> <strong><strong>de</strong>r</strong> Ergebnistabelle angezeigt wer<strong>de</strong>n<br />
sollen. Auf Spalten kann man Berechnungen durchführen o<strong><strong>de</strong>r</strong> so genannte »Built-<strong>in</strong>« -
Aufgaben<br />
Funktionen anwen<strong>de</strong>n. Hierbei gibt es Funktionen zum Än<strong><strong>de</strong>r</strong>n o<strong><strong>de</strong>r</strong> Heraustrennen<br />
von Zeichenketten, zum Konvertieren <strong>in</strong> e<strong>in</strong>en an<strong><strong>de</strong>r</strong>en Datentyp, zum Herauslesen<br />
<strong><strong>de</strong>r</strong> e<strong>in</strong>zelnen Bestandteile e<strong>in</strong>es Datums o<strong><strong>de</strong>r</strong> e<strong>in</strong>er Uhrzeit usw. E<strong>in</strong>e Gruppe dieser<br />
Funktionen s<strong>in</strong>d die Mengen- o<strong><strong>de</strong>r</strong> Aggregatfunktionen. Im Gegensatz zu <strong>de</strong>n an<strong><strong>de</strong>r</strong>en<br />
Funktionsgruppen, liefern sie e<strong>in</strong> Ergebnis zurück, dass sich auf mehrere Sätze beziehen<br />
kann. Mit Mengenfunktionen können Werte e<strong>in</strong>er Spalte summiert wer<strong>de</strong>n, es<br />
kann <strong><strong>de</strong>r</strong> Durchschnitt ermittelt wer<strong>de</strong>n usw. Gera<strong>de</strong> bei <strong>de</strong>n e<strong>in</strong>zelnen Funktionen<br />
gibt es zur Zeit erhebliche Unterschie<strong>de</strong> zwischen <strong>de</strong>n e<strong>in</strong>zelnen RDBMS-Produkten.<br />
Die Funktionalität <strong><strong>de</strong>r</strong> hier vorgestellten Funktionen existiert <strong>in</strong> <strong><strong>de</strong>r</strong> Regel zwar bei<br />
allen RDBMS-Produkten. Häufig jedoch unterschei<strong>de</strong>n sich die Funktionen <strong><strong>de</strong>r</strong><br />
RDBMS-Produkte und <strong>de</strong>s SQL:1999 Standards <strong>in</strong> <strong>de</strong>n Bezeichnungen und <strong>de</strong>m Aufruf<br />
<strong><strong>de</strong>r</strong> jeweiligen Funktionen. Die hier kennen gelernten Funktionen entsprechen <strong>de</strong>m<br />
SQL:1999 Standard.<br />
Mit <strong><strong>de</strong>r</strong> FROM-Klausel wird spezifiziert, <strong>in</strong> welchen Tabellen sich die Spalten bef<strong>in</strong><strong>de</strong>n,<br />
die ausgewählt wer<strong>de</strong>n sollen. Bestim<strong>mt</strong>e Datensätze wie<strong><strong>de</strong>r</strong>um wer<strong>de</strong>n mit <strong>de</strong>m<br />
Schlüsselwort WHERE ausgewählt. H<strong>in</strong>ter WHERE schreibt man e<strong>in</strong>en Bed<strong>in</strong>gungsausdruck,<br />
<strong><strong>de</strong>r</strong> die Ergebnistabelle auf die gewünschten Sätze beschränkt. Der Bed<strong>in</strong>gungsausdruck<br />
setzt sich aus verschie<strong>de</strong>nen Prädikaten zusammen. Die wichtigsten<br />
Prädikate s<strong>in</strong>d die Vergleichsprädikate, daneben gibt es IS NULL, LIKE, SIMILAR,<br />
BETWEEN und IN. Mehrere Bed<strong>in</strong>gungen wer<strong>de</strong>n über die logischen Operatoren<br />
AND, OR und NOT verknüpft.<br />
Die GROUP BY-Klausel wird <strong>in</strong> Zusammenhang mit <strong><strong>de</strong>r</strong> Anwendung von Mengenfunktionen<br />
verwen<strong>de</strong>t. Über GROUP BY kann man Datensätze zusammenfassen und<br />
aggregierte Werte für die zusammengefassten Gruppen errechnen. Um die gruppierten<br />
Datensätze wie<strong><strong>de</strong>r</strong> auf bestim<strong>mt</strong>e Gruppen zu beschränken, verwen<strong>de</strong>t man HAVING.<br />
Der letzte SELECT-Bestandteil dient schließlich <strong>de</strong>m Sortieren <strong><strong>de</strong>r</strong> Ergebnistabelle.<br />
Über die Schlüsselwörter ORDER BY kann die Ergebnistabelle nach Spalten sortiert<br />
wer<strong>de</strong>n.<br />
Bis hierher haben wir also gelernt, wie man aus e<strong>in</strong>er e<strong>in</strong>zelnen Tabelle Informationen<br />
heraussucht. Das nächste Kapitel beschäftigt sich daher mit <strong>de</strong>m F<strong>in</strong><strong>de</strong>n von Daten aus<br />
mehreren Tabellen.<br />
8.10 Aufgaben<br />
Wie<strong><strong>de</strong>r</strong>holungsfragen<br />
1) Über welches Schlüsselwort benennt man e<strong>in</strong>e Spalte um?<br />
2) Wozu dienen die Funktionen TRIM, SUBSTRING, UPPER, POSITION und EXTRACT?<br />
3) Was liefert <strong><strong>de</strong>r</strong> Ausdruck NULLIF( 10.99, 10.99 ) zurück?<br />
4) Was liefert <strong><strong>de</strong>r</strong> Ausdruck POSITION( 'ist' IN 'Dies ist e<strong>in</strong> Beispieltext') zurück?<br />
5) Was liefern die Funktionen CURRENT_DATE und CURRENT_TIME zurück?<br />
6) Welches Ergebnis liefert <strong><strong>de</strong>r</strong> Ausdruck »10 NOT BETWEEN 20 AND 30« ?<br />
7) Welches Ergebnis liefert <strong><strong>de</strong>r</strong> Ausdruck »NOT( 10 >= 20 AND 10 >= 30 )« ?<br />
157
158<br />
8 E<strong>in</strong>e Tabelle abfragen<br />
8) Welches Ergebnis liefert <strong><strong>de</strong>r</strong> Ausdruck »'Hamburg' IN ('München', 'Frankfurt',<br />
'Berl<strong>in</strong>')« ?<br />
9) Welches Ergebnis liefert <strong><strong>de</strong>r</strong> Ausdruck »'Hamburg' = 'München' OR 'Hamburg'<br />
='Frankfurt' OR 'Hamburg' = 'Berl<strong>in</strong>')« ?<br />
10) Welches Ergebnis liefert <strong><strong>de</strong>r</strong> Ausdruck »10 10« ?<br />
11) Wozu dienen die Schlüsselwörter ROLLUP und CUBE?<br />
12) Wozu dienen die Funktionen AVG, SUM, COUNT, MAX und MIN?<br />
Übungen<br />
1) Geben Sie alle Vorstellungen aus, die von Mai bis Juli 2002 stattf<strong>in</strong><strong>de</strong>n!<br />
2) Geben Sie die Namen aller Kun<strong>de</strong>n aus, <strong><strong>de</strong>r</strong>en Nachname an <strong><strong>de</strong>r</strong> zweiten Stelle <strong>de</strong>n<br />
Buchstaben »u« enthält!<br />
3) Berechnen Sie die Anzahl aller auf Lager liegen<strong>de</strong>n Werbeartikel und geben Sie <strong><strong>de</strong>r</strong><br />
berechneten Spalte <strong>de</strong>n Spaltennamen »Anzahl auf Lager liegen<strong>de</strong> Werbeartikel« !<br />
4) Für welche Bestellung wur<strong>de</strong> <strong><strong>de</strong>r</strong> Mitarbeiter nicht e<strong>in</strong>getragen, <strong><strong>de</strong>r</strong> diese entgegengenommen<br />
hat?<br />
5) Welche Vorstellungen f<strong>in</strong><strong>de</strong>n <strong>in</strong> <strong><strong>de</strong>r</strong> Nordseehalle o<strong><strong>de</strong>r</strong> <strong>in</strong> <strong><strong>de</strong>r</strong> Kongresshalle statt?<br />
6) Wie viele verschie<strong>de</strong>ne Vorstellungen gibt es?<br />
7) Geben Sie die Anzahl <strong><strong>de</strong>r</strong> Vorstellungen aus, die pro Veranstaltung stattf<strong>in</strong><strong>de</strong>n!<br />
8) Welcher Kun<strong>de</strong> hat wie viele K<strong>in</strong><strong><strong>de</strong>r</strong> (absteigend sortiert nach <strong><strong>de</strong>r</strong> Anzahl <strong><strong>de</strong>r</strong><br />
K<strong>in</strong><strong><strong>de</strong>r</strong>)?<br />
9) Herr Kowalski hatte mehrere Fragen, die Frau Kart ihm aus <strong><strong>de</strong>r</strong> Datenbank beantworten<br />
sollte:<br />
Was kostet e<strong>in</strong> Werbartikel im Durchschnitt?<br />
Welcher Werbeartikel wur<strong>de</strong> am häufigsten verkauft?<br />
Welche Vorstellungen f<strong>in</strong><strong>de</strong>n im Mai statt?<br />
Wie viele Vorstellungen f<strong>in</strong><strong>de</strong>n im Jahr 2002 jeweils <strong>in</strong> <strong>de</strong>n e<strong>in</strong>zelnen Monaten statt?<br />
Welcher Kun<strong>de</strong> hat die höchste Anzahl an Artikeln gekauft?<br />
Welcher Artikel wur<strong>de</strong> am wenigsten bestellt?<br />
Helfen Sie Frau Kart!<br />
10) Wie viele Vorstellungen f<strong>in</strong><strong>de</strong>n im jeweiligen Jahr jeweils <strong>in</strong> <strong>de</strong>n e<strong>in</strong>zelnen Monaten<br />
und <strong>in</strong>sgesa<strong>mt</strong> statt?<br />
11) Wie viele K<strong>in</strong><strong><strong>de</strong>r</strong> <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n s<strong>in</strong>d Mädchen und wie viele K<strong>in</strong><strong><strong>de</strong>r</strong> s<strong>in</strong>d Jungen?<br />
12) Geben Sie die Kun<strong>de</strong>nnummer <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n aus, die K<strong>in</strong><strong><strong>de</strong>r</strong> haben, <strong><strong>de</strong>r</strong>en Vorname<br />
mit <strong>de</strong>m Buchstaben »K« beg<strong>in</strong>nt (Kun<strong>de</strong>nnummern sollen nur e<strong>in</strong>mal ausgegeben<br />
wer<strong>de</strong>n)!<br />
13) Wie lauten die Namen <strong><strong>de</strong>r</strong> K<strong>in</strong><strong><strong>de</strong>r</strong>, die im Mai o<strong><strong>de</strong>r</strong> Juni Geburtstag haben?<br />
14) Hat <strong><strong>de</strong>r</strong> Kun<strong>de</strong> mit <strong><strong>de</strong>r</strong> Kun<strong>de</strong>nnummer 1 sowohl e<strong>in</strong> Mädchen als auch e<strong>in</strong>en<br />
Jungen?<br />
15) Was kostet e<strong>in</strong> Sitzplatz im Parkett im Durchschnitt, im Maximum und im<br />
M<strong>in</strong>imum?
Aufgaben<br />
16) Geben Sie die Gesa<strong>mt</strong>menge an Artikeln an, die durch die Bestellung mit <strong><strong>de</strong>r</strong><br />
Nummer 1 bestellt wur<strong>de</strong>n?<br />
17) Geben Sie die Bestellnummern, sowie die Anzahl <strong><strong>de</strong>r</strong> Bestellposten pro Bestellung<br />
aus?<br />
18) Welche Vorstellung hat noch ke<strong>in</strong>e reservierten o<strong><strong>de</strong>r</strong> belegten Sitzplätze?<br />
19) Wie viele Sitzplätze s<strong>in</strong>d für die Vorstellung mit <strong><strong>de</strong>r</strong> Nummer 12 noch frei?<br />
20) Wie viele Sitzplätze s<strong>in</strong>d zur jeweiligen Vorstellung belegt, frei o<strong><strong>de</strong>r</strong> reserviert<br />
(sortiert nach <strong><strong>de</strong>r</strong> Vorstellungsnummer)?<br />
21) Wie viele Sitzplätze s<strong>in</strong>d zur jeweiligen Vorstellung belegt, frei o<strong><strong>de</strong>r</strong> reserviert und<br />
wie viele Sitzplätze gibt es <strong>in</strong>gesa<strong>mt</strong> zu je<strong><strong>de</strong>r</strong> Vorstellung?<br />
159
9 Abfragen<br />
auf mehrere<br />
Tabellen<br />
In Kapitel 9 sollen folgen<strong>de</strong> Fragen geklärt wer<strong>de</strong>n:<br />
� Wie verb<strong>in</strong><strong>de</strong>t man Tabellen wie<strong><strong>de</strong>r</strong>, die vorher durch Mo<strong>de</strong>llierung <strong>in</strong> mehrere<br />
Tabellen aufgespalten wur<strong>de</strong>n?<br />
� Wie kann man <strong>in</strong> e<strong>in</strong>er Abfrage auf Spalten mehrerer Tabellen zugreifen?<br />
� Welche Möglichkeiten gibt es, Tabellen wie<strong><strong>de</strong>r</strong> mite<strong>in</strong>an<strong><strong>de</strong>r</strong> zu verb<strong>in</strong><strong>de</strong>n?<br />
9.1 Motivation<br />
Frau Kart von <strong><strong>de</strong>r</strong> Firma »KartoF<strong>in</strong>ale« hat <strong>in</strong>zwischen die Abfragen, um die <strong><strong>de</strong>r</strong><br />
Geschäftsführer Herr Kowalski sie gebeten hatte, erstellt und die Ergebnisse ausgedruckt.<br />
Voller Stolz zeigt sie Herrn Kowalski die Ergebnisse, <strong><strong>de</strong>r</strong> sichtlich bee<strong>in</strong>druckt<br />
ist, welche Informationen und teilweise auch Analysen er über se<strong>in</strong>e Geschäftsdaten<br />
erhalten kann.<br />
Also beauftragt er Frau Kart gleich mit weiteren Fragen, die er beantwortet haben<br />
möchte:<br />
� Erstellen Sie mir e<strong>in</strong>e Liste aller Kun<strong>de</strong>nnamen und <strong><strong>de</strong>r</strong>en K<strong>in</strong><strong><strong>de</strong>r</strong>.<br />
� Erstellen Sie mir e<strong>in</strong>e Liste aller Kun<strong>de</strong>n und <strong><strong>de</strong>r</strong>en Bestellungen. Es sollen alle Kun<strong>de</strong>n<br />
aufgeführt wer<strong>de</strong>n, auch die, die bisher noch nichts bestellt haben.<br />
� Erstellen Sie mir e<strong>in</strong>e Liste aller Vorstellungen mit Bezeichnung und Adresse <strong><strong>de</strong>r</strong><br />
Spielstätte, Bezeichnung <strong><strong>de</strong>r</strong> Veranstaltung und Vorstellungsterm<strong>in</strong>.<br />
� Erstellen Sie e<strong>in</strong>e Liste aller Bestellungen und <strong><strong>de</strong>r</strong>en Bestellposten.<br />
Frau Kart, optimistisch durch <strong>de</strong>n ersten Abfrage-Erfolg, setzt sich sofort daran, die<br />
gewünschten Listen zu erstellen. Doch gleich bei <strong><strong>de</strong>r</strong> ersten Abfrage hat sie Probleme.<br />
Die Namen <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n und die Namen <strong><strong>de</strong>r</strong> K<strong>in</strong><strong><strong>de</strong>r</strong> bef<strong>in</strong><strong>de</strong>n sich <strong>in</strong> unterschiedlichen<br />
Tabellen. Wie kann sie nun aber e<strong>in</strong>e Abfrage erstellen, die sich auf bei<strong>de</strong> Tabellen<br />
bezieht?<br />
Also ruft sie Herrn Fleissig von <strong><strong>de</strong>r</strong> Unternehmensberatung an und schil<strong><strong>de</strong>r</strong>t ihr Problem.<br />
Herr Fleissig erklärt ihr, dass man Tabellen, die über <strong>de</strong>n Fremd- und Primärschlüssel<br />
mite<strong>in</strong>an<strong><strong>de</strong>r</strong> <strong>in</strong> Beziehung stehen wie<strong><strong>de</strong>r</strong> zu e<strong>in</strong>er Tabelle verb<strong>in</strong><strong>de</strong>n kann. Er<br />
erläutert ihr dies anhand <strong><strong>de</strong>r</strong> ersten Abfrage: »Der Primärschlüssel <strong>de</strong>s Kun<strong>de</strong>n bef<strong>in</strong><strong>de</strong>t<br />
sich als Fremdschlüssel <strong>in</strong> <strong><strong>de</strong>r</strong> K<strong>in</strong>d-Tabelle. Um diese bei<strong>de</strong>n Tabellen zu e<strong>in</strong>er<br />
Tabelle zu verb<strong>in</strong><strong>de</strong>n, erstellt man e<strong>in</strong>e Abfrage, die <strong>de</strong>n Primär- und Fremdschlüssel,<br />
also die Kun<strong>de</strong>nnummer, auf Gleichheit prüft«.<br />
161
162<br />
9 Abfragen auf mehrere Tabellen<br />
Nach<strong>de</strong>m Herr Fleissig mit ihr die entsprechen<strong>de</strong> SELECT-Anweisung zum Abfragen<br />
mehrerer Tabellen durchgegangen ist, kann Frau Kart schließlich die gewünschten Listen<br />
selbst erstellen.<br />
9.2 Grundlagen<br />
Wir haben <strong>in</strong> <strong>de</strong>n Kapiteln zur Datenmo<strong>de</strong>llierung gesehen, dass zur Vermeidung<br />
mehrfach gespeicherter Daten, das Relationenmo<strong>de</strong>ll die Daten <strong>in</strong> mehrere Tabellen<br />
aufspaltet. Die Beziehungen zwischen <strong>de</strong>n Tabellen wer<strong>de</strong>n dabei über Fremd- und Primärschlüssel<br />
abgebil<strong>de</strong>t.<br />
Um nun durch e<strong>in</strong>e Abfrage Informationen aus mehreren Tabellen zu erhalten, müssen<br />
die <strong>in</strong> Beziehung stehen<strong>de</strong>n Tabellen wie<strong><strong>de</strong>r</strong> mite<strong>in</strong>an<strong><strong>de</strong>r</strong> verbun<strong>de</strong>n wer<strong>de</strong>n. Das Verb<strong>in</strong><strong>de</strong>n<br />
(»Jo<strong>in</strong>« ) von Tabellen zu e<strong>in</strong>er großen Tabelle ist e<strong>in</strong>e wichtige Aufgabe e<strong>in</strong>es<br />
RDBMS, da <strong>in</strong> <strong><strong>de</strong>r</strong> Regel für die meisten Abfragen Informationen aus verschie<strong>de</strong>nen<br />
Tabellen benötigt wer<strong>de</strong>n. Das Verb<strong>in</strong><strong>de</strong>n von Tabellen ist dabei nicht nur beschränkt<br />
auf das Wie<strong><strong>de</strong>r</strong>zusammenführen von Tabellen über Primär- und Fremdschlüsselspalten,<br />
auch wenn dieses sicherlich die Hauptaufgabe von »Jo<strong>in</strong>s« darstellt. So s<strong>in</strong>d durchaus<br />
Abfragen s<strong>in</strong>nvoll, die sich nicht auf Fremd- und Primärschlüssel beziehen. Um<br />
herauszuf<strong>in</strong><strong>de</strong>n, welche Kun<strong>de</strong>n im gleichen Ort wohnen, <strong>in</strong> <strong><strong>de</strong>r</strong> auch e<strong>in</strong>e Spielstätte<br />
vorhan<strong>de</strong>n ist, wür<strong>de</strong> man die Postleitzahl <strong>de</strong>s Kun<strong>de</strong>n mit <strong><strong>de</strong>r</strong> Postleitzahl <strong><strong>de</strong>r</strong> Spielstätte<br />
vergleichen, auch wenn es sich hierbei um ke<strong>in</strong>e Fremd-/Primärschlüsselbeziehung<br />
han<strong>de</strong>lt.<br />
E<strong>in</strong>fach ausgedrückt verb<strong>in</strong><strong>de</strong>t man Tabellen also dadurch, dass Fremd- und Primärschlüssel<br />
auf Gleichheit bzw. Spalten auf Gleichheit überprüft wer<strong>de</strong>n, die <strong>de</strong>n gleichen<br />
Datentyp haben und sich natürlich semantisch entsprechen. So macht es natürlich ke<strong>in</strong>en<br />
S<strong>in</strong>n, zwei Spalten wie »Ortsname« und »Artikelbezeichnung« auf Gleichheit zu<br />
überprüfen, da es hier ke<strong>in</strong>e <strong>in</strong>haltlichen Übere<strong>in</strong>stimmungen gibt, auch wenn <strong><strong>de</strong>r</strong><br />
Datentyp i<strong>de</strong>ntisch se<strong>in</strong> mag.<br />
Dadurch, dass das Relationenmo<strong>de</strong>ll Verb<strong>in</strong>dungen von beliebigen Tabellen zulässt,<br />
s<strong>in</strong>d beliebige Abfragen <strong>de</strong>nkbar, an die beim Entwurf <strong><strong>de</strong>r</strong> Datenbankstruktur vielleicht<br />
noch gar nicht gedacht wur<strong>de</strong>. Diese Flexibilität ist e<strong>in</strong> wesentlicher Vorteil <strong>de</strong>s<br />
Relationenmo<strong>de</strong>lls.<br />
Doch kommen wir nun zu unserer SELECT-Anweisung, mit <strong><strong>de</strong>r</strong> wir Tabellen abfragen<br />
können. Wir wollen zunächst schrittweise betrachten, wie e<strong>in</strong> »Jo<strong>in</strong>« funktioniert. Nehmen<br />
wir dazu wie<strong><strong>de</strong>r</strong> unser Beispiel mit <strong>de</strong>n Tabellen Kun<strong>de</strong> und K<strong>in</strong>d. Zunächst müssen<br />
wir die Spalten angeben, die unsere SELECT-Anweisung ausgeben soll. Wir möchten<br />
<strong>de</strong>n Namen <strong>de</strong>s Kun<strong>de</strong>n und die Vornamen <strong><strong>de</strong>r</strong> K<strong>in</strong><strong><strong>de</strong>r</strong> ausgeben. Die<br />
Informationen zu diesen Spalten f<strong>in</strong><strong>de</strong>n wir <strong>in</strong> <strong>de</strong>n Tabellen Kun<strong>de</strong> und K<strong>in</strong>d. Der erste<br />
Teil <strong><strong>de</strong>r</strong> SELECT-Abfrage könnte mit unserem bisherigen Wissen folgen<strong><strong>de</strong>r</strong>maßen aussehen:<br />
SELECT Name, Vorname, Vorname -- mehr<strong>de</strong>utige Spaltennamen<br />
FROM Kun<strong>de</strong>, K<strong>in</strong>d
Grundlagen<br />
Doch hier haben wir schon unser erstes Problem: Die Spalte »Vorname« existiert<br />
sowohl <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »Kun<strong>de</strong>« als auch <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »K<strong>in</strong>d« , <strong><strong>de</strong>r</strong> Spaltenname »Vorname«<br />
ist also mehr<strong>de</strong>utig. Wie können wir dieses Problem nun lösen? E<strong>in</strong>e Möglichkeit<br />
wäre natürlich, <strong>de</strong>n Spaltennamen »Vorname« <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »K<strong>in</strong>d« über ALTER<br />
TABLE umzubenennen, so dass wir <strong>in</strong> allen Tabellen e<strong>in</strong><strong>de</strong>utige Spaltennamen hätten.<br />
Dies ist jedoch nicht beson<strong><strong>de</strong>r</strong>s praktikabel. SQL kennt <strong>de</strong>shalb so genannte qualifizierte<br />
Namen. E<strong>in</strong> Spaltenname ist, wie wir gera<strong>de</strong> gesehen haben, zwischen zwei o<strong><strong>de</strong>r</strong><br />
mehreren Tabellen nicht immer e<strong>in</strong><strong>de</strong>utig. Wird jedoch <strong><strong>de</strong>r</strong> Tabellenname <strong><strong>de</strong>r</strong> Spalte<br />
vorangestellt, so ist e<strong>in</strong><strong>de</strong>utig festgelegt, welche Spalte geme<strong>in</strong>t ist. Genau das ist mit<br />
qualifizierten Namen geme<strong>in</strong>t. Man stellt e<strong>in</strong>fach <strong>de</strong>n Tabellennamen vor <strong>de</strong>n Spaltennamen<br />
und trennt die bei<strong>de</strong>n Bezeichner durch e<strong>in</strong>en Punkt. Um also e<strong>in</strong><strong>de</strong>utig auf <strong>de</strong>n<br />
Vornamen <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle K<strong>in</strong>d zu verweisen, lautet <strong><strong>de</strong>r</strong> qualifizierte Bezeichner<br />
K<strong>in</strong>d.Vorname<br />
Um dagegen e<strong>in</strong><strong>de</strong>utig auf <strong>de</strong>n Vornamen <strong>de</strong>s Kun<strong>de</strong>n zu verweisen, lautet <strong><strong>de</strong>r</strong> qualifizierte<br />
Bezeichner:<br />
Kun<strong>de</strong>.Vorname<br />
In Kapitel 6, Abschnitt 2, haben wir gesehen, dass e<strong>in</strong> RDBMS e<strong>in</strong>e Datenbank weiter<br />
strukturiert, als <strong>in</strong> Tabellen und Spalten. Den Tabellen übergeordnet ist das Schema<br />
und über <strong>de</strong>m Schema steht die Kategorie. E<strong>in</strong>e Tabelle kann also <strong>in</strong>nerhalb von zwei<br />
Schemata auch <strong>de</strong>n gleichen Namen bekommen. Allgeme<strong>in</strong> sieht die Vergabe qualifizierter<br />
Bezeichner <strong>de</strong>shalb folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
Kategorie.Schema.Tabelle.Attribut<br />
In diesem Buch wird jedoch ausschließlich mit e<strong>in</strong>em e<strong>in</strong>zigen Schema gearbeitet,<br />
daher reicht die Qualifizierung <strong>de</strong>s Spaltennamens über Tabelle und Spalte.<br />
Doch kommen wir zu unserem Ausgangspunkt zurück. Die gewünschte Abfrage mit<br />
qualifizierten Spaltennamen sieht jetzt folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
SELECT Kun<strong>de</strong>.Name, Kun<strong>de</strong>.Vorname, K<strong>in</strong>d.Vorname<br />
FROM Kun<strong>de</strong>, K<strong>in</strong>d<br />
Wie sieht nun das Ergebnis dieser Abfrage aus? Schließlich haben wir noch ke<strong>in</strong>en Vergleich<br />
von Primär- und Fremdschlüssel (Kun<strong>de</strong>nnummer) angegeben. Die Mengenlehre,<br />
auf <strong><strong>de</strong>r</strong> das Relationenmo<strong>de</strong>ll basiert, arbeitet mit <strong>de</strong>m kartesischen Produkt,<br />
d.h. je<strong>de</strong>s Element <strong><strong>de</strong>r</strong> e<strong>in</strong>en Tabelle wird mit je<strong>de</strong>m Element <strong><strong>de</strong>r</strong> an<strong><strong>de</strong>r</strong>en Tabelle komb<strong>in</strong>iert.<br />
Das kartesische Produkt selbst liefert vorwiegend uns<strong>in</strong>nige Daten, da je<strong><strong>de</strong>r</strong><br />
Kun<strong>de</strong> mit je<strong>de</strong>m K<strong>in</strong>d komb<strong>in</strong>iert wird. Danach wäre sozusagen, je<strong><strong>de</strong>r</strong> Kun<strong>de</strong> Elternteil<br />
je<strong>de</strong>s K<strong>in</strong><strong>de</strong>s. Das Ergebnis <strong><strong>de</strong>r</strong> Abfrage wür<strong>de</strong> also folgen<strong><strong>de</strong>r</strong>maßen aussehen:<br />
163
Kun<strong>de</strong>.Name Kun<strong>de</strong>.Vorname K<strong>in</strong>d.Vorname<br />
---------- ------------- ------------<br />
Bolte Bertram Karl<br />
Bolte Bertram Katja<br />
Bolte Bertram Ursula<br />
Bolte Bertram Enzo<br />
Bolte Bertram Ursula<br />
Muster Hans Karl<br />
Muster Hans Katja<br />
Muster Hans Ursula<br />
Muster Hans Enzo<br />
Muster Hans Ursula<br />
Wiegerich Frieda Karl<br />
Wiegerich Frieda Katja<br />
Wiegerich Frieda Ursula<br />
Wiegerich Frieda Enzo<br />
Wiegerich Frieda Ursula<br />
Carlson Peter Karl<br />
Carlson Peter Katja<br />
Carlson Peter Ursula<br />
Carlson Peter Enzo<br />
Carlson Peter Ursula<br />
164<br />
9 Abfragen auf mehrere Tabellen<br />
Um nun je<strong>de</strong>m Kun<strong>de</strong>n die dazugehörigen K<strong>in</strong><strong><strong>de</strong>r</strong> zuzuordnen, muss das kartesische<br />
Produkt e<strong>in</strong>geschränkt wer<strong>de</strong>n, <strong>in</strong><strong>de</strong>m nur die Sätze ausgegeben wer<strong>de</strong>n, bei <strong>de</strong>nen die<br />
Kun<strong>de</strong>nnummer <strong>in</strong> bei<strong>de</strong>n Tabellen i<strong>de</strong>ntisch ist. Betrachten wir hierzu die Abbildung 9.1<br />
auf <strong><strong>de</strong>r</strong> nächsten Seite. Zunächst wird das kartesische Produkt <strong><strong>de</strong>r</strong> Tabellen Kun<strong>de</strong> und<br />
K<strong>in</strong>d gebil<strong>de</strong>t. Danach wird überprüft, wo die Kun<strong>de</strong>nnummer <strong><strong>de</strong>r</strong> Tabelle Kun<strong>de</strong> <strong><strong>de</strong>r</strong><br />
Kun<strong>de</strong>nnummer <strong><strong>de</strong>r</strong> Tabelle K<strong>in</strong>d entspricht. Denn das s<strong>in</strong>d ja genau die K<strong>in</strong><strong><strong>de</strong>r</strong>, die zu<br />
diesem Kun<strong>de</strong>n gehören. Als Ergebnis erhält man alle Kun<strong>de</strong>nnamen und <strong><strong>de</strong>r</strong>en zugehörige<br />
K<strong>in</strong><strong><strong>de</strong>r</strong>, <strong>in</strong><strong>de</strong>m man alle Datensätze über e<strong>in</strong>e WHERE-Klausel herausfiltert, bei<br />
<strong>de</strong>nen die Kun<strong>de</strong>nnummer nicht übere<strong>in</strong>stim<strong>mt</strong>. Die endgültige SELECT-Anweisung<br />
sieht also wie folgt aus:<br />
SELECT Kun<strong>de</strong>.Name, Kun<strong>de</strong>.Vorname, K<strong>in</strong>d.Vorname<br />
FROM Kun<strong>de</strong>, K<strong>in</strong>d<br />
WHERE Kun<strong>de</strong>.Kun<strong>de</strong>nnummer = K<strong>in</strong>d.Kun<strong>de</strong>nnummer<br />
Kun<strong>de</strong>.Name Kun<strong>de</strong>.Vorname K<strong>in</strong>d.Vorname<br />
---------- ------------- ------------<br />
Bolte Bertram Karl<br />
Bolte Bertram Katja<br />
Bolte Bertram Ursula<br />
Wiegerich Frieda Enzo<br />
Wiegerich Frieda Ursula
Name<br />
Bolte<br />
Muster<br />
Wiegerich<br />
Carlson<br />
Vorname<br />
Bertram<br />
Hans<br />
Frieda<br />
Peter<br />
Kartesisches Produkt<br />
Grundlagen<br />
Kun<strong>de</strong> K<strong>in</strong>d<br />
Kun<strong>de</strong>.Name Kun<strong>de</strong>.Vorname<br />
Bolte Bertram<br />
Bolte Bertram<br />
Bolte Bertram<br />
Bolte Bertram<br />
Bolte Bertram<br />
Muster<br />
...<br />
Hans<br />
Wiegerich<br />
...<br />
Frieda<br />
Carlson Peter<br />
Carlson Peter<br />
Kun<strong>de</strong>nnummer<br />
1<br />
2<br />
3<br />
4<br />
Kun<strong>de</strong>nnummer<br />
1<br />
1<br />
1<br />
1<br />
1<br />
2<br />
Abbildung 9.1: »Jo<strong>in</strong>« von »Kun<strong>de</strong>« und »K<strong>in</strong>d«<br />
Der Kun<strong>de</strong> Bertram Bolte hat also drei K<strong>in</strong><strong><strong>de</strong>r</strong> und die Kund<strong>in</strong> Frieda Wiegerich zwei.<br />
Auch <strong>in</strong> <strong><strong>de</strong>r</strong> WHERE-Klausel wer<strong>de</strong>n qualifizierte Namen verwen<strong>de</strong>t, da die Spalte<br />
Kun<strong>de</strong>nnummer <strong>in</strong> bei<strong>de</strong>n Tabellen vorkom<strong>mt</strong>.<br />
Wir haben soeben <strong>de</strong>n häufigsten Typ von »Jo<strong>in</strong>s« kennen gelernt, <strong>de</strong>n »Natural Jo<strong>in</strong>« .<br />
SQL:1999 kennt <strong>in</strong>sgesa<strong>mt</strong> vier Typen von »Jo<strong>in</strong>s« :<br />
� CROSS JOIN<br />
� INNER JOIN<br />
� NATURAL JOIN<br />
� OUTER JOIN<br />
Wir wollen uns im Folgen<strong>de</strong>n die e<strong>in</strong>zelnen »Jo<strong>in</strong>« -Typen ansehen.<br />
3<br />
4<br />
4<br />
Kun<strong>de</strong>nnummer<br />
1<br />
1<br />
1<br />
3<br />
3<br />
Kun<strong>de</strong>n-<br />
K<strong>in</strong>d.Vorname<br />
nummer<br />
1<br />
Katja<br />
1<br />
Ursula<br />
1<br />
Karl<br />
3<br />
Ursula<br />
3<br />
Enzo<br />
1 Katja<br />
3<br />
3<br />
3<br />
Vorname<br />
Katja<br />
Ursula<br />
Karl<br />
Ursula<br />
Enzo<br />
Enzo<br />
Ursula<br />
Enzo<br />
Vergleich: ������������������ � �����������������<br />
Kun<strong>de</strong>.Name Kun<strong>de</strong>.Vorname<br />
Bolte Bertram<br />
Bolte Bertram<br />
Bolte<br />
...<br />
Bertram<br />
Wiegerich Frieda<br />
Kun<strong>de</strong>nnummer<br />
1<br />
1<br />
1<br />
Kun<strong>de</strong>nnummer<br />
1<br />
1<br />
1<br />
K<strong>in</strong>d.Vorname<br />
Katja<br />
Ursula<br />
Karl<br />
3 3 Enzo<br />
165
9.3 CROSS JOIN<br />
166<br />
9 Abfragen auf mehrere Tabellen<br />
Der CROSS JOIN entspricht <strong>de</strong>m kartesischen Produkt. Wir haben ihn bereits kennen<br />
gelernt, als wir die Tabellen Kun<strong>de</strong> und K<strong>in</strong>d h<strong>in</strong>ter <strong><strong>de</strong>r</strong> FROM-Klausel aufgeführt<br />
haben ohne die WHERE-Klausel zu verwen<strong>de</strong>n. Wie bereits erwähnt, liefert er <strong>in</strong> <strong><strong>de</strong>r</strong><br />
Regel uns<strong>in</strong>nige Daten, weshalb er <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>Praxis</strong> kaum Verwendung f<strong>in</strong><strong>de</strong>t. Die klassisch<br />
komma-getrennte Version <strong>de</strong>s CROSS JOIN wur<strong>de</strong> oben bereits verwen<strong>de</strong>t. Seit<br />
SQL-1992 gibt es jedoch auch die bei<strong>de</strong>n Schlüsselwörter CROSS JOIN, mit <strong>de</strong>nen für<br />
zwei Tabellen das kartesische Produkt gebil<strong>de</strong>t wer<strong>de</strong>n kann. Die dazugehörige<br />
SELECT-Anweisung für unsere bei<strong>de</strong>n Tabellen sieht dabei folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
SELECT Kun<strong>de</strong>.Name, Kun<strong>de</strong>.Vorname, K<strong>in</strong>d.Vorname<br />
FROM Kun<strong>de</strong> CROSS JOIN K<strong>in</strong>d<br />
Die Anweisung entspricht <strong><strong>de</strong>r</strong> SELECT-Anweisung aus Abschnitt 9.2 ohne WHERE-<br />
Klausel. Um jedoch besser erkennen zu können, ob es sich bei e<strong>in</strong>em Vergleich um<br />
e<strong>in</strong>en »Jo<strong>in</strong>« o<strong><strong>de</strong>r</strong> e<strong>in</strong> Auswählen von Sätzen han<strong>de</strong>lt, hat man 1992 diese Schlüsselwörter<br />
im Standard e<strong>in</strong>geführt.<br />
9.4 INNER JOIN<br />
E<strong>in</strong> INNER JOIN berücksichtigt niemals NULL, er verb<strong>in</strong><strong>de</strong>t also nur Spalten, die<br />
Werte enthalten. E<strong>in</strong> typisches Beispiel e<strong>in</strong>es INNER JOINS ist unsere Kun<strong>de</strong>-K<strong>in</strong>d-<br />
Beziehung. Es wer<strong>de</strong>n alle Kun<strong>de</strong>n aufgeführt und <strong><strong>de</strong>r</strong>en K<strong>in</strong><strong><strong>de</strong>r</strong>. Dabei wer<strong>de</strong>n die<br />
k<strong>in</strong><strong><strong>de</strong>r</strong>losen Kun<strong>de</strong>n weggelassen. In Abschnitt 9.2 haben wir die klassische kommagetrennte<br />
Version <strong>de</strong>s INNER JOIN kennen gelernt. Seit SQL-1992 gibt es wie beim<br />
CROSS JOIN auch zwei neue Schlüsselwörter, nämlich INNER JOIN. Um die obige<br />
Abfrage mit <strong>de</strong>n Schlüsselwörtern INNER JOIN darzustellen, schreibt man:<br />
SELECT Kun<strong>de</strong>.Name, Kun<strong>de</strong>.Vorname, K<strong>in</strong>d.Vorname<br />
FROM Kun<strong>de</strong> INNER JOIN K<strong>in</strong>d<br />
ON Kun<strong>de</strong>.Kun<strong>de</strong>nnummer = K<strong>in</strong>d.Kun<strong>de</strong>nnummer<br />
Als Ergebnis erhält man die bei<strong>de</strong>n Kun<strong>de</strong>n, Bertram Bolte und Frieda Wiegerich, die<br />
K<strong>in</strong><strong><strong>de</strong>r</strong> haben. Wenn man zwei Spalten auf Gleichheit überprüft, erlaubt SQL e<strong>in</strong>e e<strong>in</strong>fachere<br />
Syntax über das Schlüsselwort USING. Folgen<strong>de</strong> SQL-Anweisung liefert das<br />
gleiche Ergebnis:<br />
SELECT Kun<strong>de</strong>.Name, Kun<strong>de</strong>.Vorname, K<strong>in</strong>d.Vorname<br />
FROM Kun<strong>de</strong> INNER JOIN K<strong>in</strong>d<br />
USING (Kun<strong>de</strong>nnummer, Kun<strong>de</strong>nnummer)<br />
Ist <strong><strong>de</strong>r</strong> Name <strong><strong>de</strong>r</strong> Spalte <strong>in</strong> bei<strong>de</strong>n Tabellen i<strong>de</strong>ntisch, so braucht die Spalte nur e<strong>in</strong>mal<br />
aufgeführt zu wer<strong>de</strong>n. Um also alle Kun<strong>de</strong>n, die K<strong>in</strong><strong><strong>de</strong>r</strong> haben, mit <strong>de</strong>n Namen ihrer<br />
K<strong>in</strong><strong><strong>de</strong>r</strong> auszugeben, gibt es verschie<strong>de</strong>ne Möglichkeiten. Folgen<strong>de</strong> SELECT-Anweisungen<br />
s<strong>in</strong>d i<strong>de</strong>ntisch und liefern das gleiche Ergebnis:
INNER JOIN<br />
-- klassisch komma-getrennter Jo<strong>in</strong><br />
SELECT Kun<strong>de</strong>.Name, Kun<strong>de</strong>.Vorname, K<strong>in</strong>d.Vorname<br />
FROM Kun<strong>de</strong>, K<strong>in</strong>d<br />
WHERE Kun<strong>de</strong>.Kun<strong>de</strong>nnummer = K<strong>in</strong>d.Kun<strong>de</strong>nnummer<br />
-- Bed<strong>in</strong>gungs-Jo<strong>in</strong><br />
SELECT Kun<strong>de</strong>.Name, Kun<strong>de</strong>.Vorname, K<strong>in</strong>d.Vorname<br />
FROM Kun<strong>de</strong> INNER JOIN K<strong>in</strong>d<br />
ON Kun<strong>de</strong>.Kun<strong>de</strong>nnummer = K<strong>in</strong>d.Kun<strong>de</strong>nnummer<br />
-- Spaltennamen-Jo<strong>in</strong><br />
SELECT Kun<strong>de</strong>.Name, Kun<strong>de</strong>.Vorname, K<strong>in</strong>d.Vorname<br />
FROM Kun<strong>de</strong> INNER JOIN K<strong>in</strong>d<br />
USING (Kun<strong>de</strong>nnummer)<br />
Wie wer<strong>de</strong>n »Jo<strong>in</strong>s« durchgeführt, die sich auf die gleiche Tabelle beziehen? Wenn wir<br />
uns noch e<strong>in</strong>mal an die Tabelle Mitarbeiter zurücker<strong>in</strong>nern, so wissen wir, dass hier<br />
e<strong>in</strong>e rekursive Beziehung zwischen Mitarbeiter und Vorgesetztem abgebil<strong>de</strong>t wur<strong>de</strong>.<br />
Wir haben hier also <strong>de</strong>n Son<strong><strong>de</strong>r</strong>fall, dass <strong><strong>de</strong>r</strong> Fremdschlüssel »PersonalnummerVorgesetzter«<br />
auf die gleiche Tabelle verweist, nämlich <strong>de</strong>n Primärschlüssel »Personalnummer«<br />
. Verknüpfungen e<strong>in</strong>er Tabelle mit sich selbst bezeichnet man als »Self Jo<strong>in</strong>« .<br />
Betrachten wir folgen<strong>de</strong>s Beispiel: Es sollen die Namen aller Mitarbeiter, sowie die<br />
Namen <strong><strong>de</strong>r</strong> dazugehörigen Vorgesetzten ausgegeben wer<strong>de</strong>n. Hier tritt das gleiche<br />
Problem wie mit mehr<strong>de</strong>utigen Spaltennamen auf: Soll e<strong>in</strong>e Tabelle mit sich selbst verknüpft<br />
wer<strong>de</strong>n, so muss sie zweimal <strong>in</strong> <strong><strong>de</strong>r</strong> FROM-Klausel aufgeführt wer<strong>de</strong>n. SQL<br />
bietet die Möglichkeit, <strong>de</strong>n Namen von Tabellen über das Schlüsselwort AS umzubenennen.<br />
Das Ganze funktioniert also genauso wie das Umbenennen von Spalten.<br />
Damit sieht die Abfrage folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
SELECT Mitarbeiter.Name, Vorgesetzter.Name<br />
FROM Mitarbeiter, Mitarbeiter AS Vorgesetzter<br />
WHERE Mitarbeiter.PersonalnummerVorgesetzter =<br />
Vorgesetzter.Personalnummer<br />
Mitarbeiter.Name Vorgesetzter.Name<br />
---------------- -----------------<br />
Kart Kowalski<br />
Kle<strong>in</strong> Kart<br />
Gibt man <strong>in</strong> <strong><strong>de</strong>r</strong> FROM-Klausel zweimal die gleiche Tabelle an, so betrachtet SQL die<br />
bei<strong>de</strong>n Tabellen als zwei unterschiedliche Tabellen, die z.B. mite<strong>in</strong>an<strong><strong>de</strong>r</strong> verbun<strong>de</strong>n<br />
wer<strong>de</strong>n können.<br />
167
168<br />
Mitarbeiter<br />
Personalnummer<br />
3<br />
5<br />
6<br />
Name<br />
Kart<br />
Kle<strong>in</strong><br />
Kowalski<br />
Personalnummer<br />
Name Vorname<br />
3 Kart Karen<br />
3 Kart Karen<br />
3 Kart Karen<br />
5<br />
...<br />
Kle<strong>in</strong> Karl<br />
6 Kowalski Karsten<br />
6 Kowalski Karsten<br />
9 Abfragen auf mehrere Tabellen<br />
Entsprechend könnte man z.B. auch herausf<strong>in</strong><strong>de</strong>n, welche Mitarbeiter die gleiche Postleitzahl<br />
haben. In diesem Fall wür<strong>de</strong> man e<strong>in</strong>e Verknüpfung nicht über Fremd- und Primärschlüssel<br />
vornehmen, son<strong><strong>de</strong>r</strong>n über semantisch vergleichbare Spalten:<br />
SELECT M1.Name, M2.Name<br />
FROM Mitarbeiter AS M1 INNER JOIN Mitarbeiter AS M2<br />
ON M1.Plz = M2.Plz<br />
M1.Name M2.Name<br />
-------- -------<br />
Kart Kart<br />
Kle<strong>in</strong> Kart<br />
Kart Kle<strong>in</strong><br />
Kle<strong>in</strong> Kle<strong>in</strong><br />
Kowalski Kowalski<br />
Vorname<br />
Karen<br />
Karl<br />
Karsten<br />
Kartesisches Produkt<br />
Personalnummervorgesetzter<br />
6<br />
3<br />
NULL<br />
Personalnummervorgesetzter<br />
6<br />
6<br />
6<br />
3<br />
NULL<br />
NULL<br />
Mitarbeiter AS Vorgesetzter<br />
Personalnummer<br />
3<br />
5<br />
6<br />
Abbildung 9.2: »Self Jo<strong>in</strong>« <strong><strong>de</strong>r</strong> Tabelle »Mitarbeiter«<br />
Personalnummervorgesetzter<br />
6<br />
3<br />
NULL<br />
Doch unser Ergebnis ist noch nicht beson<strong><strong>de</strong>r</strong>s befriedigend. Zwar wer<strong>de</strong>n Frau Kart<br />
und Herr Kle<strong>in</strong> aufgeführt, die bei<strong>de</strong> im Ort mit <strong><strong>de</strong>r</strong> Postleitzahl 22222 wohnen. Es<br />
wer<strong>de</strong>n allerd<strong>in</strong>gs sowohl e<strong>in</strong>zelne Personen, als auch Personenkomb<strong>in</strong>ationen, nur <strong>in</strong><br />
umgekehrter Reihenfolge, doppelt ausgegeben. Betrachten wir noch e<strong>in</strong>mal die Vorgehensweise<br />
e<strong>in</strong>es RDBMS bei <strong><strong>de</strong>r</strong> Auswertung e<strong>in</strong>er Abfrage. Zunächst wird das kartesisches<br />
Produkt gebil<strong>de</strong>t. In diesem Fall wird je<strong><strong>de</strong>r</strong> Satz <strong><strong>de</strong>r</strong> Tabelle Mitarbeiter (M1) mit<br />
Name<br />
Kart<br />
Kle<strong>in</strong><br />
Kowalski<br />
Vorname<br />
Karen<br />
Karl<br />
Karsten<br />
Personalnummer<br />
Name Vorname<br />
3 Kart Karen<br />
5 Kle<strong>in</strong> Karl<br />
6 Kowalski Karsten<br />
3 Kart Karen<br />
5<br />
6<br />
Vergleich:<br />
Kle<strong>in</strong><br />
Kowalski<br />
Karl<br />
Karsten<br />
Personalnummervorgesetzter<br />
6<br />
3<br />
NULL<br />
6<br />
3<br />
NULL<br />
�������������������������������������� � ���������������������������<br />
Personalnummer<br />
Name Vorname<br />
3 Kart Karen<br />
5 Kle<strong>in</strong> Karl<br />
Personalnummervorgesetzter<br />
6<br />
3<br />
Personalnummer<br />
Name Vorname<br />
6 Kowalski Karsten<br />
3 Kart Karen<br />
Personalnummervorgesetzter<br />
NULL<br />
6
NATURAL JOIN<br />
je<strong>de</strong>m Satz <strong><strong>de</strong>r</strong> Tabelle Mitarbeiter (M2) komb<strong>in</strong>iert. Da z.B. Herr Kowalski natürlich <strong>in</strong><br />
bei<strong>de</strong>n Tabellen vorhan<strong>de</strong>n ist, gibt es auch e<strong>in</strong>e Komb<strong>in</strong>ation, <strong>in</strong> <strong><strong>de</strong>r</strong> er zweimal auftritt.<br />
Um gleiche Sätze aus M1 und M2 auszufiltern, fügen wir e<strong>in</strong>e Bed<strong>in</strong>gung h<strong>in</strong>zu,<br />
die überprüft, ob <strong><strong>de</strong>r</strong> Primärschlüssel zwischen M1 und M2 unterschiedlich ist. Doch<br />
wir haben noch e<strong>in</strong>e Unstimmigkeit, die Komb<strong>in</strong>ation Kle<strong>in</strong> und Kart wird zweimal<br />
aufgeführt. Um doppelte Komb<strong>in</strong>ationen auszufiltern, vergleicht man e<strong>in</strong>fach, ob <strong><strong>de</strong>r</strong><br />
Primärschlüssel von M1 größer als <strong><strong>de</strong>r</strong> Primärschlüssel von M2 ist. Die SELECT-<br />
Anweisung sieht also folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
SELECT M1.Name, M2.Name<br />
FROM Mitarbeiter AS M1 INNER JOIN Mitarbeiter AS M2<br />
ON M1.Plz = M2.Plz<br />
WHERE M1.Personalnummer M2.Personalnummer<br />
AND M1.Personalnummer > M2.Personalnummer<br />
M1.Name M2.Name<br />
------- -------<br />
Kle<strong>in</strong> Kart<br />
Damit können wir auch die erste Bed<strong>in</strong>gung auf Ungleichheit <strong><strong>de</strong>r</strong> Personalnummern<br />
weglassen, da die zweite Bed<strong>in</strong>gung diese E<strong>in</strong>schränkung schon mitberücksichtigt.<br />
9.5 NATURAL JOIN<br />
Der NATURAL JOIN ist e<strong>in</strong> Spezialfall <strong>de</strong>s INNER JOIN. E<strong>in</strong> INNER JOIN muss nicht<br />
unbed<strong>in</strong>gt zwei Spalten auf Gleichheit prüfen, als Bed<strong>in</strong>gung s<strong>in</strong>d hier alle Vergleichsoperatoren,<br />
also >,
170<br />
9 Abfragen auf mehrere Tabellen<br />
Die Namen <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n, die ke<strong>in</strong>e K<strong>in</strong><strong><strong>de</strong>r</strong> haben, wer<strong>de</strong>n nicht aufgeführt. Dies ist<br />
jedoch s<strong>in</strong>nvoll, wenn man z.B. e<strong>in</strong>e komplette Kun<strong>de</strong>nliste erstellen möchte, <strong>in</strong> <strong><strong>de</strong>r</strong><br />
u.a. auch die Namen <strong><strong>de</strong>r</strong> K<strong>in</strong><strong><strong>de</strong>r</strong> aufgeführt s<strong>in</strong>d. Seit SQL-1992 gibt es <strong>de</strong>shalb als<br />
Gegenstück zu INNER JOIN die bei<strong>de</strong>n Schlüsselwörter OUTER JOIN.<br />
E<strong>in</strong> OUTER JOIN gibt es <strong>in</strong> drei verschie<strong>de</strong>nen Varianten, je nach<strong>de</strong>m von welcher<br />
Tabelle aus man die NULL-Werte betrachtet:<br />
� LEFT OUTER JOIN<br />
� RIGHT OUTER JOIN<br />
� FULL OUTER JOIN<br />
Sehen wir uns dazu die SELECT-Anweisung zur Ausgabe <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n mit <strong>de</strong>n dazugehörigen<br />
K<strong>in</strong><strong><strong>de</strong>r</strong>n an:<br />
SELECT Kun<strong>de</strong>.Name, Kun<strong>de</strong>.Vorname, K<strong>in</strong>d.Vorname<br />
FROM Kun<strong>de</strong> LEFT OUTER JOIN K<strong>in</strong>d<br />
ON Kun<strong>de</strong>.Kun<strong>de</strong>nnummer = K<strong>in</strong>d.Kun<strong>de</strong>nnummer<br />
Kun<strong>de</strong>.Name Kun<strong>de</strong>.Vorname K<strong>in</strong>d.Vorname<br />
---------- ------------- ------------<br />
Bolte Bertram Karl<br />
Bolte Bertram Katja<br />
Bolte Bertram Ursula<br />
Muster Hans NULL<br />
Wiegerich Frieda Enzo<br />
Wiegerich Frieda Ursula<br />
Carlson Peter NULL<br />
Es wer<strong>de</strong>n die Namen aller Kun<strong>de</strong>n ausgegeben, auch die <strong><strong>de</strong>r</strong> k<strong>in</strong><strong><strong>de</strong>r</strong>losen Kun<strong>de</strong>n,<br />
also Hans Muster und Peter Carlson. Die Spalten <strong><strong>de</strong>r</strong> Tabelle, <strong>in</strong> <strong><strong>de</strong>r</strong> ihr Primärschlüssel<br />
nicht als Fremdschlüssel vorhan<strong>de</strong>n ist, wer<strong>de</strong>n als NULL dargestellt.<br />
Über LEFT und RIGHT kann festgelegt wer<strong>de</strong>n, ob die Spalten <strong><strong>de</strong>r</strong> l<strong>in</strong>ken o<strong><strong>de</strong>r</strong> <strong><strong>de</strong>r</strong><br />
rechten Tabelle ausgegeben wer<strong>de</strong>n sollen, wenn ke<strong>in</strong>e Beziehung zu <strong><strong>de</strong>r</strong> entsprechen<strong>de</strong>n<br />
Tabelle besteht. Da e<strong>in</strong> K<strong>in</strong>d immer e<strong>in</strong>em Kun<strong>de</strong>n zugeordnet ist, diese Beziehung<br />
aus <strong><strong>de</strong>r</strong> Sicht <strong>de</strong>s K<strong>in</strong><strong>de</strong>s also niemals optional ist, wür<strong>de</strong> RIGHT OUTER JOIN <strong>in</strong> diesem<br />
Fall e<strong>in</strong>em NATURAL JOIN entsprechen.<br />
Betrachten wir hierzu e<strong>in</strong> weiteres Beispiel. Wir wollen e<strong>in</strong>e Liste aller Mitarbeiter und<br />
<strong><strong>de</strong>r</strong>en Abteilung ausgeben. Es sollen auch Mitarbeiter ohne zugehörige Abteilung ausgegeben<br />
wer<strong>de</strong>n. Über e<strong>in</strong>en LEFT OUTER JOIN wür<strong>de</strong> das dann folgen<strong><strong>de</strong>r</strong>maßen aussehen:<br />
SELECT Name, Vorname, Abteilung.Abteilungsbezeichnung<br />
FROM Mitarbeiter LEFT OUTER JOIN Abteilung<br />
ON Mitarbeiter.Abteilungsbezeichnung =<br />
Abteilung.Abteilungsbezeichnung
OUTER JOIN<br />
Name Vorname Abteilung.Abteilungsbezeichnung<br />
-------- ------- -------------------------------<br />
Kart Karen Vertrieb<br />
Kle<strong>in</strong> Karl Vertrieb<br />
Kowalski Karsten NULL<br />
Wir sehen, dass <strong><strong>de</strong>r</strong> Geschäftsführer Herr Kowalski ke<strong>in</strong>er Abteilung zugeordnet ist.<br />
Wollen wir nun umgekehrt wissen, welche Abteilungen es gibt und welche Mitarbeiter<br />
zu diesen Abteilungen gehören, so verwen<strong>de</strong>n wir anstelle <strong>de</strong>s LEFT e<strong>in</strong> RIGHT.<br />
Dadurch wer<strong>de</strong>n auch Abteilungen ausgegeben, <strong>de</strong>nen ke<strong>in</strong> Mitarbeiter zugeordnet<br />
ist.<br />
SELECT Name, Vorname, Abteilung.Abteilungsbezeichnung<br />
FROM Mitarbeiter RIGHT OUTER JOIN Abteilung<br />
ON Mitarbeiter.Abteilungsbezeichnung =<br />
Abteilung.Abteilungsbezeichnung<br />
Name Vorname Abteilung.Abteilungsbezeichnung<br />
-------- ------- -------------------------------<br />
NULL NULL Geschäftsführung<br />
NULL NULL Rechnungswesen<br />
Kart Karen Vertrieb<br />
Kle<strong>in</strong> Karl Vertrieb<br />
Da Frau Kart und Herr Kle<strong>in</strong> zu e<strong>in</strong>er Abteilung gehören, s<strong>in</strong>d sie wie<strong><strong>de</strong>r</strong> <strong>in</strong> <strong><strong>de</strong>r</strong> Ergebnistabelle<br />
zu f<strong>in</strong><strong>de</strong>n. Herr Kowalski ist nicht aufgeführt, da er ke<strong>in</strong>er Abteilung zugeordnet<br />
ist. Dafür s<strong>in</strong>d aber alle Abteilungen, die es gibt, <strong>in</strong> <strong><strong>de</strong>r</strong> Ergebnistabelle zu<br />
sehen, auch wenn ke<strong>in</strong> Mitarbeiter zugeordnet ist.<br />
Möchte man nun e<strong>in</strong>e Liste, <strong>in</strong> <strong><strong>de</strong>r</strong> alle Mitarbeiter und auch alle Abteilungen aufgeführt<br />
s<strong>in</strong>d, unabhängig davon ob e<strong>in</strong> Mitarbeiter zu e<strong>in</strong>er Abteilung gehört o<strong><strong>de</strong>r</strong> ob<br />
e<strong>in</strong>e Abteilung Mitarbeiter hat, so verwen<strong>de</strong>t man schließlich e<strong>in</strong>en FULL OUTER<br />
JOIN:<br />
SELECT Name, Vorname, Abteilung.Abteilungsbezeichnung<br />
FROM Mitarbeiter FULL OUTER JOIN Abteilung<br />
ON Mitarbeiter.Abteilungsbezeichnung =<br />
Abteilung.Abteilungsbezeichnung<br />
Name Vorname Abteilung.Abteilungsbezeichnung<br />
-------- ------- -------------------------------<br />
Kowalski Karsten NULL<br />
NULL NULL Geschäftsführung<br />
NULL NULL Rechnungswesen<br />
Kart Karen Vertrieb<br />
Kle<strong>in</strong> Karl Vertrieb<br />
Jetzt enthält die Ergebnistabelle die Namen aller Mitarbeiter und aller Abteilungen.<br />
171
172<br />
9 Abfragen auf mehrere Tabellen<br />
Wie bei e<strong>in</strong>em INNER JOIN auch, kann anstelle <strong><strong>de</strong>r</strong> ON-Bed<strong>in</strong>gung das Schlüsselwort<br />
USING verwen<strong>de</strong>t wer<strong>de</strong>n, sofern man auf Gleichheit überprüft. Folgen<strong>de</strong> SELECT-<br />
Anweisungen s<strong>in</strong>d also i<strong>de</strong>ntisch:<br />
SELECT Name, Vorname, Abteilung.Abteilungsbezeichnung<br />
FROM Mitarbeiter OUTER JOIN Abteilung<br />
ON Mitarbeiter.Abteilungsbezeichnung =<br />
Abteilung.Abteilungsbezeichnung<br />
SELECT Name, Vorname, Abteilung.Abteilungsbezeichnung<br />
FROM Mitarbeiter OUTER JOIN Abteilung<br />
USING (Abteilungsbezeichnung)<br />
9.7 »Jo<strong>in</strong>s« auf mehrere Tabellen<br />
Um mehr als zwei Tabellen mite<strong>in</strong>an<strong><strong>de</strong>r</strong> zu verb<strong>in</strong><strong>de</strong>n, gibt es zwei Möglichkeiten. Die<br />
erste Alternative ist <strong><strong>de</strong>r</strong> klassisch komma-getrennte Stil. In diesem Fall gibt man h<strong>in</strong>ter<br />
<strong><strong>de</strong>r</strong> WHERE-Klausel alle Primär- und Fremdschlüsselbeziehungen an, über die die e<strong>in</strong>zelnen<br />
Tabellen mite<strong>in</strong>an<strong><strong>de</strong>r</strong> verknüpft s<strong>in</strong>d und verb<strong>in</strong><strong>de</strong>t diese Beziehungen mit<br />
AND. Um z.B. die Namen und <strong>de</strong>n Wohnort aller Kun<strong>de</strong>n, sowie die Namen <strong><strong>de</strong>r</strong> dazugehörigen<br />
K<strong>in</strong><strong><strong>de</strong>r</strong> auszugeben, sieht die SELECT-Anweisung dann wie folgt aus:<br />
SELECT Kun<strong>de</strong>.Name, Kun<strong>de</strong>.Vorname, Ort.Ort, K<strong>in</strong>d.Vorname<br />
FROM Kun<strong>de</strong>, K<strong>in</strong>d, Ort<br />
WHERE Kun<strong>de</strong>.Kun<strong>de</strong>nnummer = K<strong>in</strong>d.Kun<strong>de</strong>nnummer<br />
AND Kun<strong>de</strong>.Plz = Ort.Plz<br />
Die Anzahl <strong><strong>de</strong>r</strong> zu verknüpfen<strong>de</strong>n Tabellen bestim<strong>mt</strong> dabei die Anzahl <strong><strong>de</strong>r</strong> Bed<strong>in</strong>gungen<br />
h<strong>in</strong>ter WHERE, die jeweils durch AND verbun<strong>de</strong>n wer<strong>de</strong>n.<br />
Die zweite Möglichkeit, mehrere Tabellen untere<strong>in</strong>an<strong><strong>de</strong>r</strong> zu verb<strong>in</strong><strong>de</strong>n, ist die Verwendung<br />
<strong><strong>de</strong>r</strong> Schlüsselwörter JOIN und ON. Hierbei verknüpft man immer das Ergebnis<br />
<strong>de</strong>s ersten Jo<strong>in</strong>s mit <strong>de</strong>m zweiten Jo<strong>in</strong> usw. Das Ganze sieht dann folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
SELECT Kun<strong>de</strong>.Name, Kun<strong>de</strong>.Vorname, Ort.Ort, K<strong>in</strong>d.Vorname<br />
FROM Kun<strong>de</strong> INNER JOIN K<strong>in</strong>d<br />
ON Kun<strong>de</strong>.Kun<strong>de</strong>nnummer = K<strong>in</strong>d.Kun<strong>de</strong>nnummer<br />
INNER JOIN Ort<br />
ON Kun<strong>de</strong>.Plz = Ort.Plz<br />
In diesem Fall wird zunächst das Ergebnis aus <strong>de</strong>m ersten »Jo<strong>in</strong>« zwischen Kun<strong>de</strong> und<br />
K<strong>in</strong>d gebil<strong>de</strong>t. Danach wird dieses Ergebnis verwen<strong>de</strong>t und über e<strong>in</strong>en »Jo<strong>in</strong>« mit <strong><strong>de</strong>r</strong><br />
Tabelle »Ort« verknüpft.
9.8 Zusammenfassung<br />
Zusammenfassung<br />
In diesem Kapitel haben wir gesehen, wie man mehrere Tabellen zu e<strong>in</strong>er Tabelle verb<strong>in</strong><strong>de</strong>t.<br />
Auf diese Tabelle kann man dann wie<strong><strong>de</strong>r</strong> alle Ausdrücke und Prädikate anwen<strong>de</strong>n,<br />
die wir im letzten Kapitel kennen gelernt haben.<br />
E<strong>in</strong>e Möglichkeit, um zwei Tabellen mite<strong>in</strong>an<strong><strong>de</strong>r</strong> zu verb<strong>in</strong><strong>de</strong>n, ist die Anwendung <strong>de</strong>s<br />
klassischen komma-getrennten Stils. Dabei verwen<strong>de</strong>t man die normalen Bed<strong>in</strong>gungsausdrücke,<br />
um Fremd- und Primärschlüssel mite<strong>in</strong>an<strong><strong>de</strong>r</strong> zu vergleichen. »Jo<strong>in</strong>s« s<strong>in</strong>d<br />
dabei nicht nur auf Fremd- und Primärschlüssel beschränkt. Letztendlich kann je<strong>de</strong><br />
Tabelle mit e<strong>in</strong>er an<strong><strong>de</strong>r</strong>en Tabelle verbun<strong>de</strong>n wer<strong>de</strong>n, sofern diese zwei semantisch<br />
gleiche Spalten besitzen. Auch e<strong>in</strong>e Verb<strong>in</strong>dung über das Gleichheitszeichen ist nicht<br />
zw<strong>in</strong>gend notwendig. Ebenso können alle an<strong><strong>de</strong>r</strong>en Vergleichsoperatoren verwen<strong>de</strong>t<br />
wer<strong>de</strong>n, auch wenn diese Fälle <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>Praxis</strong> selten auftreten.<br />
Neben <strong>de</strong>m komma-getrennten Stil gibt es spezielle Schlüsselwörter, um »Jo<strong>in</strong>s« zu<br />
kennzeichnen. Dabei unterschei<strong>de</strong>t man generell zwischen<br />
� OUTER JOIN und<br />
� INNER JOIN<br />
E<strong>in</strong> INNER JOIN berücksichtigt im Gegensatz zum OUTER JOIN unbekannte Werte<br />
über NULL nicht. E<strong>in</strong> Spezialfall <strong>de</strong>s INNER JOIN ist <strong><strong>de</strong>r</strong> NATURAL JOIN, <strong>de</strong>ssen<br />
Hauptaufgabe <strong>in</strong> <strong><strong>de</strong>r</strong> Verknüpfung von Tabellen über Primär- und Fremdschlüssel<br />
besteht.<br />
9.9 Aufgaben<br />
Wie<strong><strong>de</strong>r</strong>holungsfragen<br />
1) Wor<strong>in</strong> besteht <strong><strong>de</strong>r</strong> Unterschied zwischen e<strong>in</strong>em INNER JOIN und e<strong>in</strong>em CROSS<br />
JOIN?<br />
2) Wor<strong>in</strong> besteht <strong><strong>de</strong>r</strong> Unterschied zwischen e<strong>in</strong>em RIGHT OUTER JOIN und e<strong>in</strong>em<br />
LEFT OUTER JOIN?<br />
3) Folgen<strong>de</strong> Anweisung verb<strong>in</strong><strong>de</strong>t die Tabellen Mitarbeiter und Abteilung:<br />
Mitarbeiter NATURAL JOIN Abteilung<br />
Geben Sie SQL-Ausdrücke an, die diesem entsprechen!<br />
4) Wie können Sie folgen<strong>de</strong> SQL-Anweisung durch H<strong>in</strong>zufügen e<strong>in</strong>er WHERE-Klausel<br />
so än<strong><strong>de</strong>r</strong>n, dass sie e<strong>in</strong>em LEFT OUTER JOIN entspricht?<br />
SELECT Name, Vorname, Abteilung.Abteilungsbezeichnung<br />
FROM Mitarbeiter FULL OUTER JOIN Abteilung<br />
ON Mitarbeiter.Abteilungsbezeichnung =<br />
Abteilung.Abteilungsbezeichnung<br />
WHERE ...<br />
173
174<br />
9 Abfragen auf mehrere Tabellen<br />
5) Geben Sie e<strong>in</strong> Beispiel für e<strong>in</strong>en »Self Jo<strong>in</strong>« !<br />
6) Was ist bei e<strong>in</strong>em »Self Jo<strong>in</strong>« bei <strong><strong>de</strong>r</strong> Angabe <strong><strong>de</strong>r</strong> Tabellennamen zu beachten?<br />
Übungen<br />
1) Geben Sie die Namen aller Spielstätten aus und <strong>de</strong>n Ortsnamen, <strong>in</strong> <strong>de</strong>m sich die<br />
Spielstätte bef<strong>in</strong><strong>de</strong>t!<br />
2) In welchen Spielstätten f<strong>in</strong><strong>de</strong>n Veranstaltungen statt, die von Mozart s<strong>in</strong>d?<br />
3) Geben Sie die Name <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n und die Anzahl <strong><strong>de</strong>r</strong> Bestellungen aus, die von diesem<br />
stammen!<br />
4) Erstellen Sie e<strong>in</strong>e Liste aller Bestellungen und <strong><strong>de</strong>r</strong>en Bestellposten!<br />
5) Erstellen Sie e<strong>in</strong>e Liste aller Vorstellungen mit Bezeichnung und Adresse <strong><strong>de</strong>r</strong> Spielstätte,<br />
Bezeichnung <strong><strong>de</strong>r</strong> Veranstaltung und Angabe <strong><strong>de</strong>r</strong> Vorstellungsterm<strong>in</strong>e!<br />
6) Geben Sie die Bezeichnung und <strong>de</strong>n Ortsnamen <strong><strong>de</strong>r</strong> Spielstätten aus, die die gleiche<br />
Postleitzahl besitzen?<br />
7) Geben Sie die Namen aller Kun<strong>de</strong>n aus, die im gleichen Ort wohnen!<br />
8) Welche Sitzplätze s<strong>in</strong>d zur Veranstaltung »Phil Coll<strong>in</strong>s LIVE« am 21.07.2002 noch<br />
frei?<br />
9) Zu welchen Term<strong>in</strong>en gibt es Vorstellungen zu <strong><strong>de</strong>r</strong> Veranstaltung »Don Giovanni« ?<br />
10) Welche Kun<strong>de</strong>n haben die Veranstaltung »Don Giovanni« zu welchem Term<strong>in</strong> gebucht<br />
und welche Sitzplätze haben sie erhalten?<br />
11) In welcher Spielstätte f<strong>in</strong><strong>de</strong>n ke<strong>in</strong>e Vorstellungen statt?<br />
12) Zu welcher Veranstaltung gibt es zur Zeit ke<strong>in</strong>e Vorstellungen?<br />
13) Geben Sie die Namen <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n aus, die bei e<strong>in</strong>em Bestellvorgang mehr als drei<br />
Artikel bestellt haben!<br />
14) Geben Sie die Namen <strong><strong>de</strong>r</strong> Kun<strong>de</strong>n aus, <strong><strong>de</strong>r</strong>en K<strong>in</strong><strong><strong>de</strong>r</strong> das gleiche Geschlecht haben.<br />
Geben Sie dabei auch die Namen <strong><strong>de</strong>r</strong> K<strong>in</strong><strong><strong>de</strong>r</strong> aus!
10<br />
Abfragen mit<br />
Unterabfragen<br />
In Kapitel 10 sollen folgen<strong>de</strong> Fragen geklärt wer<strong>de</strong>n:<br />
� Wie kann man das Ergebnis e<strong>in</strong>er Abfrage als Teil e<strong>in</strong>er neuen Abfrage verwen<strong>de</strong>n?<br />
� Wie kann man <strong>in</strong> e<strong>in</strong>er e<strong>in</strong>zigen Anweisung ermitteln, welche Mitarbeiter über <strong>de</strong>m<br />
Durchschnitt verdienen?<br />
10.1 Motivation<br />
Inzwischen hat Frau Kart die neuen Abfragen fertiggestellt und zeigt sie ihrem<br />
Geschäftsführer, Herrn Kowalski. Der ist begeistert und angesichts <strong><strong>de</strong>r</strong> Tatsache, dass<br />
das Jahr bald zu En<strong>de</strong> geht, möchte Herr Kowalski e<strong>in</strong>en Bonus an alle Mitarbeiter ausgeben.<br />
Dabei sollen alle Mitarbeiter die über <strong>de</strong>m Durchschnitt verdienen, e<strong>in</strong>en Bonus<br />
von 10% und Mitarbeiter unter <strong>de</strong>m Durchschnitt e<strong>in</strong>en Bonus von 15% erhalten. Also<br />
beauftragt er Frau Kart, zwei Listen zu erstellen. E<strong>in</strong>e Liste soll alle Mitarbeitern enthalten,<br />
die überdurchschnittlich verdienen und die zweite Liste die Mitarbeiter, die<br />
unter <strong>de</strong>m Durchschnitt verdienen.<br />
Zunächst ermittelt Frau Kart das Durchschnittsgehalt mit <strong><strong>de</strong>r</strong> Mengenfunktion AVG<br />
und schreibt dieses auf. Mit zwei e<strong>in</strong>fachen SELECT-Anweisungen kann sie nun die<br />
bei<strong>de</strong>n Listen erstellen. Ihr Ergebnis ist zwar korrekt, <strong>de</strong>nnoch ist sie unzufrie<strong>de</strong>n, da<br />
Herr Fleissig von <strong><strong>de</strong>r</strong> Unternehmensberatung ihr erzählt hat, dass die meisten Abfragen<br />
durch e<strong>in</strong>e e<strong>in</strong>zige SELECT-Anweisung ausgeführt wer<strong>de</strong>n können. Sie ruft also<br />
wie<strong><strong>de</strong>r</strong> Herrn Fleissig an, <strong><strong>de</strong>r</strong> ihr erzählt, dass man mehrere SELECT-Anweisungen<br />
»schachteln« kann.<br />
10.2 Grundlagen<br />
Betrachten wir zunächst unser Fallbeispiel: Die SELECT-Anweisung zum Ermitteln <strong>de</strong>s<br />
durchschnittlichen Gehaltes lautet:<br />
SELECT AVG( Gehalt ) AS 'Durchschnittsgehalt'<br />
FROM Mitarbeiter<br />
Durchschnittsgehalt<br />
-------------------<br />
3016.666666<br />
175
176<br />
10 Abfragen mit Unterabfragen<br />
Den ermittelten Wert für das Durchschnittsgehalt können wir nun verwen<strong>de</strong>n, um alle<br />
Mitarbeiter abzufragen, die unter <strong>de</strong>m Durchschnitt liegen. Entsprechend e<strong>in</strong>fach sieht<br />
die dazugehörige SELECT-Anweisung aus:<br />
SELECT Name, Vorname<br />
FROM Mitarbeiter<br />
WHERE Gehalt < 3016.66<br />
Name Vorname Gehalt<br />
----- ------- -------<br />
Kart Karen 3000.00<br />
Kle<strong>in</strong> Karl 2050.00<br />
Um zum gewünschten Ergebnis zu gelangen, mussten also zwei Abfragen ausgeführt<br />
wer<strong>de</strong>n. Das Resultat <strong><strong>de</strong>r</strong> ersten Abfrage wur<strong>de</strong> <strong>in</strong> <strong><strong>de</strong>r</strong> zweiten Abfrage weiter verwen<strong>de</strong>t.<br />
Man kann nun bei<strong>de</strong> SELECT-Anweisungen mite<strong>in</strong>an<strong><strong>de</strong>r</strong> schachteln und das Ergebnis<br />
<strong><strong>de</strong>r</strong> ersten Abfrage direkt <strong>in</strong> die zweite Abfrage e<strong>in</strong>fliessen lassen. Dazu komb<strong>in</strong>iert<br />
man bei<strong>de</strong> Abfragen e<strong>in</strong>fach wie folgt:<br />
SELECT Name, Vorname, Gehalt<br />
FROM Mitarbeiter<br />
WHERE Gehalt < ( SELECT AVG( Gehalt )<br />
FROM Mitarbeiter )<br />
Wir erhalten das gleiche Ergebnis durch e<strong>in</strong>e e<strong>in</strong>zige Abfrage, <strong>in</strong><strong>de</strong>m die Anweisung<br />
zur Ermittlung <strong>de</strong>s Durchschnittsgehalts <strong>in</strong> <strong><strong>de</strong>r</strong> WHERE-Bed<strong>in</strong>gung verwen<strong>de</strong>t wird.<br />
Aufgrund dieser Vorgehensweise bezeichnet man die Abfragen, die <strong>in</strong> die WHERE-<br />
Bed<strong>in</strong>gung e<strong>in</strong>fließen als Unterabfrage (Subquery) o<strong><strong>de</strong>r</strong> <strong>in</strong>nere Abfrage. Entsprechend<br />
wird die zweite Abfrage als äußere Abfrage bezeichnet. Unterabfragen s<strong>in</strong>d also Abfragen<br />
<strong>in</strong>nerhalb e<strong>in</strong>er Abfrage.<br />
In unserem Beispiel liefert die <strong>in</strong>nere Abfrage e<strong>in</strong>en e<strong>in</strong>zigen Wert zurück, nämlich das<br />
Durchschnittsgehalt. Wir wissen aber aus <strong>de</strong>n letzen Kapiteln, dass Abfragen nicht nur<br />
e<strong>in</strong>zelne Werte, son<strong><strong>de</strong>r</strong>n Zeilen o<strong><strong>de</strong>r</strong> ganze Ergebnistabellen zurückliefern können. Je<br />
nach<strong>de</strong>m, was von <strong><strong>de</strong>r</strong> <strong>in</strong>neren Abfrage zurückgeliefert wird, unterschei<strong>de</strong>t man zwischen:<br />
� Unterabfragen mit e<strong>in</strong>em Rückgabewert (»Scalar Subquery« ),<br />
� Unterabfragen mit e<strong>in</strong>er zurückgegebenen Zeile (»Row Subquery« ),<br />
� Unterabfragen mit mehreren zurückgegebenen Zeilen (»Table Subquery« ).<br />
Wir wollen uns im Folgen<strong>de</strong>n die unterschiedlichen Typen von Unterabfragen und die<br />
dazugehörigen Abfragemöglichkeiten ansehen.
Unterabfragen mit e<strong>in</strong>em Rückgabewert<br />
10.3 Unterabfragen mit e<strong>in</strong>em Rückgabewert<br />
Diese Art von Unterabfragen haben wir bereits im e<strong>in</strong>leiten<strong>de</strong>n Beispiel kennen<br />
gelernt. Voraussetzung dafür, dass die Abfrage korrekt ausgeführt wur<strong>de</strong>, war die Tatsache,<br />
dass die <strong>in</strong>nere Abfrage genau e<strong>in</strong>en Wert zurückliefert. Wären mehrere Werte<br />
von <strong><strong>de</strong>r</strong> Unterabfrage zurückgeliefert wor<strong>de</strong>n, so hätte das RDBMS die Abfrage nicht<br />
ausführen können. Betrachten wir hierzu e<strong>in</strong> Beispiel: Es sollen alle Mitarbeiter ausgegeben<br />
wer<strong>de</strong>n, die weniger verdienen als Frau Kart. E<strong>in</strong>e gültige SELECT-Anweisung<br />
könnte lauten:<br />
SELECT Name, Vorname, Gehalt<br />
FROM Mitarbeiter<br />
WHERE Gehalt < ( SELECT Gehalt<br />
FROM Mitarbeiter<br />
WHERE Name LIKE 'K%' )<br />
Hier wür<strong>de</strong> das RDBMS e<strong>in</strong>e Fehlermeldung ausgeben, da die <strong>in</strong>nere Abfrage mehr als<br />
e<strong>in</strong>en Wert zurückliefert. Sowohl das Gehalt von Frau Kart als auch das von Herrn<br />
Kowalski wer<strong>de</strong>n von <strong><strong>de</strong>r</strong> Unterabfrage zurückgegeben.<br />
Bei skalaren Unterabfragen muss also gewährleistet se<strong>in</strong>, dass die <strong>in</strong>nere Abfrage zum<br />
e<strong>in</strong>en nur e<strong>in</strong>en e<strong>in</strong>zigen Wert zurückliefert und dass die Spalten, die man mite<strong>in</strong>an<strong><strong>de</strong>r</strong><br />
vergleicht, zue<strong>in</strong>an<strong><strong>de</strong>r</strong> passen. Die <strong>in</strong>nere Abfrage muss also e<strong>in</strong>en Wert zurückliefern,<br />
<strong><strong>de</strong>r</strong> zur <strong><strong>de</strong>r</strong> Spalte passt, mit <strong><strong>de</strong>r</strong> verglichen wird (<strong>in</strong> unserem Fall verwen<strong>de</strong>n <strong>in</strong>nere<br />
und äußere Abfrage die Spalte »Gehalt« ).<br />
Damit die <strong>in</strong>nere Abfrage nur e<strong>in</strong>en Wert zurückliefert, sollte man <strong>in</strong> diesem Fall besser<br />
<strong>de</strong>n Primärschlüssel, also die Personalnummer von Frau Kart, als Bed<strong>in</strong>gung angeben.<br />
Betrachten wir hierzu e<strong>in</strong> weiteres Beispiel. Um alle Mitarbeiter auszugeben, die im<br />
gleichen Ort wohnen, wie Hans Muster, sollte die Abfrage also folgen<strong><strong>de</strong>r</strong>maßen aussehen:<br />
SELECT Name, Vorname, Plz<br />
FROM Mitarbeiter<br />
WHERE Plz = ( SELECT Plz<br />
FROM Kun<strong>de</strong><br />
WHERE Kun<strong>de</strong>nnummer = 2 )<br />
Diesmal wird die Postleitzahl von Hans Muster über <strong>de</strong>n Primärschlüssel ermittelt, so<br />
dass nur e<strong>in</strong> Wert von <strong><strong>de</strong>r</strong> <strong>in</strong>neren Abfrage zurückgeliefert wer<strong>de</strong>n kann.<br />
177
178<br />
10 Abfragen mit Unterabfragen<br />
10.4 Unterabfragen mit e<strong>in</strong>er<br />
zurückgegebenen Zeile<br />
Unterabfragen mit e<strong>in</strong>er e<strong>in</strong>zigen zurückgebenen Zeile wer<strong>de</strong>n von <strong>de</strong>n meisten<br />
RDBMS zur Zeit noch nicht unterstützt. Generell gleichen solche Abfragen <strong>de</strong>n Abfragen<br />
mit nur e<strong>in</strong>em Wert, nur dass hier mehrere Spalten beim Vergleich angegeben wer<strong>de</strong>n<br />
können. Um also z.B. alle Mitarbeiter auszugeben, die sowohl im gleichen Ort als<br />
auch <strong>in</strong> <strong><strong>de</strong>r</strong> gleichen Strasse wie Hans Muster wohnen, lautet die Anweisung:<br />
SELECT Name, Vorname, Plz<br />
FROM Mitarbeiter<br />
WHERE (Plz, Strasse) = ( SELECT Plz, Strasse<br />
FROM Kun<strong>de</strong><br />
WHERE Kun<strong>de</strong>nnummer = 2 )<br />
10.5 Unterabfragen mit mehreren<br />
zurückgegebenen Zeilen<br />
Um <strong>in</strong> Unterabfragen mehrere Zeilen abzufragen, reichen die bisherigen Vergleichsoperatoren<br />
und Prädikate nicht aus. SQL kennt <strong>de</strong>shalb für diese Art von Abfragen<br />
spezielle Prädikate, die wir uns im Folgen<strong>de</strong>n ansehen wollen.<br />
10.5.1 IN<br />
Das Prädikat IN entspricht eigentlich e<strong>in</strong>er OR-Verknüpfung von Werten. Wenn e<strong>in</strong>e<br />
Unterabfrage mehrere Werte e<strong>in</strong>er Spalte zurückliefert, so kann mit IN überprüft wer<strong>de</strong>n,<br />
ob e<strong>in</strong>er dieser Werte e<strong>in</strong>er gewünschten Bed<strong>in</strong>gung entspricht. Um z.B. alle Mitarbeiter<br />
auszugeben, die im gleichen Ort wie die Kun<strong>de</strong>n Hans Muster und Bertram<br />
Bolte wohnen, lautet die SELECT-Anweisung:<br />
SELECT Name, Vorname, Plz<br />
FROM Mitarbeiter<br />
WHERE Plz IN ( SELECT Plz<br />
FROM Kun<strong>de</strong><br />
WHERE Kun<strong>de</strong>nnummer = 1 OR Kun<strong>de</strong>nnummer = 2)<br />
Um <strong>de</strong>mgegenüber alle Mitarbeiter zu ermitteln, die nicht im gleichen Ort wie Hans<br />
Muster und Bertram Bolte wohnen, verwen<strong>de</strong>t man e<strong>in</strong>fach die Schlüsselwörter NOT<br />
IN.<br />
10.5.2 EXISTS<br />
Über das Schlüsselwort EXISTS kann getestet wer<strong>de</strong>n, ob e<strong>in</strong>e Unterabfrage Zeilen<br />
zurückliefert. Ist dies <strong><strong>de</strong>r</strong> Fall, so liefert die Unterabfrage TRUE zurück, an<strong><strong>de</strong>r</strong>nfalls
Unterabfragen mit mehreren zurückgegebenen Zeilen<br />
FALSE. Um z.B. alle Abteilungen auszugeben, <strong>de</strong>nen m<strong>in</strong><strong>de</strong>stens e<strong>in</strong> Mitarbeiter zugeordnet<br />
ist, lautet die SELECT-Anweisung:<br />
SELECT Abteilungsbezeichnung<br />
FROM Abteilung<br />
WHERE EXISTS ( SELECT *<br />
FROM Mitarbeiter<br />
WHERE Mitarbeiter.Abteilungsbezeichnung =<br />
Abteilung.Abteilungsbezeichnung)<br />
Abteilungsbezeichnung<br />
--<br />
Vertrieb<br />
Wie bei e<strong>in</strong>em »Jo<strong>in</strong>« auch, müssen Fremd- und Primärschlüssel mite<strong>in</strong>an<strong><strong>de</strong>r</strong> verbun<strong>de</strong>n<br />
wer<strong>de</strong>n. In diesem Fall stehen <strong>in</strong>nere und äußere Abfrage <strong>in</strong> e<strong>in</strong>er Wechselbeziehung<br />
zue<strong>in</strong>an<strong><strong>de</strong>r</strong>, da die <strong>in</strong>nere auf die äußere Abfrage verweist. Man spricht dann von<br />
»korrelieren<strong>de</strong>n Unterabfragen« . Im Gegensatz zu <strong>de</strong>n bisherigen Unterabfragen wertet<br />
e<strong>in</strong> RDBMS korrelieren<strong>de</strong> Unterabfragen an<strong><strong>de</strong>r</strong>s aus. Bei e<strong>in</strong>er nicht-korrelieren<strong>de</strong>n<br />
Abfrage kann das RDBMS zunächst die <strong>in</strong>nere Abfrage ausführen und erhält dann e<strong>in</strong><br />
Ergebnis. Dieses Ergebnis kann es dann verwen<strong>de</strong>n, um die äußere Abfrage auszuführen.<br />
Bei korrelieren<strong>de</strong>n Unterabfragen ist dies nicht möglich, da die <strong>in</strong>nere Abfrage<br />
immer von <strong><strong>de</strong>r</strong> gera<strong>de</strong> bearbeiteten Zeile <strong><strong>de</strong>r</strong> äußeren Abfrage abhängt. Für je<strong>de</strong> Zeile<br />
<strong><strong>de</strong>r</strong> äußeren Abfrage wird also auch die <strong>in</strong>nere Abfrage ausgewertet. Betrachten wir<br />
dazu folgen<strong>de</strong> Abbildung:<br />
SELECT *<br />
FROM Mitarbeiter 2<br />
WHERE Abteilungsbezeichnung = 'Vertrieb'<br />
Mitarbeiter<br />
Personalnummer<br />
3<br />
5<br />
6<br />
EXISTS<br />
Name<br />
Kart<br />
Kle<strong>in</strong><br />
Kowalski<br />
Vorname<br />
Karen<br />
Karl<br />
Karsten<br />
1<br />
SELECT Abteilungsbezeichnung<br />
FROM Abteilung<br />
Abteilung<br />
Abteilungsbezeichnung<br />
Vertrieb<br />
Geschäftsführung<br />
Abteilungsbezeichnung<br />
Vertrieb<br />
Vertrieb<br />
NULL<br />
Abteilungsnummer<br />
1<br />
2<br />
EXISTS<br />
SELECT *<br />
FROM Mitarbeiter<br />
WHERE Abteilungsbezeichnung = 'Geschäftsführung'<br />
Mitarbeiter<br />
Personalnummer<br />
3<br />
5<br />
6<br />
Name<br />
Kart<br />
Kle<strong>in</strong><br />
Kowalski<br />
Vorname<br />
Karen<br />
Karl<br />
Karsten<br />
Abbildung 10.1: Korrelieren<strong>de</strong> Unterabfrage mit EXISTS<br />
3<br />
4<br />
Abteilungsbezeichnung<br />
Vertrieb<br />
Vertrieb<br />
NULL<br />
179
180<br />
10 Abfragen mit Unterabfragen<br />
Zunächst wird über die äußere Abfrage die erste Abteilungsbezeichnung ermittelt,<br />
nämlich Vertrieb (1). Dieser Wert wird nun <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>in</strong>neren Abfrage verwen<strong>de</strong>t, um herauszubekommen,<br />
welche Mitarbeiter im Vertrieb arbeiten (2). Da es <strong>in</strong> diesem Fall zwei<br />
Mitarbeiter s<strong>in</strong>d, erfüllt die Abteilungsbezeichnung »Vertrieb« die Bed<strong>in</strong>gung und<br />
gehört zur Ergebnistabelle. Nun ermittelt die äußere Abfrage die nächste Abteilungsbezeichnung,<br />
nämlich »Geschäftsführung« (3). Die <strong>in</strong>nere Abfrage stellt fest, dass es<br />
ke<strong>in</strong>en Mitarbeiter gibt, <strong><strong>de</strong>r</strong> zu dieser Abteilung gehört (4). Entsprechend gibt sie<br />
FALSE zurück.<br />
Wie beim Mengenoperator IN kann auch EXISTS über das Schlüsselwort NOT negiert<br />
wer<strong>de</strong>n.<br />
10.5.3 ANY / SOME / ALL<br />
Mit ANY o<strong><strong>de</strong>r</strong> SOME kann man überprüfen, ob e<strong>in</strong> Wert größer als e<strong>in</strong> beliebiger Wert<br />
aus e<strong>in</strong>er Menge ist. Hiermit s<strong>in</strong>d Abfragen möglich, wie z.B. »Geben Sie das Gehalt<br />
aller Mitarbeiter an, die mehr als e<strong>in</strong> an<strong><strong>de</strong>r</strong>er Mitarbeiter verdienen« . Die dazugehörige<br />
SELECT-Anweisung lautet:<br />
SELECT Name, Vorname, Gehalt<br />
FROM Mitarbeiter<br />
WHERE Gehalt > ANY (SELECT Gehalt FROM Mitarbeiter )<br />
Name Vorname Gehalt<br />
-------- ------- -------<br />
Kart Karen 3000.00<br />
Kowalski Karsten 4000.00<br />
Frau Kart verdient mehr als Herr Kle<strong>in</strong> und Herr Kowalski verdient sowieso mehr als<br />
je<strong><strong>de</strong>r</strong> an<strong><strong>de</strong>r</strong>e Mitarbeiter. Herr Kle<strong>in</strong> ist nicht aufgeführt, da es ke<strong>in</strong>en an<strong><strong>de</strong>r</strong>en Mitarbeiter<br />
gibt, <strong><strong>de</strong>r</strong> weniger als er verdient.<br />
Entsprechend kann man über das Schlüsselwort ALL ermitteln, welcher Mitarbeiter<br />
mehr als je<strong><strong>de</strong>r</strong> an<strong><strong>de</strong>r</strong>e Mitarbeiter verdient. Die SELECT-Anweisung dazu sieht dann<br />
wie folgt aus:<br />
SELECT Name, Vorname, Gehalt<br />
FROM Mitarbeiter<br />
WHERE Gehalt >= ALL (SELECT Gehalt FROM Mitarbeiter )<br />
Name Vorname Gehalt<br />
-------- ------- -------<br />
Kowalski Karsten 4000.00<br />
In diesem Fall wird nur Herr Kowalski ausgegeben, da es ke<strong>in</strong>en Mitarbeiter gibt, <strong><strong>de</strong>r</strong><br />
mehr als er verdient.
Zusammenfassung<br />
Sie haben sicherlich bemerkt, dass man die bei<strong>de</strong>n obigen Abfragen auch mit <strong>de</strong>n Mengenfunktionen<br />
MIN und MAX als Unterabfrage hätte realisieren können. Letztendlich<br />
gibt es <strong>in</strong> SQL häufig mehrere Möglichkeiten, Abfragen zu formulieren.<br />
Das gilt für viele Abfragen. Betrachten wir hierzu e<strong>in</strong> weiteres Beispiel: Um z.B. alle<br />
Mitarbeiter auszugeben, die <strong>in</strong> e<strong>in</strong>em Ort wohnen, <strong>in</strong> <strong>de</strong>m auch e<strong>in</strong> beliebiger Kun<strong>de</strong><br />
wohnt, führen folgen<strong>de</strong> SELECT-Anweisungen zum gleichen Ergebnis:<br />
SELECT Name, Vorname<br />
FROM Mitarbeiter<br />
WHERE Plz = ANY (SELECT Plz FROM Kun<strong>de</strong>)<br />
SELECT Mitarbeiter.Name, Mitarbeiter.Vorname<br />
FROM Mitarbeiter, Kun<strong>de</strong><br />
WHERE Mitarbeiter.Plz = Kun<strong>de</strong>.Plz<br />
Generell gilt, dass die meisten Abfragen, die man als »Jo<strong>in</strong>« formulieren kann, auch als<br />
»Subquery« gestellt wer<strong>de</strong>n können. In diesem Fall bleibt es Geschmackssache, welche<br />
Formulierung man als »besser« empf<strong>in</strong><strong>de</strong>t. E<strong>in</strong>e Ausnahme, die man nicht als »Jo<strong>in</strong>«<br />
formulieren kann, ist das Verwen<strong>de</strong>n von Mengenfunktionen <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>in</strong>neren Abfrage,<br />
wie wir es gleich am Anfang kennen gelernt haben.<br />
10.6 Zusammenfassung<br />
In diesem Kapitel haben wir Unterabfragen kennen gelernt. Gera<strong>de</strong> <strong>in</strong> Zusammenhang<br />
mit <strong><strong>de</strong>r</strong> Verwendung von Mengenfunktionen s<strong>in</strong>d Unterabfragen sehr nützlich. Unterabfragen<br />
s<strong>in</strong>d Abfragen <strong>in</strong> e<strong>in</strong>er Abfrage. Man kann die Ergebniswerte e<strong>in</strong>er Abfrage<br />
als Vergleichswerte <strong>in</strong> e<strong>in</strong>er an<strong><strong>de</strong>r</strong>en Abfrage verwen<strong>de</strong>n. Man unterschei<strong>de</strong>t Unterabfragen<br />
danach, ob sie e<strong>in</strong>en e<strong>in</strong>zigen Wert, e<strong>in</strong>e e<strong>in</strong>zige Zeile o<strong><strong>de</strong>r</strong> mehrere Zeilen<br />
zurückliefert.<br />
Liefert e<strong>in</strong>e Unterabfrage mehrere Zeilen zurück, so können die Prädikate IN, EXISTS,<br />
ANY/SOME o<strong><strong>de</strong>r</strong> ALL verwen<strong>de</strong>t wer<strong>de</strong>n. IN dient zur Überprüfung e<strong>in</strong>er zurückgelieferten<br />
Menge von Werten, so wie wir es bereits bei e<strong>in</strong>fachen Abfragen gesehen hatten.<br />
Das Prädikat EXISTS gibt TRUE o<strong><strong>de</strong>r</strong> FALSE aus, je nach<strong>de</strong>m ob die Unterabfrage<br />
Sätze zurückliefert o<strong><strong>de</strong>r</strong> nicht. ANY bzw. SOME testet, ob aus e<strong>in</strong>er Menge von Werten<br />
wenigstens e<strong>in</strong> Wert e<strong>in</strong>er Bed<strong>in</strong>gung entspricht. ALL prüft, ob alle Werte e<strong>in</strong>er Menge<br />
e<strong>in</strong>er <strong>de</strong>f<strong>in</strong>ierten Bed<strong>in</strong>gung entsprechen.<br />
10.7 Aufgaben<br />
Wie<strong><strong>de</strong>r</strong>holungsfragen<br />
1) Was ist mit <strong>in</strong>nerer Abfrage und was mit äußerer Abfrage geme<strong>in</strong>t?<br />
2) Was ist e<strong>in</strong>e korrelieren<strong>de</strong> Unterabfrage?<br />
181
182<br />
10 Abfragen mit Unterabfragen<br />
3) Wie wird e<strong>in</strong>e nicht-korrelieren<strong>de</strong> Unterabfrage vom RDBMS ausgewertet? Erklären<br />
Sie dies anhand e<strong>in</strong>es Beispiels.<br />
4) Wie wird e<strong>in</strong>e korrelieren<strong>de</strong> Unterabfrage vom RDBMS ausgewertet? Erklären Sie<br />
dies anhand e<strong>in</strong>es Beispiels.<br />
5) Worauf muss man achten, wenn man <strong>in</strong> <strong><strong>de</strong>r</strong> äußeren Abfrage ausschließlich Vergleichsoperatoren<br />
verwen<strong>de</strong>t?<br />
6) Wozu dienen die Prädikate NOT IN, NOT EXISTS, ALL, SOME?<br />
Übungen<br />
1) Welche Mitarbeiter verdienen mehr als <strong><strong>de</strong>r</strong> Mitarbeiter mit <strong>de</strong>m kle<strong>in</strong>sten Gehalt?<br />
2) Welcher Abteilung s<strong>in</strong>d ke<strong>in</strong>e Mitarbeiter zugeordnet?<br />
3) Erhöhen Sie das Gehalt aller Mitarbeiter, die unter <strong>de</strong>m Durchschnitt verdienen, um<br />
5%! (H<strong>in</strong>weis: Auch bei <strong><strong>de</strong>r</strong> UPDATE-Anweisung kann e<strong>in</strong>e Unterabfrage h<strong>in</strong>ter<br />
<strong><strong>de</strong>r</strong> WHERE-Klausel folgen.)<br />
4) Löschen Sie alle Werbeartikel, <strong><strong>de</strong>r</strong>en Preis unter <strong>de</strong>m Durchschnitt liegt! (H<strong>in</strong>weis:<br />
Auch bei <strong><strong>de</strong>r</strong> DELETE-Anweisung kann e<strong>in</strong>e Unterabfrage h<strong>in</strong>ter <strong><strong>de</strong>r</strong> WHERE-<br />
Klausel folgen.)<br />
5) Welche Sitzplätze <strong><strong>de</strong>r</strong> Vorstellung 11 kosten überdurchschnittlich viel?<br />
6) Geben Sie die Namen <strong><strong>de</strong>r</strong> Mitarbeiter aus, die ke<strong>in</strong>en Vorgesetzten haben! (H<strong>in</strong>weis:<br />
Verwen<strong>de</strong>n Sie die Schlüsselwörter NOT EXISTS.)<br />
7) Geben Sie die Namen <strong><strong>de</strong>r</strong> Spielstätten aus, die die gleiche Postleitzahl besitzen!
11 Transaktionen<br />
In Kapitel 11 sollen folgen<strong>de</strong> Fragen geklärt wer<strong>de</strong>n:<br />
� Wie kann man mehrere Än<strong><strong>de</strong>r</strong>ungen an Datensätzen zu e<strong>in</strong>er E<strong>in</strong>heit zusammenfassen?<br />
� Warum sollte man mehrere Än<strong><strong>de</strong>r</strong>ungen an Datensätzen zu e<strong>in</strong>er E<strong>in</strong>heit zusammenfassen?<br />
� Wie kann man Än<strong><strong>de</strong>r</strong>ungen wie<strong><strong>de</strong>r</strong> rückgängig machen?<br />
� Welche Probleme treten auf, wenn mehrere Benutzer gleichzeitig auf die gleichen<br />
Datensätze e<strong>in</strong>er Tabelle zugreifen?<br />
� Wie können Probleme, die im Mehrbenutzerbetrieb auftreten können, verh<strong>in</strong><strong><strong>de</strong>r</strong>t<br />
wer<strong>de</strong>n?<br />
11.1 Motivation<br />
Täglich gehen neue Bestellungen bei <strong><strong>de</strong>r</strong> Firma »KartoF<strong>in</strong>ale« e<strong>in</strong>. Herr Kle<strong>in</strong>, von Frau<br />
Kart <strong>in</strong>zwischen e<strong>in</strong>gearbeitet, trägt die Bestellungen <strong>in</strong> die Tabellen Bestellung und<br />
Bestellposten e<strong>in</strong>. Gera<strong>de</strong> ist er dabei, e<strong>in</strong>e Bestellung von <strong><strong>de</strong>r</strong> Kund<strong>in</strong> Frau Wiegerich<br />
zu erfassen. Sie möchte für <strong>de</strong>n 27.8. zwei Karten für die Oper »Don Giovanni«.<br />
Zunächst sieht Herr Kle<strong>in</strong> mit Hilfe <strong><strong>de</strong>r</strong> SELECT-Anweisung <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle Sitzplatz<br />
nach, ob noch freie Plätze für diese Vorstellung mit <strong><strong>de</strong>r</strong> Nummer 12 vorhan<strong>de</strong>n s<strong>in</strong>d.<br />
Darauf än<strong><strong>de</strong>r</strong>t er <strong>de</strong>n Zustand <strong><strong>de</strong>r</strong> bei<strong>de</strong>n freien gefun<strong>de</strong>nen Sitzplätze auf <strong>de</strong>n Status<br />
»belegt«. Hierzu verwen<strong>de</strong>t er die UPDATE-Anweisung. Nun will er e<strong>in</strong>en Datensatz<br />
<strong>in</strong> die Tabelle Bestellung e<strong>in</strong>fügen. Er gibt die dazugehörige INSERT-Anweisung e<strong>in</strong><br />
und gera<strong>de</strong> <strong>in</strong> <strong>de</strong>m Moment, wo er die Anweisung zum RDBMS sen<strong>de</strong>n will, fällt <strong><strong>de</strong>r</strong><br />
Strom aus. Die Datenbank von »KartoF<strong>in</strong>ale« bef<strong>in</strong><strong>de</strong>t sich <strong>in</strong> e<strong>in</strong>em <strong>in</strong>konsistenten<br />
Zustand, zwei Sitzplätze wur<strong>de</strong>n als »belegt« gekennzeichnet, obgleich es ke<strong>in</strong>e dazugehörige<br />
Bestellung gibt.<br />
11.2 Transaktionen<br />
In <strong><strong>de</strong>r</strong> realen Welt gibt es immer Folgen von Arbeiten, die zusammengenommen e<strong>in</strong><br />
Ergebnis liefern. Diese Arbeiten müssen entwe<strong><strong>de</strong>r</strong> vollständig o<strong><strong>de</strong>r</strong> gar nicht ausgeführt<br />
wer<strong>de</strong>n. Das bekannteste Beispiel hierfür ist die Überweisung e<strong>in</strong>es Geldbetrages<br />
bei e<strong>in</strong>er Bank. Der Geldbetrag e<strong>in</strong>es Kontos wird e<strong>in</strong>em an<strong><strong>de</strong>r</strong>en Konto gutgeschrieben.<br />
Dazu muss zunächst <strong><strong>de</strong>r</strong> Gelbetrag von e<strong>in</strong>em Konto abgezogen und erst danach<br />
<strong>de</strong>m an<strong><strong>de</strong>r</strong>en Konto h<strong>in</strong>zuaddiert wer<strong>de</strong>n. Wird <strong><strong>de</strong>r</strong> zweite Schritt nicht korrekt ausgeführt,<br />
wür<strong>de</strong> sche<strong>in</strong>bar Geld verschw<strong>in</strong><strong>de</strong>n.<br />
183
184<br />
11 Transaktionen<br />
Um so etwas zu vermei<strong>de</strong>n, fasst man mehrere Arbeitsanweisungen zu e<strong>in</strong>er Transaktion<br />
zusammen. E<strong>in</strong>e Transaktion <strong>in</strong>nerhalb e<strong>in</strong>er Datenbank ist e<strong>in</strong>e Folge von SQL-<br />
Anweisungen, die zusammengenommen e<strong>in</strong>e E<strong>in</strong>heit bil<strong>de</strong>n. Wichtigste Eigenschaft<br />
e<strong>in</strong>er Transaktion ist ihre vollständige Ausführung. Wird e<strong>in</strong>e Transaktion nicht vollständig<br />
ausgeführt, so muss <strong><strong>de</strong>r</strong> Zustand vor Beg<strong>in</strong>n <strong><strong>de</strong>r</strong> Transaktion wie<strong><strong>de</strong>r</strong>hergestellt<br />
wer<strong>de</strong>n. E<strong>in</strong>e Transaktion wird also ganz o<strong><strong>de</strong>r</strong> gar nicht ausgeführt.<br />
In unserem Fallbeispiel haben wir gesehen, dass das Erfassen e<strong>in</strong>er Bestellung aus<br />
mehreren SQL-Anweisungen besteht und somit e<strong>in</strong> typisches Beispiel für e<strong>in</strong>e Transaktion<br />
darstellt. In unserem Fall müssten also die Än<strong><strong>de</strong>r</strong>ungen <strong>de</strong>s Zustan<strong>de</strong>s <strong><strong>de</strong>r</strong> bei<strong>de</strong>n<br />
Sitzplätze wie<strong><strong>de</strong>r</strong> automatisch rückgängig gemacht wer<strong>de</strong>n.<br />
Das Problem <strong>de</strong>s Zurückführens e<strong>in</strong>er Transaktion tritt jedoch nicht nur bei Hardwarefehlern<br />
auf. Programmfehler können auch dazu führen, dass e<strong>in</strong>e Transaktion wie<strong><strong>de</strong>r</strong><br />
zurückgeführt wer<strong>de</strong>n muss. Angenommen, Herr Kle<strong>in</strong> wür<strong>de</strong> die Bestellung <strong>in</strong> e<strong>in</strong>er<br />
an<strong><strong>de</strong>r</strong>en Reihenfolge verarbeiten. Zunächst fügt er e<strong>in</strong>en Datensatz <strong>in</strong> die Tabelle<br />
Bestellung e<strong>in</strong>, danach überprüft er erst, ob es freie Sitzplätze gibt. Ist dies nicht <strong><strong>de</strong>r</strong><br />
Fall, müßte <strong><strong>de</strong>r</strong> erste Schritt dieser Transaktion selbständig wie<strong><strong>de</strong>r</strong> rückgängig gemacht<br />
wer<strong>de</strong>n.<br />
SQL kennt vier Anweisungen zum Zurückführen und endgültigen Sichern von Än<strong><strong>de</strong>r</strong>ungen.<br />
11.3 ROLLBACK und COMMIT<br />
Gemäß <strong>de</strong>m SQL:1999 Standard beg<strong>in</strong>nt e<strong>in</strong>e Transaktion immer automatisch mit <strong><strong>de</strong>r</strong><br />
ersten SQL-Anweisung. Es gibt also im Standard ke<strong>in</strong>e Anweisung, um e<strong>in</strong>e Transaktion<br />
explizit zu starten. Been<strong>de</strong>t wird e<strong>in</strong>e Transaktion durch die SQL-Anweisung<br />
ROLLBACK o<strong><strong>de</strong>r</strong> COMMIT. Die SQL-Anweisung ROLLBACK stellt <strong>de</strong>n Ursprungszustand<br />
vor Beg<strong>in</strong>n <strong><strong>de</strong>r</strong> Transaktion wie<strong><strong>de</strong>r</strong> her. COMMIT dagegen been<strong>de</strong>t e<strong>in</strong>e Transaktion<br />
erfolgreich und schreibt die Än<strong><strong>de</strong>r</strong>ungen unwi<strong><strong>de</strong>r</strong>ruflich <strong>in</strong> die Datenbank.<br />
Betrachten wir hierzu wie<strong><strong>de</strong>r</strong> unser Fallbeispiel. Gehen wir davon aus, dass Herr Kle<strong>in</strong><br />
zunächst e<strong>in</strong>en Datensatz <strong>in</strong> die Tabelle Bestellung e<strong>in</strong>fügt und dann erst überprüft, ob<br />
freie Plätze vorhan<strong>de</strong>n s<strong>in</strong>d. Entsprechend gibt er folgen<strong>de</strong> SQL-Anweisungen e<strong>in</strong>:<br />
INSERT INTO Bestellung VALUES ( 9, '2002-02-18' , 3, NULL )<br />
SELECT *<br />
FROM Sitzplatz<br />
WHERE Vorstellungsnummer = 12<br />
AND Zustand = 'frei'<br />
-- wenn ke<strong>in</strong>e Plätze mehr frei s<strong>in</strong>d, Transaktion zurückführen<br />
ROLLBACK
ROLLBACK und COMMIT<br />
Wenn Herr Kle<strong>in</strong> feststellt, dass ke<strong>in</strong>e freien Plätze mehr vorhan<strong>de</strong>n s<strong>in</strong>d, muss er nicht<br />
überlegen, welche Än<strong><strong>de</strong>r</strong>ungen die bisherige Transaktion durchgeführt hat. Das<br />
RDBMS »merkt« sich alle Än<strong><strong>de</strong>r</strong>ungen e<strong>in</strong>er Transaktion und macht diese bei Erhalt<br />
<strong><strong>de</strong>r</strong> Anweisung ROLLBACK selbständig wie<strong><strong>de</strong>r</strong> rückgängig.<br />
S<strong>in</strong>d allerd<strong>in</strong>gs noch Plätze frei, so sieht das Ganze folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
INSERT INTO Bestellung VALUES ( 9, '2002-02-18' , 3, NULL )<br />
SELECT *<br />
FROM Sitzplatz<br />
WHERE Vorstellungsnummer = 12<br />
AND Zustand = 'frei'<br />
-- es s<strong>in</strong>d zwei Plätze frei<br />
UPDATE Sitzplatz<br />
SET Zustand = 'frei'<br />
WHERE Vorstellungsnummer = 12<br />
AND Artikelnummer IN (1202,1203)<br />
INSERT INTO Bestellposten VALUES ( 9, 1, 1202, 1 )<br />
INSERT INTO Bestellposten VALUES ( 9, 2, 1203, 1 )<br />
COMMIT<br />
Zunächst wird wie<strong><strong>de</strong>r</strong> die Bestellung e<strong>in</strong>gefügt und danach überprüft, ob freie Sitzplätze<br />
vorhan<strong>de</strong>n s<strong>in</strong>d. Da dies <strong><strong>de</strong>r</strong> Fall ist, wer<strong>de</strong>n die zwei Sitzplätze mit <strong><strong>de</strong>r</strong> Artikelnummer<br />
1202 und 1203 als »belegt« gekennzeichnet. Danach wer<strong>de</strong>n die bei<strong>de</strong>n Artikel<br />
<strong><strong>de</strong>r</strong> Bestellung als Bestellposten h<strong>in</strong>zugefügt. Die Transaktion ist damit erfolgreich<br />
been<strong>de</strong>t und kann über die SQL-Anweisung COMMIT endgültig <strong>in</strong> die Datenbank<br />
geschrieben wer<strong>de</strong>n.<br />
Was muss man aber nun tun, wenn <strong>in</strong>nerhalb e<strong>in</strong>er Transaktion z.B. <strong><strong>de</strong>r</strong> Strom ausfällt,<br />
muß man dann manuell Transaktionen zurückführen? Die Antwort darauf lautet e<strong>in</strong><strong>de</strong>utig<br />
»Ne<strong>in</strong>« , <strong>de</strong>nn schließlich wissen sie ja gar nicht, welche Transaktionen zum Zeitpunkt<br />
<strong>de</strong>s Stromausfalls gestartet waren, da ja mehrere Benutzer mit <strong><strong>de</strong>r</strong> Datenbank<br />
arbeiten. E<strong>in</strong> RDBMS protokolliert, welche Transaktionen es gibt und welche Än<strong><strong>de</strong>r</strong>ung<br />
je<strong>de</strong> Transaktion vornim<strong>mt</strong>. Erst wenn für e<strong>in</strong>e Transaktion e<strong>in</strong> COMMIT o<strong><strong>de</strong>r</strong><br />
ROLLBACK ausgeführt wird, wird die Transaktion als been<strong>de</strong>t angesehen. Bei e<strong>in</strong>em<br />
Stromausfall nun erkennt das RDBMS beim erneuten Starten eigenständig, welche<br />
Transaktionen vor <strong>de</strong>m Stromausfall aktiv waren und führt diese automatisch über e<strong>in</strong><br />
ROLLBACK zurück und überführt die Datenbank wie<strong><strong>de</strong>r</strong> <strong>in</strong> e<strong>in</strong>en konsistenten<br />
Zustand.<br />
185
11.4 SAVEPOINT<br />
186<br />
11 Transaktionen<br />
Da Transaktionen nicht explizit gestartet wer<strong>de</strong>n können, kann man sie natürlich auch<br />
nicht schachteln. Nun kom<strong>mt</strong> es aber häufig vor, dass Transaktionen aus sehr vielen<br />
SQL-Anweisungen bestehen. Die Folge ist, dass das RDBMS sehr viel protokollieren<br />
muss und e<strong>in</strong> COMMIT bzw. ROLLBACK dazu führt, dass sehr viele Än<strong><strong>de</strong>r</strong>ungen zu<br />
e<strong>in</strong>em bestim<strong>mt</strong>en Zeitpunkt geschrieben bzw. zurückgeführt wer<strong>de</strong>n müssen. Um<br />
dies zu vermei<strong>de</strong>n, führt SQL:1999 so genannte Savepo<strong>in</strong>ts e<strong>in</strong>. Savepo<strong>in</strong>ts dienen<br />
dazu, e<strong>in</strong>en Teil e<strong>in</strong>er Transaktion bereits vorzeitig wegzuschreiben bzw. zu e<strong>in</strong>em<br />
ganz bestim<strong>mt</strong>en Punkt e<strong>in</strong>er Transaktion zurückzuspr<strong>in</strong>gen. Savepo<strong>in</strong>ts wer<strong>de</strong>n mit<br />
<strong>de</strong>m Schlüsselwort SAVEPOINT angelegt. Betrachten wir hierzu wie<strong><strong>de</strong>r</strong> e<strong>in</strong> Beispiel.<br />
E<strong>in</strong> neuer Kun<strong>de</strong> ruft an und möchte <strong>de</strong>n Werbeartikel »Opernführer« bestellen. Dazu<br />
muss zunächst <strong><strong>de</strong>r</strong> Kun<strong>de</strong> <strong>in</strong> die entsprechen<strong>de</strong> Tabelle e<strong>in</strong>gefügt wer<strong>de</strong>n. Dann wird<br />
e<strong>in</strong> Datensatz <strong>in</strong> die Tabelle Bestellung geschrieben und überprüft, ob <strong><strong>de</strong>r</strong> Werbeartikel<br />
vorhan<strong>de</strong>n ist. Ist dies nicht <strong><strong>de</strong>r</strong> Fall, müsste die Transaktion normalerweise komplett<br />
zurückgeführt wer<strong>de</strong>n. Will <strong><strong>de</strong>r</strong> Kun<strong>de</strong> nun aber etwas an<strong><strong>de</strong>r</strong>es bestellen, so muss se<strong>in</strong><br />
Datensatz wie<strong><strong>de</strong>r</strong> vollständig neu erfasst wer<strong>de</strong>n. Um dies zu vermei<strong>de</strong>n, fügt man<br />
nach <strong>de</strong>m Anlegen <strong>de</strong>s Kun<strong>de</strong>n e<strong>in</strong>en Savepo<strong>in</strong>t e<strong>in</strong>, zu <strong>de</strong>m man über e<strong>in</strong> ROLLBACK<br />
zurückspr<strong>in</strong>gen kann.<br />
INSERT INTO Kun<strong>de</strong><br />
VALUES ( 5, 'Meyer', 'Michael', 'M', 'Menzelstr.', '108', 44444)<br />
SAVEPOINT bestellung_schreiben<br />
INSERT INTO Bestellung VALUES ( 9, '2002-02-18' , 3, NULL )<br />
SELECT NULLIF(Lagerbestand, 9999)<br />
FROM Werbeartikel<br />
WHERE Beschreibung LIKE 'Opernführer'<br />
-- Opernführer nicht auf Lager, also zurück zu<br />
-- bestellung_schreiben<br />
ROLLBACK TO SAVEPOINT bestellung_schreiben<br />
Will <strong><strong>de</strong>r</strong> Kun<strong>de</strong> ke<strong>in</strong>en an<strong><strong>de</strong>r</strong>en Artikel bestellen, so kann mit ROLLBACK die komplette<br />
Transaktion rückgängig gemacht wer<strong>de</strong>n:<br />
-- Opernführer nicht auf Lager, Kun<strong>de</strong> will nichts bestellen,<br />
-- also alles rückgängig machen, auch das Erfassen <strong>de</strong>s Kun<strong>de</strong>n<br />
ROLLBACK<br />
Abschließend sei darauf h<strong>in</strong>gewiesen, dass die meisten RDBMS-Produkte <strong>in</strong> <strong><strong>de</strong>r</strong> <strong>Praxis</strong><br />
nach je<strong><strong>de</strong>r</strong> SQL-Anweisung <strong>in</strong> <strong><strong>de</strong>r</strong> Regel automatisch e<strong>in</strong> COMMIT ausführen (häufig<br />
als Autocommit bezeichnet). D.h., je<strong>de</strong> Än<strong><strong>de</strong>r</strong>ung an <strong><strong>de</strong>r</strong> Datenbank wird sofort <strong>in</strong> die<br />
Datenbank geschrieben. Um <strong>in</strong> diesem Fall Transaktionen zu verwen<strong>de</strong>n, muss das<br />
Autocommit ausgeschaltet wer<strong>de</strong>n.
Mehrbenutzerbetrieb (»Concurreny Control«)<br />
11.5 Mehrbenutzerbetrieb<br />
(»Concurreny Control«)<br />
11.5.1 Grundlagen<br />
Bisher haben wir SQL-Anweisungen und Transaktionen immer nur so betrachtet, als<br />
wür<strong>de</strong>n wir alle<strong>in</strong>e mit <strong><strong>de</strong>r</strong> Datenbank arbeiten. In <strong><strong>de</strong>r</strong> Realität greifen <strong>in</strong> <strong><strong>de</strong>r</strong> Regel<br />
jedoch sehr viele Benutzer auf e<strong>in</strong>e Datenbank zu. Wenn zwei Benutzer zur gleichen<br />
Zeit mit <strong>de</strong>n gleichen Daten arbeiten und diese verän<strong><strong>de</strong>r</strong>n, können Probleme auftreten.<br />
Wir wollen uns im Folgen<strong>de</strong>n vier solcher Probleme ansehen.<br />
11.5.2 »Lost Update«<br />
Betrachten wir zunächst wie<strong><strong>de</strong>r</strong> unser Fallbeispiel. Herr Kle<strong>in</strong> nim<strong>mt</strong> gera<strong>de</strong> e<strong>in</strong>e<br />
Bestellung für <strong>de</strong>n Werbeartikel mit <strong><strong>de</strong>r</strong> Nummer 1001 entgegen. Zunächst stellt er fest,<br />
dass <strong><strong>de</strong>r</strong> Werbeartikel noch 26 mal auf Lager liegt. Der Kun<strong>de</strong> bestellt diesen Artikel<br />
dreimal, entsprechend korrigiert er <strong>de</strong>n Lagerbestand.<br />
Zur gleichen Zeit erhält <strong><strong>de</strong>r</strong> E<strong>in</strong>kauf diesen Artikel 10 mal neu, br<strong>in</strong>gt ihn auf Lager<br />
und benachrichtigt Frau Kart. Diese trägt <strong>de</strong>n Lagerbestand neu e<strong>in</strong>. Betrachten wir<br />
e<strong>in</strong>mal <strong>de</strong>n Ablauf:<br />
Herr Kle<strong>in</strong> Frau Kart<br />
Lies Lagerbestand<br />
Werbeartikel 1001<br />
= 26<br />
Verm<strong>in</strong><strong><strong>de</strong>r</strong>e Lagerbestand<br />
Werbeartikel 1001 um 3<br />
= 23<br />
Lies Lagerbestand<br />
Werbeartikel 1001<br />
= 26<br />
Erhöhe Lagerbestand<br />
Werbeartikel 1001 um 10<br />
= 36<br />
Abbildung 11.1: »Lost Update«-Problem<br />
Zuerst liest Herr Kle<strong>in</strong> und danach Frau Kart <strong>de</strong>n Lagerbestand. Herr Kle<strong>in</strong> än<strong><strong>de</strong>r</strong>t <strong>de</strong>n<br />
Datenbestand auf 23. Frau Kart bekom<strong>mt</strong> davon nichts mit, da sie <strong>de</strong>n Lagerbestand ja<br />
schon vorher gelesen hat und erhöht ihn auf 36.<br />
187
188<br />
11 Transaktionen<br />
Die Än<strong><strong>de</strong>r</strong>ung von Herrn Kle<strong>in</strong> geht verloren, da diese von <strong><strong>de</strong>r</strong> Än<strong><strong>de</strong>r</strong>ung durch Frau<br />
Kart überschrieben wird. Dieses Problem wird <strong>de</strong>shalb als »Lost Update« -Problem<br />
bezeichnet.<br />
11.5.3 »Dirty Read«<br />
Das zweite Problem besteht dar<strong>in</strong>, dass zunächst zwei Benutzer die gleichen Daten<br />
lesen und anschließend e<strong>in</strong> Benutzer die Daten än<strong><strong>de</strong>r</strong>t. Betrachten wir hierzu wie<strong><strong>de</strong>r</strong><br />
unser Beispiel. Herr Kle<strong>in</strong> hat <strong>de</strong>n Werbeartikel mit <strong><strong>de</strong>r</strong> Nummer 1001 gelesen und<br />
danach <strong>de</strong>n Lagerbestand entsprechend <strong><strong>de</strong>r</strong> Bestellung auf 23 angepasst. Zur gleichen<br />
Zeit erstellt Frau Kart e<strong>in</strong>e Lagerliste mit <strong>de</strong>n Bestän<strong>de</strong>n <strong><strong>de</strong>r</strong> Werbeartikel:<br />
Zunächst lesen bei<strong>de</strong> Benutzer <strong>de</strong>n Lagerbestand. Dann än<strong><strong>de</strong>r</strong>t Herr Kle<strong>in</strong> <strong>de</strong>n Lagerbestand<br />
und Frau Kart bekom<strong>mt</strong> davon nichts mit. Die Lagerliste enthält fälschlicherweise<br />
e<strong>in</strong>en Lagerbestand von 26 anstatt korrekterweise 23.<br />
11.5.4 »Non-repeatable Read«<br />
Herr Kle<strong>in</strong> Frau Kart<br />
Lies Lagerbestand<br />
Werbeartikel 1001<br />
= 26<br />
Verm<strong>in</strong><strong><strong>de</strong>r</strong>e Lagerbestand<br />
Werbeartikel 1001 um 3<br />
= 23<br />
Lies Lagerbestand<br />
Werbeartikel 1001<br />
= 26<br />
Abbildung 11.2: »Dirty Read« -Problem<br />
Das dritte Problem behan<strong>de</strong>lt das erneute Lesen von Daten. Angenommen Herr Kle<strong>in</strong><br />
liest <strong>de</strong>n Lagerbestand und än<strong><strong>de</strong>r</strong>t ihn danach auf 23. Zur gleichen Zeit liest Frau Kart<br />
<strong>de</strong>n Lagerbestand zunächst, um nachzusehen, ob von diesem Artikel genug auf Lager<br />
ist. Da <strong><strong>de</strong>r</strong> Lagerbestand über 25 liegt, bestellt sie nicht neu. Danach liest sie <strong>de</strong>n Lagerbestand<br />
erneut, um e<strong>in</strong>e Lagerliste auszudrucken. Dieses mal erhält sie jedoch e<strong>in</strong>en<br />
an<strong><strong>de</strong>r</strong>en Wert für <strong>de</strong>n Lagerbestand.
11.5.5 »Phantom Read«<br />
Mehrbenutzerbetrieb (»Concurreny Control«)<br />
Herr Kle<strong>in</strong> Frau Kart<br />
Lies Lagerbestand<br />
Werbeartikel 1001<br />
= 26<br />
Verm<strong>in</strong><strong><strong>de</strong>r</strong>e Lagerbestand<br />
Werbeartikel 1001 um 3<br />
= 23<br />
Lies Lagerbestand<br />
Werbeartikel 1001<br />
= ��<br />
Lies Lagerbestand<br />
Werbeartikel 1001<br />
= ��<br />
Abbildung 11.3: »Non-repeatable Read« -Problem<br />
Das vierte und letzte Problem beschäftigt sich mit unterschiedlichen Ergebnistabellen,<br />
obgleich je<strong>de</strong>smal die gleiche Abfrage ausgeführt wird. Betrachten wir hierzu wie<strong><strong>de</strong>r</strong><br />
e<strong>in</strong> Beispiel: Frau Kart erstellt e<strong>in</strong>e Liste aller Werbeartikel. Gleichzeitig löscht <strong><strong>de</strong>r</strong><br />
Geschäftsführer aus dieser Tabelle Werbeartikel, die nicht so oft verkauft wur<strong>de</strong>n.<br />
Erstellt Frau Kart danach noch e<strong>in</strong>mal die Liste, so fehlen Datensätze, die vorher noch<br />
<strong>in</strong> <strong><strong>de</strong>r</strong> Ergebnistabelle zurückgeliefert wur<strong>de</strong>n:<br />
Herr Kowalski Frau Kart<br />
Lies Werbeartikel<br />
Löschen Werbeartikel 1003<br />
und 1077<br />
Lies Werbeartikel<br />
Lies Werbeartikel<br />
Abbildung 11.4: »Phantom Read« -Problem<br />
189
11.5.6 Isolationslevel<br />
190<br />
11 Transaktionen<br />
Alle gera<strong>de</strong> beschriebenen Probleme müssen natürlich nicht als gegeben h<strong>in</strong>genommen<br />
wer<strong>de</strong>n, son<strong><strong>de</strong>r</strong>n wer<strong>de</strong>n automatisch vom RDBMS berücksichtigt. So muss man<br />
nicht dafür sorgen, dass e<strong>in</strong>e bestim<strong>mt</strong>e Tabelle exklusiv für e<strong>in</strong>en gesperrt ist, das<br />
RDBMS führt dies automatisch für e<strong>in</strong>e Transaktion durch.<br />
Dennoch können mit SQL bestim<strong>mt</strong>e Probleme zugelassen wer<strong>de</strong>n. Betrachten wir<br />
hierzu wie<strong><strong>de</strong>r</strong> unser Beispiel: Wenn Frau Kart e<strong>in</strong>e Liste aller Werbartikel erstellen<br />
möchte, so ist es nicht <strong>in</strong> je<strong>de</strong>m Fall unbed<strong>in</strong>gt notwendig, dass diese zeitgenau aktuell<br />
ist. Es ist also nicht schlimm, wenn »Dirty Read« -, »Non-repeatable Read« und »Phantom<br />
Read« -Probleme vorkommen.<br />
Wenn mehrere Benutzer gleichzeitig auf Daten zugreifen und das RDBMS das Ganze<br />
so koord<strong>in</strong>ieren muss, dass die aufgeführten Probleme nicht auftreten, so kostet das<br />
Ressourcen und Abfragen erfolgen für die Benutzer natürlich langsamer. Läßt man nun<br />
bei bestim<strong>mt</strong>en Transaktionen bestim<strong>mt</strong>e Probleme zu, so kann sich das RDBMS auf<br />
an<strong><strong>de</strong>r</strong>e D<strong>in</strong>ge »konzentrieren« und Abfragen können schneller abgewickelt wer<strong>de</strong>n.<br />
Um explizit Probleme zuzulassen, kennt SQL die SET TRANSACTION-Anweisung.<br />
Sie erlaubt, <strong>de</strong>n Isolationslevel e<strong>in</strong>er Transaktion e<strong>in</strong>zustellen. E<strong>in</strong>er <strong><strong>de</strong>r</strong> folgen<strong>de</strong>n<br />
Schlüsselwörter ist möglich:<br />
� READ UNCOMMITTED<br />
� READ COMMITTED<br />
� REPEATABLE READ<br />
� SERIALIZABLE<br />
Die folgen<strong>de</strong> Tabelle gibt Auskunft darüber, welchen Isolationslevel man e<strong>in</strong>stellen<br />
muß, um bestim<strong>mt</strong>e Probleme zuzulassen. SERIALIZABLE entspricht dabei <strong><strong>de</strong>r</strong> Standar<strong>de</strong><strong>in</strong>stellung<br />
und verh<strong>in</strong><strong><strong>de</strong>r</strong>t alle aufgeführten Probleme.<br />
Isolationslevel »Dirty Read« »Non-Repeatable<br />
Read«<br />
READ UNCOMMITED Ja Ja Ja<br />
READ COMMITTED Ne<strong>in</strong> Ja Ja<br />
REPEATABLE READ Ne<strong>in</strong> Ne<strong>in</strong> Ja<br />
SERIALIZABLE Ne<strong>in</strong> Ne<strong>in</strong> Ne<strong>in</strong><br />
Um alle Probleme für e<strong>in</strong>e Transaktion zuzulassen, schreibt man <strong>in</strong> SQL vor Beg<strong>in</strong>n <strong><strong>de</strong>r</strong><br />
Transaktion:<br />
SET TRANSACTION READ UNCOMMITED<br />
Tabelle 11.1: Isolationslevel<br />
»Phantom<br />
Read«
Zusammenfassung<br />
11.6 Zusammenfassung<br />
In diesem Kapitel haben wir gesehen, wie man mehrere SQL-Anweisungen zu e<strong>in</strong>er<br />
E<strong>in</strong>heit, e<strong>in</strong>er so genannten Transaktion, zusammenfasst. Die SQL-Anweisungen e<strong>in</strong>er<br />
Transaktion wer<strong>de</strong>n entwe<strong><strong>de</strong>r</strong> vollständig o<strong><strong>de</strong>r</strong> gar nicht ausgeführt. Um e<strong>in</strong>e Transaktion<br />
wie<strong><strong>de</strong>r</strong> zurückzuführen zu <strong>de</strong>m Zustand vor Beg<strong>in</strong>n <strong><strong>de</strong>r</strong> Transaktion, verwen<strong>de</strong>t<br />
man die SQL-Anweisung ROLLBACK. Um die Än<strong><strong>de</strong>r</strong>ungen e<strong>in</strong>er Transaktion endgültig<br />
<strong>in</strong> die Datenbank zu schreiben, verwen<strong>de</strong>t man die SQL-Anweisung COMMIT.<br />
Um größere Transaktionen e<strong>in</strong>facher handhabbar zu machen, kann man so genannte<br />
»Savepo<strong>in</strong>ts« <strong>de</strong>f<strong>in</strong>ieren, zu <strong>de</strong>nen über e<strong>in</strong> ROLLBACK »zurückgesprungen« wer<strong>de</strong>n<br />
kann.<br />
Durch <strong>de</strong>n Mehrbenutzerbetrieb können verschie<strong>de</strong>ne Probleme auftreten. Diese Probleme<br />
wer<strong>de</strong>n jedoch weitestgehend vom RDBMS selbständig behoben. Dafür benötigt<br />
das RDBMS allerd<strong>in</strong>gs Ressourcen, wodurch Abfragen an<strong><strong>de</strong>r</strong>er Benutzer dann durchaus<br />
langsamer ausgeführt wer<strong>de</strong>n. Um das RDBMS zu entlasten, können bestim<strong>mt</strong>e<br />
Probleme für bestim<strong>mt</strong>e Transaktionen wie<strong><strong>de</strong>r</strong> zugelassen wer<strong>de</strong>n.<br />
11.7 Aufgaben<br />
Wie<strong><strong>de</strong>r</strong>holungsfragen<br />
1) Welche Eigenschaften muss e<strong>in</strong>e Transaktion besitzen?<br />
2) Wie wer<strong>de</strong>n die Än<strong><strong>de</strong>r</strong>ungen e<strong>in</strong>er Transaktion wie<strong><strong>de</strong>r</strong> rückgängig gemacht?<br />
3) Wie wer<strong>de</strong>n die Än<strong><strong>de</strong>r</strong>ungen e<strong>in</strong>er Transaktion endgültig <strong>in</strong> die Datenbank<br />
geschrieben?<br />
4) Was s<strong>in</strong>d »Savepo<strong>in</strong>ts« ?<br />
Übungen<br />
1) Gegeben sei e<strong>in</strong>e leere Tabelle »Person« mit <strong>de</strong>n Spalten »Name« , »Vorname« ,<br />
»Alter« . Welchen Inhalt hat diese Tabelle nach<strong>de</strong>m folgen<strong>de</strong> SQL-Anweisungen<br />
ausgeführt wur<strong>de</strong>n?<br />
INSERT INTO Person VALUES ( 'Muster', 'Hans', 63 )<br />
INSERT INTO Person VALUES ( 'Carlson', 'Peter', 26 )<br />
INSERT INTO Person VALUES ( 'Friedrichs', 'Frieda', 12 )<br />
ROLLBACK<br />
2) Welchen Inhalt hat diese Tabelle, nach<strong>de</strong>m folgen<strong>de</strong> SQL-Anweisungen ausgeführt<br />
wur<strong>de</strong>n?<br />
INSERT INTO Person VALUES ( 'Muster', 'Hans', 63 )<br />
INSERT INTO Person VALUES ( 'Carlson', 'Peter', 26 )<br />
INSERT INTO Person VALUES ( 'Friedrichs', 'Frieda', 12 )<br />
COMMIT<br />
191
192<br />
11 Transaktionen<br />
3) Welchen Inhalt hat diese Tabelle, nach<strong>de</strong>m folgen<strong>de</strong> SQL-Anweisungen ausgeführt<br />
wur<strong>de</strong>n?<br />
INSERT INTO Person VALUES ( 'Muster', 'Hans', 63 )<br />
SAVEPOINT sp1<br />
INSERT INTO Person VALUES ( 'Carlson', 'Peter', 26 )<br />
INSERT INTO Person VALUES ( 'Friedrichs', 'Frieda', 12 )<br />
ROLLBACK TO sp1<br />
4) Welchen Inhalt hat diese Tabelle, nach<strong>de</strong>m folgen<strong>de</strong> SQL-Anweisungen ausgeführt<br />
wur<strong>de</strong>n?<br />
INSERT INTO Person VALUES ( 'Muster', 'Hans', 63 )<br />
SAVEPOINT sp1<br />
INSERT INTO Person VALUES ( 'Carlson', 'Peter', 26 )<br />
INSERT INTO Person VALUES ( 'Friedrichs', 'Frieda', 12 )<br />
ROLLBACK
12<br />
»Stored Procedures« und<br />
»Prozedurale<br />
Sprachelemente«<br />
In Kapitel 12 sollen folgen<strong>de</strong> Fragen geklärt wer<strong>de</strong>n:<br />
� Wie kann man mehrere Anweisungen unter e<strong>in</strong>em Namen zusammenfassen und <strong>in</strong><br />
e<strong>in</strong>em Schritt ausführen lassen?<br />
� Was s<strong>in</strong>d prozedurale Sprachelemente?<br />
� Was s<strong>in</strong>d gespeicherte Prozeduren (»Stored Procedures«)?<br />
� Was s<strong>in</strong>d Funktionen und Prozeduren?<br />
� Was s<strong>in</strong>d Variablen?<br />
� Welche prozeduralen Anweisungen kennt SQL zur Steuerung <strong>de</strong>s Programmablaufs?<br />
12.1 Motivation<br />
Täglich erfassen Herr Kle<strong>in</strong> und Frau Kart neue Bestellungen, <strong>in</strong><strong>de</strong>m sie e<strong>in</strong>zelne SQL-<br />
Anweisungen e<strong>in</strong>geben, um Datensätze <strong>in</strong> die Tabellen »Bestellung«, »Bestellposten«<br />
und »Kun<strong>de</strong>« e<strong>in</strong>zufügen. Das ersche<strong>in</strong>t Frau Kart zu Recht sehr umständlich, also ruft<br />
sie Herrn Fleissig von <strong><strong>de</strong>r</strong> Unternehmensberatung an und schil<strong><strong>de</strong>r</strong>t ihr Problem.<br />
Herr Fleissig erzählt ihr, dass man mehrere SQL-Anweisungen auf <strong>de</strong>m Datenbankserver<br />
unter e<strong>in</strong>em selbst<strong>de</strong>f<strong>in</strong>ierten Namen <strong>in</strong> e<strong>in</strong>er Rout<strong>in</strong>e speichern kann. Über <strong>de</strong>n<br />
Namen <strong><strong>de</strong>r</strong> Rout<strong>in</strong>e kann man dann die Folge von SQL-Anweisungen <strong>in</strong> e<strong>in</strong>em Schritt<br />
ausführen. Mit Rout<strong>in</strong>en kann man aber noch viel mehr machen, da SQL auch prozedurale<br />
Sprachelemente enthält, die e<strong>in</strong>er vollständigen Programmiersprache entsprechen.<br />
Er empfiehlt Frau Kart, e<strong>in</strong>e Rout<strong>in</strong>e mit <strong>de</strong>m Namen »ErfasseBestellung« zu erstellen.<br />
Dieser Rout<strong>in</strong>e kann sie dann die Werte e<strong>in</strong>er Bestellung übergeben.<br />
12.2 Rout<strong>in</strong>en<br />
Bisher haben wir SQL als re<strong>in</strong> <strong>de</strong>klarative (beschreiben<strong>de</strong>) Programmiersprache kennen<br />
gelernt, d.h. man beschreibt, was man als Ergebnis vom RDBMS erhalten möchte.<br />
In Kapitel 8 wur<strong>de</strong> auch schon kurz erwähnt, dass SQL prozedurale Sprachelemente<br />
enthält. Prozedurale Sprachelemente dienen dazu, <strong>de</strong>m RDBMS zu beschreiben, wie<br />
e<strong>in</strong> gewünschtes Ergebnis schrittweise bearbeitet wird. Folgen von prozeduralen SQL-<br />
Anweisungen s<strong>in</strong>d zwar schwieriger zu programmieren, da man <strong>de</strong>m RDBMS je<strong>de</strong>n<br />
e<strong>in</strong>zelnen Arbeitsschritt vorgeben muss, dafür ist man mit prozeduralen SQL-Anwei-<br />
193
194<br />
12 »Stored Procedures« und »Prozedurale Sprachelemente«<br />
sungen wesentlich flexibler als mit re<strong>in</strong> <strong>de</strong>klarativen Sprachelementen. Gera<strong>de</strong> die<br />
Komb<strong>in</strong>ation bei SQL von <strong>de</strong>klarativen und prozeduralen Sprachelementen macht <strong>de</strong>ssen<br />
Leistungsfähigkeit aus. In diesem Kapitel wer<strong>de</strong>n wir uns mit <strong>de</strong>n prozeduralen<br />
Sprachelementen beschäftigen. Das Kapitel soll lediglich als E<strong>in</strong>führung dienen, um<br />
e<strong>in</strong>en Überblick zu erhalten, was mit prozeduralen Sprachelementen machbar ist.<br />
Bevor wir uns jedoch mit <strong>de</strong>n prozeduralen Sprachelementen beschäftigen, müssen<br />
zunächst die Begriffe Funktion, Prozedur und Variable geklärt wer<strong>de</strong>n. Folgen von<br />
SQL-Anweisungen kann man unter e<strong>in</strong>em geme<strong>in</strong>samen Namen speichern und über<br />
diesen Namen wie<strong><strong>de</strong>r</strong> aufrufen. Diese Folgen von SQL-Anweisungen wer<strong>de</strong>n als Rout<strong>in</strong>e<br />
bezeichnet. Bei Rout<strong>in</strong>en unterschei<strong>de</strong>t man <strong>in</strong> SQL zwischen Funktionen und Prozeduren.<br />
Betrachten wir zunächst e<strong>in</strong> Beispiel für e<strong>in</strong>e gespeicherte Prozedur, die alle<br />
Werbeartikel ausgeben soll, die über 20,-- Eur kosten. Die SELECT-Anweisung dazu ist<br />
für uns ke<strong>in</strong> Problem mehr, sie lautet:<br />
SELECT *<br />
FROM Werbeartikel<br />
WHERE Preis > 20.00<br />
Um nun nicht je<strong>de</strong>smal die komplette SELECT-Anweisung zur Ermittlung e<strong>in</strong>er Liste<br />
dieser Werbeartikel e<strong>in</strong>geben zu müssen, wird e<strong>in</strong>e Prozedur mit <strong>de</strong>m Namen »Lies-<br />
Werbeartikel« erstellt. Dies erfolgt über die SQL-Anweisung CREATE PROCEDURE:<br />
CREATE PROCEDURE LiesWerbeartikel ()<br />
SELECT *<br />
FROM Werbeartikel<br />
WHERE Preis > 20.00;<br />
Nun kann über die SQL-Anweisung CALL die Prozedur wie folgt wie<strong><strong>de</strong>r</strong> aufgerufen<br />
wer<strong>de</strong>n und man erhält das gleiche Ergebnis, als wenn die dazugehörige SELECT-<br />
Anweisung e<strong>in</strong>gegeben wor<strong>de</strong>n wäre:<br />
CALL LiesWerbeartikel<br />
Jetzt wäre es natürlich komfortabel, wenn wir e<strong>in</strong>en Schwellwert für <strong>de</strong>n Preis an die<br />
Prozedur übergeben könnten, damit nicht immer nur alle Artikel über 20,-- Eur ausgegeben<br />
wer<strong>de</strong>n. Man kann <strong>de</strong>shalb Werte, sogenannte Parameter, an e<strong>in</strong>e Prozedur<br />
übergeben. Für <strong>de</strong>n Parameter »PreisSchwellwert« muss die Prozedur wie folgt geän<strong><strong>de</strong>r</strong>t<br />
wer<strong>de</strong>n:<br />
CREATE PROCEDURE LiesWerbeartikel(PreisSchwellwert DECIMAL(8,2))<br />
SELECT *<br />
FROM Werbeartikel<br />
WHERE Preis > PreisSchwellwert;<br />
Bevor die Prozedur jedoch erneut angelegt wer<strong>de</strong>n kann, muss diese vorher natürlich<br />
gelöscht wer<strong>de</strong>n. Dies erfolgt über die SQL-Anweisung DROP PROCEDURE. Um also<br />
die Prozedur zu löschen, schreibt man e<strong>in</strong>fach:<br />
DROP PROCEDURE LiesWerbeartikel
Rout<strong>in</strong>en<br />
Unser bisheriges Beispiel war sehr e<strong>in</strong>fach. Damit wir kompliziertere Abfragen schrittweise<br />
bearbeiten können, müssen wir <strong>de</strong>n Begriff Variable verstehen. E<strong>in</strong>e Variable ist <strong>in</strong><br />
e<strong>in</strong>er Programmiersprache e<strong>in</strong> Platzhalter für e<strong>in</strong>en Wert, auf <strong>de</strong>n man über e<strong>in</strong>en Namen<br />
zugreifen kann. Diesem Namen bzw. dieser Variablen kann man je nach Bedarf beliebige<br />
Werte zuweisen. E<strong>in</strong>e Variable haben wir eben bereits bei <strong><strong>de</strong>r</strong> Prozedur »LiesWerbeartikel«<br />
kennen gelernt: »PreisSchwellwert« . Dieser Parameter kann beliebige Zahlen speichern,<br />
die aus maximal 8 Stellen mit 2 Nachkommastellen bestehen. E<strong>in</strong>e Variable hat also<br />
e<strong>in</strong>en bestim<strong>mt</strong>en Datentyp und damit auch e<strong>in</strong>en bestim<strong>mt</strong>en Wertebereich. Um explizit<br />
e<strong>in</strong>e Variable anzulegen, verwen<strong>de</strong>t man die SQL-Anweisung DECLARE. Um z.B. <strong>in</strong><br />
e<strong>in</strong>er Prozedur <strong>de</strong>n Durchschnittspreis e<strong>in</strong>es Werbeartikels zu ermitteln und diesen <strong>in</strong><br />
e<strong>in</strong>er Variablen zu speichern, kann man <strong>in</strong> zwei Schritten vorgehen:<br />
CREATE PROCEDURE ErmittleDurchschnitt ()<br />
DECLARE durchschnitt DECIMAL(8,2);<br />
SELECT AVG(Preis) INTO durchschnitt<br />
FROM Werbeartikel;<br />
SELECT durchschnitt;<br />
Zunächst wird die Variable »durchschnitt« <strong>de</strong>klariert, danach die SELECT-Anweisung<br />
zum Ermitteln <strong>de</strong>s Durchschnittspreises aufgerufen und über das Schlüsselwort INTO<br />
<strong>in</strong> <strong><strong>de</strong>r</strong> Variablen »durchschnitt« gespeichert. Danach kann über die SQL-Anweisung<br />
SELECT die Variable ausgegeben wer<strong>de</strong>n.<br />
Soll <strong><strong>de</strong>r</strong> Durchschnittswert nach Aufruf <strong><strong>de</strong>r</strong> Prozedur weiterverwen<strong>de</strong>t wer<strong>de</strong>n, können<br />
Parameter als Outputparameter <strong>de</strong>klariert wer<strong>de</strong>n, <strong>in</strong> die <strong><strong>de</strong>r</strong> Wert dann zurückgeben<br />
wird. Das Ganze könnte folgen<strong><strong>de</strong>r</strong>maßen aussehen:<br />
CREATE PROCEDURE ErmittleDurchschnitt(OUT rueckgabe DECIMAL(8,2))<br />
DECLARE durchschnitt DECIMAL(8,2);<br />
SELECT AVG(Preis) INTO durchschnitt<br />
FROM Werbeartikel;<br />
SET rueckgabe = durchschnitt;<br />
Vor <strong><strong>de</strong>r</strong> Angabe <strong>de</strong>s Übergabeparameters »rueckgabe« gibt man über das Schlüsselwort<br />
OUT bekannt, dass dieser Parameter <strong>in</strong> <strong><strong>de</strong>r</strong> Prozedur e<strong>in</strong>en Wert zugewiesen bekom<strong>mt</strong>,<br />
<strong>de</strong>n man nach <strong><strong>de</strong>r</strong> Ausführung weiterverwen<strong>de</strong>n möchte. Standardmäßig s<strong>in</strong>d Übergabeparameter<br />
mit <strong>de</strong>m Schlüsselwort IN festgelegt, übergeben also e<strong>in</strong>en Wert an die<br />
Prozedur. In diesem Fall steht IN als Abkürzung für Input. E<strong>in</strong> Übergabeparameter<br />
kann sowohl e<strong>in</strong>en Wert an e<strong>in</strong>e Prozedur übergeben als auch e<strong>in</strong>en Wert als Ausgabeparameter<br />
speichern. Er muss dann mit <strong>de</strong>m Schlüsselwort INOUT <strong>de</strong>klariert wer<strong>de</strong>n.<br />
Wird bei e<strong>in</strong>em Übergabeparameter we<strong><strong>de</strong>r</strong> IN, OUT noch INOUT angegeben, so han<strong>de</strong>lt<br />
es sich standardmäßig um e<strong>in</strong>en E<strong>in</strong>gabeparameter (IN). Doch wie ruft man nun<br />
die Prozedur auf? Zuerst <strong>de</strong>klariert man e<strong>in</strong>e Variable, die nach Aufruf <strong><strong>de</strong>r</strong> Prozedur<br />
<strong>de</strong>n Durchschnittspreis enthalten soll. Diese Variable übergibt man dann an die Prozedur<br />
»ErmittleDurchschnitt« und erhält danach <strong>in</strong> ihr <strong>de</strong>n Durchschnittspreis zurück:<br />
195
196<br />
12 »Stored Procedures« und »Prozedurale Sprachelemente«<br />
DECLARE zahl DECIMAL(8,2);<br />
CALL ErmittleDurchschnitt (zahl);<br />
SELECT 'Durchschnittspreis für Werbeartikel: ' || zahl;<br />
Bisher haben wir gesehen, wie man Prozeduren anlegt, die auf <strong>de</strong>m Datenbankserver<br />
gespeichert wer<strong>de</strong>n und wie man Werte als Parameter an die Prozedur übergibt. Dabei<br />
können Parameter nur Werte an die Prozedur übergeben (IN), zurückliefern (OUT)<br />
o<strong><strong>de</strong>r</strong> bei<strong>de</strong>s (INOUT). Aufgerufen wer<strong>de</strong>n gespeicherte Prozeduren über die SQL-<br />
Anweisung CALL.<br />
Am Anfang dieses Abschnitts haben wir erfahren, dass es neben Prozeduren auch Funktionen<br />
gibt. Funktionen s<strong>in</strong>d weitgehend i<strong>de</strong>ntisch mit Prozeduren, liefern jedoch immer<br />
e<strong>in</strong>en skalaren Wert zurück. Wir haben <strong>in</strong> Kapitel 8 bereits vor<strong>de</strong>f<strong>in</strong>ierte Funktionen wie<br />
TRIM, SUBSTRING o<strong><strong>de</strong>r</strong> ABS kennen gelernt. Funktionen kann man auch selbst über<br />
die SQL-Anweisung CREATE FUNCTION erzeugen und über DROP FUNCTION wie<strong><strong>de</strong>r</strong><br />
löschen. Im Gegensatz zur Prozedur wird bei e<strong>in</strong>er Funktion zusätzlich angegeben,<br />
welchen Datentyp <strong><strong>de</strong>r</strong> zurückgegebene Wert hat. Betrachten wir dazu, wie e<strong>in</strong>e Funktion<br />
aussieht, die <strong>de</strong>n Durchschnittspreis für Werbeartikel zurückliefert:<br />
CREATE FUNCTION ErmittleDurchschnittspreis() RETURNS<br />
DECIMAL(8,2)<br />
RETURN (SELECT AVG(Preis) FROM Werbeartikel);<br />
H<strong>in</strong>ter CREATE FUNCTION folgt <strong><strong>de</strong>r</strong> Name <strong><strong>de</strong>r</strong> Funktion und danach das Schlüsselwort<br />
RETURNS, das angibt, von welchem Datentyp <strong><strong>de</strong>r</strong> zurückgelieferte Wert ist.<br />
Anschließend wird die SELECT-Anweisung zum Ermitteln <strong>de</strong>s Durchschnittspreises<br />
aufgerufen und über die SQL-Anweisung RETURN zurückgegeben. Je<strong>de</strong> Funktion <strong>in</strong><br />
SQL muss mit <strong><strong>de</strong>r</strong> SQL-Anweisung RETURN e<strong>in</strong>en Wert <strong>de</strong>s angegebenen Datentyps<br />
zurückgeben.<br />
Funktionen wer<strong>de</strong>n nicht wie Prozeduren mit <strong>de</strong>m Schlüsselwort CALL aufgerufen,<br />
son<strong><strong>de</strong>r</strong>n können <strong>in</strong>nerhalb von Anweisungen direkt verwen<strong>de</strong>t wer<strong>de</strong>n.<br />
Um nun z.B. alle Werbeartikel und <strong>in</strong> je<strong><strong>de</strong>r</strong> Zeile gleichzeitig <strong>de</strong>n Durchschnittspreis<br />
mit auszugeben, kann man schreiben:<br />
SELECT ErmittleDurchschnittspreis() AS 'Durchschnitt',<br />
Beschreibung, Lagerbestand, Preis<br />
FROM Werbeartikel<br />
Durchschnitt Beschreibung Lagerbestand Preis<br />
------------ ------------------------ ------------ -----<br />
33.08 Noten f. Klavier 26 89.00<br />
33.08 T-Shirt Farbe: rot 11 29.99<br />
33.08 Phil Coll<strong>in</strong>s <strong>in</strong> Concert 21 20.00<br />
33.08 Plakat mit Musical-Katzen 89 33.50<br />
33.08 Opernführer 9999 19.99<br />
33.08 Schwarzer Zauberstock 32 5.99
Sprachelemente zur Kontrollsteuerung<br />
Das Beispiel läßt erahnen, wie leistungsfähig Funktionen und Prozeduren s<strong>in</strong>d. Das<br />
gleiche Ergebnis mit e<strong>in</strong>er e<strong>in</strong>zigen SELECT-Anweisung wäre so nicht ohne weiteres<br />
möglich. Wir wissen nun, was Funktionen und Prozeduren s<strong>in</strong>d.<br />
Im Folgen<strong>de</strong>n wollen wir sehen, wie man prozedurale Sprachelemente verwen<strong>de</strong>n<br />
kann, um leistungsfähige und wie<strong><strong>de</strong>r</strong>verwendbare Rout<strong>in</strong>en zu schreiben. Zunächst<br />
wer<strong>de</strong>n alle prozeduralen Sprachelemente vorgestellt. Am Schluss dieses Kapitels wird<br />
dann e<strong>in</strong>e etwas komplexere Funktion programmiert, <strong>in</strong> <strong><strong>de</strong>r</strong> diese Sprachelemente<br />
angewen<strong>de</strong>t wer<strong>de</strong>n.<br />
12.3 Sprachelemente zur Kontrollsteuerung<br />
Bisher haben wir nur SQL-Anweisungen kennen gelernt, die sequenziell, also immer<br />
nach <strong><strong>de</strong>r</strong> gleichen Reihenfolge abgearbeitet wur<strong>de</strong>n. Über Sprachelemente zur Kontrollsteuerung<br />
kann die Abarbeitung <strong><strong>de</strong>r</strong> e<strong>in</strong>zelnen Anweisungen gesteuert wer<strong>de</strong>n.<br />
12.3.1 BEGIN...END<br />
In unserem letzten Beispiel haben wir <strong>in</strong> <strong><strong>de</strong>r</strong> Funktion nur e<strong>in</strong>e e<strong>in</strong>zige SQL-Anweisung<br />
ausgeführt. Über die Schlüsselwörter BEGIN...END können mehrere SQL-Anweisungen<br />
zusammengefasst wer<strong>de</strong>n.<br />
Die Funktion »ErmittleDurchschnittspreis« kann man dann auch wie folgt schreiben:<br />
CREATE FUNCTION ErmittleDurchschnittspreis() RETURNS<br />
DECIMAL(8,2)<br />
BEGIN<br />
DECLARE durchschnitt DECIMAL(8,2);<br />
END<br />
Rout<strong>in</strong>e<br />
Rout<strong>in</strong>e<br />
����������������� ��� ���� �����<br />
����������������� ��� ���� �����<br />
Funktionen<br />
Funktionen<br />
��� �����������������<br />
��� �����������������<br />
Prozedur<br />
Prozedur<br />
���� �����������������<br />
���� �����������������<br />
��� ���� ��������<br />
��� ���� ��������<br />
Abbildung 12.1: Funktionen und Prozeduren<br />
SELECT AVG(Preis) INTO durchschnitt FROM Werbeartikel;<br />
RETURN (durchschnitt);<br />
Zunächst wird <strong>in</strong> <strong><strong>de</strong>r</strong> Funktion e<strong>in</strong>e Variable <strong>de</strong>klariert, <strong>in</strong> <strong><strong>de</strong>r</strong> <strong><strong>de</strong>r</strong> Durchschnittspreis<br />
gespeichert wer<strong>de</strong>n soll. Dann wird <strong><strong>de</strong>r</strong> Durchschnittspreis ermittelt und über<br />
197
198<br />
12 »Stored Procedures« und »Prozedurale Sprachelemente«<br />
RETURN zurückgeliefert. Im Gegensatz zu unserer vorherigen Version von »Ermittle-<br />
Durchschnittspreis« ist diese Variante etwas umfangreicher, dafür aber verständlicher.<br />
Über die Schlüsselwörter BEGIN...END wer<strong>de</strong>n die Anweisungen zu e<strong>in</strong>em Anweisungsblock<br />
zusammengefasst.<br />
12.3.2 IF...THEN...ELSE<br />
Die IF...THEN...ELSE-Anweisung dient zum Abbil<strong>de</strong>n von »Wenn...dann« -Entscheidungen.<br />
Abhängig von e<strong>in</strong>er bestim<strong>mt</strong>en Bed<strong>in</strong>gung wird e<strong>in</strong> Anweisungsblock ausgeführt<br />
o<strong><strong>de</strong>r</strong> nicht. Betrachten wir hierzu e<strong>in</strong> Beispiel: Abhängig davon, wie viele<br />
Bestellungen e<strong>in</strong> Mitarbeiter bearbeitet hat, soll er e<strong>in</strong>en Bonus ausgezahlt bekommen.<br />
Bei e<strong>in</strong>er o<strong><strong>de</strong>r</strong> ke<strong>in</strong>er bearbeiteten Bestellung gibt es ke<strong>in</strong>en Bonus, bei zwei bearbeiteten<br />
Bestellungen 10,-- Eur und bei mehr als drei Bestellungen 20,-- Eur. Hierzu schreiben<br />
wir e<strong>in</strong>e Prozedur, die als Übergabeparameter die Personalnummer erhält und<br />
dann ausgibt, wie hoch <strong><strong>de</strong>r</strong> Bonus für <strong>de</strong>n Mitarbeiter ist:<br />
CREATE PROCEDURE HoeheBonus(Personalnr INTEGER,<br />
OUT Bonus DECIMAL(4,2))<br />
BEGIN<br />
DECLARE anzahlBestellungen INTEGER;<br />
-- Ermitteln <strong><strong>de</strong>r</strong> bearbeiteten Bestellungen<br />
SELECT COUNT(Personalnummer) INTO anzahlBestellungen<br />
FROM Bestellung<br />
WHERE Personalnummer = Personalnr;<br />
-- Variable Bonus auf 0 setzen<br />
SET Bonus = 0.00;<br />
IF anzahlBestellungen = 2 THEN<br />
SET Bonus = 10.00;<br />
ELSEIF anzahlBestellungen >= 3 THEN<br />
SET Bonus = 20.00;<br />
END IF<br />
END<br />
Zunächst wird <strong>in</strong> <strong><strong>de</strong>r</strong> Funktion die Anzahl <strong><strong>de</strong>r</strong> Bestellungen ermittelt, die <strong><strong>de</strong>r</strong> Mitarbeiter<br />
mit <strong><strong>de</strong>r</strong> übergebenen Personalnummer bearbeitet hat. In <strong><strong>de</strong>r</strong> IF-Anweisung wird<br />
dann abhängig von <strong><strong>de</strong>r</strong> Anzahl <strong><strong>de</strong>r</strong> bearbeiteten Bestellungen die Übergabevariable<br />
»Bonus« auf <strong>de</strong>n entsprechen<strong>de</strong>n Betrag gesetzt.<br />
12.3.3 CASE<br />
Die CASE-Anweisung entspricht weitestgehend e<strong>in</strong>er mehrfach geschachtelten IF-<br />
Anweisung. Betrachten wir dazu die IF-Anweisung aus <strong>de</strong>m letzten Beispiel. Mit e<strong>in</strong>er<br />
CASE-Anweisung könnte man das Gleiche wie folgt erreichen:
Sprachelemente zur Kontrollsteuerung<br />
SET Bonus =<br />
CASE<br />
WHEN anzahlBestellungen = 2 THEN 10.00<br />
WHEN anzahlBestellungen >= 3 THEN 20.00<br />
ELSE 0.00<br />
END<br />
E<strong>in</strong>geleitet durch das CASE-Schlüsselwort folgt h<strong>in</strong>ter <strong>de</strong>m Schlüsselwort WHEN<br />
jeweils die Bed<strong>in</strong>gung die erfüllt se<strong>in</strong> muss, damit <strong><strong>de</strong>r</strong> Wert h<strong>in</strong>ter THEN verwen<strong>de</strong>t<br />
wird. Der ELSE-Zweig wird ausgeführt, wenn ke<strong>in</strong>e <strong><strong>de</strong>r</strong> aufgeführen WHEN-Bed<strong>in</strong>gungen<br />
e<strong>in</strong>tritt.<br />
Soll immer die gleiche Variable ausschließlich auf Gleichheit mit bestim<strong>mt</strong>en Werten<br />
getestet wer<strong>de</strong>n, ist die Verwendung <strong><strong>de</strong>r</strong> CASE-Anweisung noch e<strong>in</strong>facher. Angenommen,<br />
wir möchten über e<strong>in</strong>e SELECT-Anweisung alle Kun<strong>de</strong>n ausgeben. Anstelle <strong><strong>de</strong>r</strong><br />
Kürzel »M« und »W« für Geschlecht soll allerd<strong>in</strong>gs <strong>in</strong> <strong><strong>de</strong>r</strong> Ergebnistabelle »männlich«<br />
bzw. »weiblich« ausgegeben wer<strong>de</strong>n. Da man <strong>in</strong> diesem Fall immer die gleiche Spalte<br />
auf Gleichheit mit »W« o<strong><strong>de</strong>r</strong> »M« testet, kann diese direkt h<strong>in</strong>ter <strong><strong>de</strong>r</strong> CASE-Anweisung<br />
aufgeführt wer<strong>de</strong>n. Dann muss h<strong>in</strong>ter <strong><strong>de</strong>r</strong> WHEN-Klausel <strong><strong>de</strong>r</strong> Spaltenname nicht<br />
explizit aufgeführt wer<strong>de</strong>n:<br />
SELECT Name,<br />
Vorname,<br />
CASE Geschlecht<br />
WHEN 'M' THEN 'Männlich'<br />
WHEN 'W' THEN 'Weiblich'<br />
ELSE 'unbekannt'<br />
END AS 'Geschlecht'<br />
FROM Kun<strong>de</strong><br />
Name Vorname Geschlecht<br />
--------- ------- ----------<br />
Bolte Bertram Männlich<br />
Muster Hans Männlich<br />
Wiegerich Frieda Weiblich<br />
Carlson Peter Männlich<br />
12.3.4 REPEAT...UNTIL<br />
REPEAT wie<strong><strong>de</strong>r</strong>holt e<strong>in</strong>en Anweisungsblock so lange, bis e<strong>in</strong>e <strong>de</strong>f<strong>in</strong>ierte Bed<strong>in</strong>gung<br />
e<strong>in</strong>tritt. Der Anweisungblock wird bei REPEAT m<strong>in</strong><strong>de</strong>stens e<strong>in</strong>mal durchlaufen, da die<br />
Bed<strong>in</strong>gung erst am En<strong>de</strong> <strong>de</strong>s Anweisungsblocks überprüft wird. Nehmen wir als Beispiel<br />
e<strong>in</strong>e Funktion, die die n-te Potenz e<strong>in</strong>er Zahl berechnen soll. Wir wollen diese<br />
Funktion Potenz nennen und es wer<strong>de</strong>n zwei Übergabeparameter übergeben: Zum<br />
e<strong>in</strong>en die Zahl, von <strong><strong>de</strong>r</strong> die Potenz berechnet wer<strong>de</strong>n soll und zum an<strong><strong>de</strong>r</strong>en die Zahl für<br />
die n-te Potenz. Mit Hilfe <strong><strong>de</strong>r</strong> REPEAT-Anweisung wird die Multiplikation dann entsprechend<br />
oft durchlaufen:<br />
199
200<br />
12 »Stored Procedures« und »Prozedurale Sprachelemente«<br />
CREATE FUNCTION Potenz (basis FLOAT, exponent INTEGER)<br />
RETURNS FLOAT<br />
BEGIN<br />
DECLARE ergebnis FLOAT;<br />
SET ergebnis = basis;<br />
-- multipliziere ergebnis so oft mit basis,<br />
-- bis exponent kle<strong>in</strong>er gleich 1<br />
REPEAT<br />
SET ergebnis = ergebnis * basis;<br />
SET exponent = exponent – 1;<br />
UNTIL exponent 1 DO<br />
SET ergebnis = ergebnis * basis;<br />
SET exponent = exponent – 1;<br />
END WHILE<br />
…<br />
In diesem Fall wird über die WHILE-Anweisung <strong><strong>de</strong>r</strong> Anweisungsblock solange durchlaufen,<br />
wie die Variable exponent e<strong>in</strong>en Wert größer 1 hat.<br />
12.3.6 LEAVE<br />
Die SQL-Anweisung LEAVE ist nur <strong>in</strong> Zusammenhang mit Wie<strong><strong>de</strong>r</strong>holungen von<br />
Anweisungsblöcken über WHILE o<strong><strong>de</strong>r</strong> REPEAT s<strong>in</strong>nvoll und dient dazu, e<strong>in</strong>e Wie<strong><strong>de</strong>r</strong>holungsschleife<br />
vorzeitig zu been<strong>de</strong>n. Betrachten wir dazu wie<strong><strong>de</strong>r</strong> unser letztes Bei-
Beispiel: Bestellung erfassen<br />
spiel mit <strong><strong>de</strong>r</strong> Funktion Potenz. Angenommen, es sollen ke<strong>in</strong>e Ergebnisse größer als<br />
10000 zurückgegeben wer<strong>de</strong>n, so kann die Schleife vorzeitig über das Schlüsselwort<br />
LEAVE verlassen wer<strong>de</strong>n. Demnach wür<strong>de</strong> die WHILE-Schleife folgen<strong><strong>de</strong>r</strong>maßen aussehen:<br />
…<br />
WHILE exponent > 1 DO<br />
SET ergebnis = ergebnis * basis;<br />
IF ergebnis > 10000 THEN<br />
LEAVE; -- Verlassen <strong><strong>de</strong>r</strong> Wie<strong><strong>de</strong>r</strong>holungsschleife<br />
END IF<br />
SET exponent = exponent – 1;<br />
END WHILE<br />
…<br />
12.4 Beispiel: Bestellung erfassen<br />
Zum Abschluss dieses Kapitels sollen alle Erkenntnisse noch e<strong>in</strong>mal an zwei Beispielen<br />
vertieft wer<strong>de</strong>n. Im ersten Beispiel soll e<strong>in</strong>e Prozedur geschrieben wer<strong>de</strong>n, die für e<strong>in</strong>en<br />
Kun<strong>de</strong>n <strong>de</strong>n Namen <strong>de</strong>s K<strong>in</strong><strong>de</strong>s <strong>in</strong> die dazugehörige Tabelle e<strong>in</strong>trägt. Da das Geburtsdatum<br />
<strong>de</strong>s K<strong>in</strong><strong>de</strong>s i.d.R. kle<strong>in</strong>er als das <strong>de</strong>s Elternteils ist, soll die Prozedur dies überprüfen<br />
und wenn nötig, e<strong>in</strong>e Fehlermeldung zurückliefern. Außer<strong>de</strong>m soll überprüft<br />
wer<strong>de</strong>n, ob das Geburtsdatum niedriger als das aktuelle Tagesdatum ist.<br />
Der Prozedur »K<strong>in</strong>dErfassen« wer<strong>de</strong>n vier E<strong>in</strong>gabe- und e<strong>in</strong> Ausgabeparameter übergeben.<br />
Die E<strong>in</strong>gabeparameter »Kun<strong>de</strong>nnr« , »VornameK<strong>in</strong>d« , »GeburtsdatumK<strong>in</strong>d« ,<br />
»GeschlechtK<strong>in</strong>d« enthalten die Kun<strong>de</strong>nnummer <strong>de</strong>s Elternteils sowie die Informationen<br />
über das K<strong>in</strong>d. Der Ausgabeparameter »Rueckgabe« liefert e<strong>in</strong>e Zeichenkette<br />
zurück, <strong>in</strong> <strong><strong>de</strong>r</strong> nach Ausführen <strong><strong>de</strong>r</strong> Prozedur beschrieben ist, ob Probleme beim E<strong>in</strong>fügen<br />
aufgetreten s<strong>in</strong>d o<strong><strong>de</strong>r</strong> ob das E<strong>in</strong>fügen erfolgreich war.<br />
CREATE PROCEDURE K<strong>in</strong>dErfassen( Kun<strong>de</strong>nnr INTEGER,<br />
VornameK<strong>in</strong>d VARCHAR(20),<br />
GeburtsdatumK<strong>in</strong>d DATE,<br />
GeschlechtK<strong>in</strong>d CHAR(1),<br />
OUT Rueckgabe VARCHAR(100) )<br />
...<br />
Danach wer<strong>de</strong>n über e<strong>in</strong>e IF-Anweisung mehrere Werte auf Plausibilität überprüft. Die<br />
erste Bed<strong>in</strong>gung testet, ob das Geburtsdatum <strong>de</strong>s K<strong>in</strong><strong>de</strong>s <strong>in</strong> <strong><strong>de</strong>r</strong> Zukunft liegt. Ist dies<br />
<strong><strong>de</strong>r</strong> Fall, wird e<strong>in</strong>e Fehlermeldung <strong>in</strong> <strong><strong>de</strong>r</strong> Variablen »Rueckgabe« zurückgeliefert.<br />
An<strong><strong>de</strong>r</strong>nfalls wird das Geburtsdatum <strong>de</strong>s Elternteils über die SELECT-Anweisung<br />
ermittelt und überprüft, ob das K<strong>in</strong>d <strong>de</strong>m Geburtsdatum nach älter als das Elternteil<br />
ist. Auch <strong>in</strong> diesem Fall erfolgt e<strong>in</strong>e Fehlermeldung. Ist das K<strong>in</strong>d jünger als das Elternteil,<br />
wer<strong>de</strong>n die Daten <strong>in</strong> die Tabelle »K<strong>in</strong>d« über die INSERT-Anweisung e<strong>in</strong>gefügt.<br />
201
202<br />
12 »Stored Procedures« und »Prozedurale Sprachelemente«<br />
IF GeburtsdatumK<strong>in</strong>d > CURRENT_DATE THEN<br />
SET Rueckgabe = 'Problem: Geburtsdatum <strong>in</strong> <strong><strong>de</strong>r</strong> Zukunft!';<br />
ELSEIF ( SELECT Geburtsdatum<br />
FROM Kun<strong>de</strong><br />
WHERE Kun<strong>de</strong>nnummer = Kun<strong>de</strong>nnr ) >= GeburtsdatumK<strong>in</strong>d<br />
SET Rueckgabe = 'Problem: K<strong>in</strong>d Geburtsdatum aktueller!';<br />
ELSE<br />
INSERT INTO K<strong>in</strong>d VALUES( Kun<strong>de</strong>nnr, VornameK<strong>in</strong>d,<br />
GeburtsdatumK<strong>in</strong>d, GeschlechtK<strong>in</strong>d);<br />
SET Rueckgabe = 'Datensatz erfolgreich e<strong>in</strong>gefügt!'<br />
END IF<br />
Zum Aufrufen unserer Prozedur müssen wir e<strong>in</strong>e Variable für <strong>de</strong>n Übergabeparameter<br />
»Rueckgabe« <strong>de</strong>klarieren, <strong>in</strong> <strong><strong>de</strong>r</strong> die Zeichenkette mit <strong><strong>de</strong>r</strong> Fehlermeldung zurückgegeben<br />
wird. Danach wird die Prozedur über die SQL-Anweisung CALL aufgerufen:<br />
DECLARE ergebnis VARCHAR(100);<br />
CALL K<strong>in</strong>dErfassen( 1, 'Hans', '2003-01-01', DEFAULT, ergebnis );<br />
SELECT ergebnis;<br />
-------------------------------------<br />
Problem: Geburtsdatum <strong>in</strong> <strong><strong>de</strong>r</strong> Zukunft!<br />
12.5 Beispiel: Phonetischer Vergleich<br />
Im zweiten Beispiel geht es um das Erstellen e<strong>in</strong>er Funktion zur phonetischen Suche.<br />
E<strong>in</strong>ige RDBMS-Produkte wie z.B. IBM DB2 o<strong><strong>de</strong>r</strong> Microsoft SQL Server bieten die Funktion<br />
SOUNDEX an, mit <strong><strong>de</strong>r</strong> man Wörter auf Ähnlichkeit im Klang überprüfen kann.<br />
Dieser phonetische Vergleich basiert auf e<strong>in</strong>em Algorithmus, <strong><strong>de</strong>r</strong> bestim<strong>mt</strong>en ähnlich<br />
kl<strong>in</strong>gen<strong>de</strong>n Buchstaben e<strong>in</strong>e Zahl zuordnet und Vokale beim Vergleich nicht mit<br />
berücksichtigt. Dadurch kann man Wörter, die ähnlich kl<strong>in</strong>gen, aber unterschiedlich<br />
buchstabiert wer<strong>de</strong>n, f<strong>in</strong><strong>de</strong>n. Personen, die <strong>de</strong>n Namen Meyer, Meier, Maier o<strong><strong>de</strong>r</strong><br />
Mayer haben, ergeben dabei die gleiche Zahlenfolge.<br />
Betrachten wir zunächst <strong>de</strong>n Algorithmus: Der erste Buchstabe e<strong>in</strong>es Wortes bleibt<br />
erhalten und wird <strong>in</strong> e<strong>in</strong>en Großbuchstaben umgewan<strong>de</strong>lt. Allen folgen<strong>de</strong>n Buchstaben<br />
wer<strong>de</strong>n Zahlen zugeordnet, außer es han<strong>de</strong>lt sich um Vokale o<strong><strong>de</strong>r</strong> die Buchstaben<br />
H, W und Y.
Beispiel: Phonetischer Vergleich<br />
Buchstaben Zugeordnete Zahl<br />
B, P, F, V 1<br />
C, S, K, G, J, Q, X, Z 2<br />
D, T 3<br />
L 4<br />
M, N 5<br />
R 6<br />
Von <strong>de</strong>m ermittelten Soun<strong>de</strong>x-Co<strong>de</strong> wer<strong>de</strong>n dann die ersten 4 Zeichen berücksichtigt.<br />
Besteht <strong><strong>de</strong>r</strong> Co<strong>de</strong> aus weniger als 4 Zeichen, wer<strong>de</strong>n die restlichen Zeichen mit <strong><strong>de</strong>r</strong> Zahl<br />
0 aufgefüllt.<br />
Betrachten wir als Beispiel <strong>de</strong>n Nachnamen »Muster« und berechnen <strong>de</strong>n Co<strong>de</strong> e<strong>in</strong>mal<br />
manuell, so ergibt sich »M236« . Der erste Buchstabe <strong>de</strong>s Wortes wird übernommen.<br />
Der zweite Buchstabe, das »u« wird ignoriert (Vokal), <strong>de</strong>m Buchstabe »s« wird die Zahl<br />
2 zugeordnet, »t« die Zahl 3, »e« wird wie<strong><strong>de</strong>r</strong> ignoriert (Vokal) und »r« entspricht <strong><strong>de</strong>r</strong><br />
Zahl 6. Somit ergibt sich als Soun<strong>de</strong>x-Co<strong>de</strong> <strong><strong>de</strong>r</strong> Wert »M236« . Dieser Algorithmus wird<br />
übrigens vom »Amerikanischen Nationalen Archiv« verwen<strong>de</strong>t, um Akten <strong><strong>de</strong>r</strong> Volkszählung<br />
gemäß <strong>de</strong>n Namen <strong><strong>de</strong>r</strong> Bürger lautbezogen zu ordnen. Der Algorithmus<br />
bezieht sich damit zwar mehr auf die englische Sprache, allerd<strong>in</strong>gs hat er sich auch im<br />
<strong>de</strong>utschen Sprachraum bewährt.<br />
Wie setzen wir diesen Algorithmus nun <strong>in</strong> SQL um? Zunächst erzeugen wir e<strong>in</strong>e Funktion,<br />
<strong><strong>de</strong>r</strong> wir <strong>de</strong>n Namen »Klang« geben wollen. Als Übergabeparameter wird das Wort<br />
übermittelt, für das <strong><strong>de</strong>r</strong> Soun<strong>de</strong>x-Co<strong>de</strong> berechnet wer<strong>de</strong>n soll. Entsprechend gibt die<br />
Funktion dann <strong>de</strong>n berechneten Soun<strong>de</strong>x-Co<strong>de</strong> als Zeichenkette zurück.<br />
CREATE FUNCTION Klang ( Wort VARCHAR(250) )<br />
RETURNS VARCHAR(250)<br />
BEGIN<br />
...<br />
Zuerst wer<strong>de</strong>n die Variablen <strong>de</strong>klariert, die <strong>in</strong> <strong><strong>de</strong>r</strong> Funktion verwen<strong>de</strong>t wer<strong>de</strong>n. In diesem<br />
Fall wird die Variable »Klang« für <strong>de</strong>n Rückgabewert benötigt. Weiterh<strong>in</strong> <strong>de</strong>klarieren<br />
wir e<strong>in</strong>e Variable, die <strong>de</strong>n In<strong>de</strong>x auf das aktuell zu bearbeiten<strong>de</strong> Zeichen enthält<br />
und e<strong>in</strong>e weitere, die jeweils e<strong>in</strong> e<strong>in</strong>zelnes Zeichen <strong>de</strong>s Wortes speichern soll.<br />
DECLARE Klang VARCHAR(250);<br />
DECLARE In<strong>de</strong>x INTEGER;<br />
DECLARE Zeichen VARCHAR;<br />
...<br />
Tabelle 12.1: »Soun<strong>de</strong>x-Algorithmus«<br />
203
204<br />
12 »Stored Procedures« und »Prozedurale Sprachelemente«<br />
Nun folgen die eigentlichen SQL-Anweisungen <strong><strong>de</strong>r</strong> Funktion. Zuerst wer<strong>de</strong>n überflüssige<br />
Leerzeichen entfernt und das erste Zeichen <strong>de</strong>s Wortes <strong>in</strong> <strong><strong>de</strong>r</strong> Rückgabevariablen<br />
»Klang« gespeichert:<br />
-- Leerzeichen entfernen und <strong>in</strong> Großbuchstaben wan<strong>de</strong>ln<br />
SET Wort = TRIM( BOTH ' ' FROM Wort );<br />
SET Wort = UPPER( Wort );<br />
-- erstes Zeichen <strong>de</strong>s Wortes bleibt erhalten<br />
SET In<strong>de</strong>x = 1;<br />
SET Klang = SUBSTRING( Wort FROM In<strong>de</strong>x FOR 1);<br />
...<br />
Darauf folgt die eigentliche WHILE-Schleife, die solange ausgeführt wird, bis das letzte<br />
Zeichen bearbeitet ist o<strong><strong>de</strong>r</strong> bis <strong><strong>de</strong>r</strong> Soun<strong>de</strong>x-Co<strong>de</strong> aus maximal 4 Zeichen besteht:<br />
-- Wort konvertieren<br />
WHILE In<strong>de</strong>x
SET Klang = Klang + Zeichen;<br />
END WHILE;<br />
...<br />
Zusammenfassung<br />
Zum Schluss wird getestet, ob die Zeichenkette, die zurückgeliefert wer<strong>de</strong>n soll, auch<br />
aus vier Zeichen besteht. Ist dies nicht <strong><strong>de</strong>r</strong> Fall, so wer<strong>de</strong>n die übrigen Stellen mit <strong><strong>de</strong>r</strong><br />
Zahl 0 aufgefüllt. Darauf wird das Ergebnis mit <strong><strong>de</strong>r</strong> Anweisung RETURN zurückgeliefert.<br />
-- evtl. <strong>de</strong>n Rest mit 0 auffüllen<br />
WHILE LEN( Klang ) < 4 DO<br />
SET Klang = Klang + '0';<br />
END WHILE<br />
RETURN( Klang );<br />
END<br />
Bevor wir das Kapitel been<strong>de</strong>n, wollen wir natürlich noch e<strong>in</strong>mal sehen, ob unsere<br />
Funktion »Klang« auch das gewünschte Ergebnis liefert. Dazu fügen wir zunächst mit<br />
Hilfe <strong><strong>de</strong>r</strong> INSERT-Anweisung drei neue Kun<strong>de</strong>n e<strong>in</strong>:<br />
INSERT INTO Kun<strong>de</strong> VALUES<br />
(5, 'Meier', 'Petra', 'W', 'Magnusweg', '61', 22222)<br />
INSERT INTO Kun<strong>de</strong> VALUES<br />
(6, 'Meyer', 'Paula', 'W', 'Parkstr.', '81', 22222)<br />
INSERT INTO Kun<strong>de</strong> VALUES<br />
(7, 'Maier', 'Pieter', 'M', 'Hollgang', '86', 22222)<br />
Um nun alle Kun<strong>de</strong>n zu f<strong>in</strong><strong>de</strong>n, <strong><strong>de</strong>r</strong>en Name so ähnlich kl<strong>in</strong>gt wie »Mayer« , können<br />
wir folgen<strong>de</strong> SELECT-Anweisung verwen<strong>de</strong>n und erhalten dann alle drei e<strong>in</strong>gefügten<br />
Kun<strong>de</strong>n:<br />
SELECT *<br />
FROM Kun<strong>de</strong><br />
WHERE Klang(Name) = Klang('mayer')<br />
12.6 Zusammenfassung<br />
In diesem Kapitel haben wir die prozeduralen Sprachelemente von SQL kennen gelernt.<br />
Ursprünglich ist SQL als re<strong>in</strong> <strong>de</strong>klarative Programmiersprache konzipiert wor<strong>de</strong>n. Mit<br />
<strong><strong>de</strong>r</strong> Zeit und <strong>de</strong>m Erfolg prozeduraler Programmiersprachen wie C o<strong><strong>de</strong>r</strong> Pascal wur<strong>de</strong>n<br />
<strong>in</strong> die RDBMS-Produkte und schließlich auch im ANSI SQL-Standard die wichtigsten<br />
prozeduralen Sprachelemente übernommen. Prozedurale Sprachelemente s<strong>in</strong>d vor<br />
allem <strong>in</strong> Zusammenhang mit <strong><strong>de</strong>r</strong> Verwendung von Rout<strong>in</strong>en s<strong>in</strong>nvoll. Rout<strong>in</strong>en dienen<br />
dazu, SQL-Anweisungen unter e<strong>in</strong>em bestim<strong>mt</strong>en Namen vom RDBMS zu speichern.<br />
Über diesen Namen kann dann <strong><strong>de</strong>r</strong> komplette Anweisungsblock aufgerufen wer<strong>de</strong>n.<br />
Um Rout<strong>in</strong>en flexibel e<strong>in</strong>setzen zu können, kann man Werte an die Rout<strong>in</strong>en übergeben<br />
205
206<br />
12 »Stored Procedures« und »Prozedurale Sprachelemente«<br />
und sich Werte zurückliefern lassen. Werte, die als E<strong>in</strong>gabeparameter an die Rout<strong>in</strong>e<br />
übergeben wer<strong>de</strong>n, kennzeichnet man mit <strong>de</strong>m Schlüsselwort IN. Werte, die als Ausgabeparameter<br />
an die Rout<strong>in</strong>e übergeben wer<strong>de</strong>n, kennzeichnet man dagegen mit <strong>de</strong>m<br />
Schlüsselwort OUT. E<strong>in</strong> Übergabeparameter kann sowohl als E<strong>in</strong>gabe- und Ausgabeparameter<br />
dienen. Dann wird er mit <strong>de</strong>m Schlüsselwort INOUT gekennzeichnet.<br />
Bei Rout<strong>in</strong>en unterschei<strong>de</strong>t man zwischen Funktionen und Prozeduren. Funktionen<br />
liefern immer e<strong>in</strong>en Wert über die Anweisung RETURN zurück, <strong>de</strong>ssen Datentyp man<br />
bei Anlegen <strong><strong>de</strong>r</strong> Funktion angeben muss. Dadurch können Funktionen <strong>in</strong>nerhalb von<br />
SQL-Anweisungen verwen<strong>de</strong>t wer<strong>de</strong>n. In Kapitel 8 haben wir bereits »Built-<strong>in</strong>« -Funktionen<br />
kennen gelernt. »Built-<strong>in</strong>« -Funktionen s<strong>in</strong>d vor<strong>de</strong>f<strong>in</strong>ierte Funktionen <strong>de</strong>s<br />
RDBMS und entsprechen vom Aufruf eigenen selbst erstellten Funktionen.<br />
Prozeduren können im Gegensatz zu Funktionen nicht <strong>in</strong>nerhalb von SQL-Anweisungen<br />
verwen<strong>de</strong>t wer<strong>de</strong>n und liefern auch ke<strong>in</strong>en Wert zurück (es sei <strong>de</strong>nn über e<strong>in</strong>en<br />
Ausgabeparameter). Um Prozeduren aufzurufen, verwen<strong>de</strong>t man die SQL-Anweisung<br />
CALL.<br />
Der allgeme<strong>in</strong>e Aufbau, um e<strong>in</strong>e Prozedur anzulegen, sieht wie folgt aus:<br />
CREATE PROCEDURE ( parameter1, ..., parameter n)<br />
Der allgeme<strong>in</strong>e Aufbau, um e<strong>in</strong>e Funktion anzulegen, sieht wie folgt aus:<br />
CREATE FUNCTION ( parameter1, ..., parameter n)<br />
RETURNS <br />
Um mehrere SQL-Anweisungen <strong>in</strong>nerhalb e<strong>in</strong>er Anweisung zu e<strong>in</strong>em Block zusammenzufassen,<br />
verwen<strong>de</strong>t man die Schlüsselwörter BEGIN… END.<br />
Über die IF- o<strong><strong>de</strong>r</strong> die CASE-Anweisung kann festgelegt wer<strong>de</strong>n, welche Anweisungen<br />
bei E<strong>in</strong>treten e<strong>in</strong>er bestim<strong>mt</strong>en Bed<strong>in</strong>gung ausgeführt wer<strong>de</strong>n sollen.<br />
Mit REPEAT o<strong><strong>de</strong>r</strong> WHILE kann e<strong>in</strong> Anweisungblock mehrmals h<strong>in</strong>tere<strong>in</strong>an<strong><strong>de</strong>r</strong> durchlaufen<br />
wer<strong>de</strong>n. Dabei wird über e<strong>in</strong>e Abbruchbed<strong>in</strong>gung festgelegt, wie oft <strong><strong>de</strong>r</strong> Anweisungsblock<br />
ausgeführt wird. Bei <strong><strong>de</strong>r</strong> REPEAT-Anweisung erfolgt die Überprüfung <strong><strong>de</strong>r</strong><br />
Abbruchbed<strong>in</strong>gung am En<strong>de</strong> <strong>de</strong>s Anweisungsblockes, bei <strong><strong>de</strong>r</strong> WHILE-Anweisung am<br />
Anfang. Um e<strong>in</strong>en Anweisungsblock zu verlassen, bevor die Abbruchbed<strong>in</strong>gung e<strong>in</strong>tritt,<br />
kann man die LEAVE-Anweisung verwen<strong>de</strong>n.<br />
12.7 Aufgaben<br />
Wie<strong><strong>de</strong>r</strong>holungsfragen<br />
1) Wor<strong>in</strong> besteht <strong><strong>de</strong>r</strong> wesentliche Unterschied zwischen e<strong>in</strong>er Prozedur und e<strong>in</strong>er<br />
Funktion?<br />
2) Welche Unterschie<strong>de</strong> bestehen <strong>in</strong>haltlich zwischen <strong>de</strong>n bei<strong>de</strong>n folgen<strong>de</strong>n Prozeduren?<br />
CREATE PROCEDURE beispiel(IN param1, OUT param2, INOUT param3)<br />
CREATE PROCEDURE beispiel(param1, OUT param2, param3)
Aufgaben<br />
3) Wor<strong>in</strong> besteht <strong><strong>de</strong>r</strong> Unterschied zwischen <strong><strong>de</strong>r</strong> CASE- und <strong><strong>de</strong>r</strong> IF-Anweisung? Kann<br />
je<strong>de</strong> IF-Anweisung auch mit e<strong>in</strong>er CASE-Anweisung geschrieben wer<strong>de</strong>n bzw. umgekehrt?<br />
4) Wozu dient die WHILE-Anweisung?<br />
5) Wor<strong>in</strong> besteht <strong><strong>de</strong>r</strong> Unterschied zwischen <strong><strong>de</strong>r</strong> REPEAT- und <strong><strong>de</strong>r</strong> WHILE-Anweisung?<br />
6) Geben Sie e<strong>in</strong> Beispiel zur Verwendung <strong><strong>de</strong>r</strong> LEAVE-Anweisung!<br />
Übungen<br />
1) Än<strong><strong>de</strong>r</strong>n Sie die Prozedur »K<strong>in</strong>dErfassen« aus Abschnitt 12.2, so dass anstelle e<strong>in</strong>er<br />
IF-Anweisung die CASE-Anweisung verwen<strong>de</strong>t wird!<br />
2) Än<strong><strong>de</strong>r</strong>n Sie die Funktion »Klang« aus Abschnitt 12.5 so, dass anstelle e<strong>in</strong>er CASEdie<br />
IF-Anweisung und anstelle <strong><strong>de</strong>r</strong> WHILE- die REPEAT-Anweisung verwen<strong>de</strong>t<br />
wird!<br />
3) Än<strong><strong>de</strong>r</strong>n Sie die Funktion »Klang« aus Abschnitt 12.5 so, dass auch <strong><strong>de</strong>r</strong> Buchstabe ‚ß'<br />
als ‚ss' im Algorithmus berücksichtigt wird!<br />
4) Erweitern Sie die Funktion »Potenz« aus Abschnitt 12.3.4, so dass auch negative<br />
Zahlen und die Zahl 0 als Exponent übergeben wer<strong>de</strong>n können!<br />
5) Schreiben Sie e<strong>in</strong>e Prozedur »ErhoeheGehalt« , die das Gehalt aller Mitarbeiter so<br />
lange um jeweils immer 1% erhöht, bis das niedrigste Gehalt auf über 2.500 Eur gestiegen<br />
ist?<br />
6) Schreiben Sie e<strong>in</strong>e Funktion, die <strong>de</strong>n durchschnittlichen Preis e<strong>in</strong>es Werbeartikels<br />
zurückliefert!<br />
7) Verwen<strong>de</strong>n Sie die Funktion aus Übung 6., um e<strong>in</strong>e SELECT-Anweisung zu schreiben,<br />
die die Beschreibung aller Werbeartikel mit ihrem Preis ausgibt und die Differenz<br />
zum Durchschnittspreis!<br />
8) Schreiben Sie e<strong>in</strong>e Prozedur »Kun<strong>de</strong>nBonus« , die ermittelt, welcher Kun<strong>de</strong> die <strong>in</strong>sgesa<strong>mt</strong><br />
höchste Bestellsumme hat und fügen Sie dann für je<strong>de</strong> Bestellung, die dieser<br />
Kun<strong>de</strong> getätigt hat, e<strong>in</strong>en Bestellposten mit <strong>de</strong>m Werbeartikel 1081 (Menge 1)<br />
h<strong>in</strong>zu!<br />
9) Schreiben Sie e<strong>in</strong>e Funktion mit <strong>de</strong>m Namen Klangunterschied, <strong><strong>de</strong>r</strong> zwei Wörter als<br />
Übergabeparameter übergeben wer<strong>de</strong>n. Die Funktion soll dann <strong>de</strong>n Soun<strong>de</strong>x-Co<strong>de</strong><br />
für bei<strong>de</strong> Wörter ermitteln und dann die Differenz zwischen <strong>de</strong>n bei<strong>de</strong>n Zahlen<br />
(also nach <strong>de</strong>m ersten Buchstaben <strong>de</strong>s Soun<strong>de</strong>x-Co<strong>de</strong>s) zurückliefern! (H<strong>in</strong>weis:<br />
Verwen<strong>de</strong>n Sie die »Built-<strong>in</strong>« -Funktion CAST).<br />
207
13 Trigger<br />
In Kapitel 13 sollen folgen<strong>de</strong> Fragen geklärt wer<strong>de</strong>n:<br />
� Wie können komplizierte Integritätsbed<strong>in</strong>gungen unterstützt wer<strong>de</strong>n?<br />
� Wie kann man automatisch Prozeduren aufrufen, wenn e<strong>in</strong> Datensatz aus e<strong>in</strong>er<br />
Tabelle gelöscht, e<strong>in</strong>gefügt o<strong><strong>de</strong>r</strong> geän<strong><strong>de</strong>r</strong>t wird?<br />
� Was s<strong>in</strong>d Trigger?<br />
13.1 Motivation<br />
Frau Kart hat <strong>in</strong>zwischen Prozeduren geschrieben, über die man Bestellungen und die<br />
K<strong>in</strong><strong><strong>de</strong>r</strong> von Kun<strong>de</strong>n erfassen kann. Obgleich sie Herrn Kle<strong>in</strong> gezeigt hat, wie er die Prozeduren<br />
verwen<strong>de</strong>n soll, trägt Herr Kle<strong>in</strong> <strong>de</strong>nnoch manchmal Datensätze <strong>in</strong> die K<strong>in</strong>d-<br />
Tabelle über die INSERT-Anweisung e<strong>in</strong>. Dadurch haben sich e<strong>in</strong>ige Fehler e<strong>in</strong>geschlichen:<br />
So existieren mehrere E<strong>in</strong>träge <strong>in</strong> <strong><strong>de</strong>r</strong> K<strong>in</strong>d-Tabelle mit e<strong>in</strong>em Geburtsdatum,<br />
dass <strong>in</strong> <strong><strong>de</strong>r</strong> Zukunft liegt.<br />
Bei <strong><strong>de</strong>r</strong> Durchsicht <strong><strong>de</strong>r</strong> Tabellen fallen Frau Kart die Fehler auf. Als vorbildliche Vorgesetzte<br />
ermahnt sie Herrn Kart, die von ihr geschriebenen Prozeduren zu verwen<strong>de</strong>n.<br />
Dennoch ruft sie wie<strong><strong>de</strong>r</strong> Herrn Fleissig von <strong><strong>de</strong>r</strong> Unternehmensberatung an, <strong><strong>de</strong>r</strong> ihr bisher<br />
immer gute Ratschläge geben konnte. Auch diesmal kennt Herr Fleissig e<strong>in</strong>e bessere<br />
Lösung für ihr Problem.<br />
Er rät Frau Kart Folgen<strong>de</strong>s: »Neben Prozeduren, die man explizit aufrufen muss, kann<br />
man Prozeduren schreiben, die bei E<strong>in</strong>treten e<strong>in</strong>es bestim<strong>mt</strong>en Ereignisses für e<strong>in</strong>e<br />
Tabelle automatisch ausgeführt wer<strong>de</strong>n. Solche Ereignisse s<strong>in</strong>d das E<strong>in</strong>fügen, Än<strong><strong>de</strong>r</strong>n<br />
o<strong><strong>de</strong>r</strong> Löschen von Datensätzen. Man bezeichnet solche automatisch aufgerufenen Prozeduren<br />
als »Trigger«. In ihrem Fall können Sie e<strong>in</strong>e Trigger-Prozedur schreiben, die<br />
immer dann ausgeführt wird, wenn <strong>in</strong> die K<strong>in</strong>d-Tabelle e<strong>in</strong> Datensatz e<strong>in</strong>gefügt o<strong><strong>de</strong>r</strong><br />
geän<strong><strong>de</strong>r</strong>t wird.«<br />
13.2 »Trigger«<br />
Bisher haben wir Datenbankensysteme als mehr o<strong><strong>de</strong>r</strong> weniger passive Softwaresysteme<br />
kennen gelernt. E<strong>in</strong>e Aktion wird von <strong><strong>de</strong>r</strong> Datenbank dann ausgeführt, wenn<br />
man es ihr explizit mitteilt. Trigger bieten nun die Möglichkeit, SQL-Anweisungen<br />
automatisch ausführen zu lassen, wenn <strong>in</strong> e<strong>in</strong>e Tabelle e<strong>in</strong> neuer Datensatz e<strong>in</strong>gefügt<br />
o<strong><strong>de</strong>r</strong> e<strong>in</strong> Datensatz geän<strong><strong>de</strong>r</strong>t o<strong><strong>de</strong>r</strong> gelöscht wird. In diesem Fall übernim<strong>mt</strong> das Datenbanksystem<br />
e<strong>in</strong>e aktive Rolle. Deshalb unterschei<strong>de</strong>t man häufig auch zwischen akti-<br />
209
210<br />
13 Trigger<br />
ven und passiven Datenbanksystemen, je nach<strong>de</strong>m ob das Datenbanksystem auch<br />
selbstständig SQL-Anweisungen ausführen kann o<strong><strong>de</strong>r</strong> nicht.<br />
Der Begriff »Trigger« stam<strong>mt</strong> aus <strong>de</strong>m Englischen und heißt übersetzt »Gewehrabzug« .<br />
Man spricht häufig davon, dass e<strong>in</strong> RDBMS »Trigger abfeuert« . Diese sehr dramatische<br />
Wortwahl soll ver<strong>de</strong>utlichen, dass e<strong>in</strong> RDBMS auf Ereignisse reagiert und Prozeduren<br />
selbstständig ausführt. Dadurch bieten Trigger die Möglichkeit, komplizierte Integritätsbed<strong>in</strong>gungen<br />
<strong>in</strong> e<strong>in</strong>er Datenbank abzubil<strong>de</strong>n. Daneben können Trigger auch e<strong>in</strong>gesetzt<br />
wer<strong>de</strong>n, um Än<strong><strong>de</strong>r</strong>ungen an Tabellen zu protokollieren.<br />
13.3 Erzeugen e<strong>in</strong>es »Triggers«<br />
Um e<strong>in</strong>e Trigger-Prozedur zu erzeugen, verwen<strong>de</strong>t man die SQL-Anweisung CREATE<br />
TRIGGER und um diese wie<strong><strong>de</strong>r</strong> zu löschen, natürlich die SQL-Anweisung DROP<br />
TRIGGER.<br />
Beim Erzeugen gibt man <strong>de</strong>m Trigger e<strong>in</strong>en Namen und bestim<strong>mt</strong>, für welche Tabelle<br />
dieser Trigger aufgerufen wer<strong>de</strong>n soll. Nach Angabe <strong>de</strong>s Tabellennamens wird über die<br />
Schlüsselwörter BEFORE und AFTER festgelegt, ob die Prozedur vor <strong><strong>de</strong>r</strong> Datenän<strong><strong>de</strong>r</strong>ung<br />
o<strong><strong>de</strong>r</strong> danach ausgeführt wer<strong>de</strong>n soll. Darauf folgen schließlich e<strong>in</strong>es o<strong><strong>de</strong>r</strong> mehrere<br />
<strong><strong>de</strong>r</strong> Schlüsselwörter INSERT, DELETE o<strong><strong>de</strong>r</strong> UPDATE, je nach<strong>de</strong>m aufgrund welchen<br />
Ereignisses die Trigger-Prozedur aufgerufen wer<strong>de</strong>n soll.<br />
Der allgeme<strong>in</strong>e Aufbau zum Erzeugen e<strong>in</strong>es Triggers sieht folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
CREATE TRIGGER <br />
BEFORE | AFTER<br />
INSERT | DELETE | UPDATE[ OF (Spaltenliste)]<br />
ON [REFERENCING {OLD | NEW} {ROW |TABLE} [AS] <br />
[ FOR EACH { ROW | STATEMENT ]<br />
BEGIN<br />
...<br />
Wie man <strong>de</strong>m Aufbau entnehmen kann, folgen nach <strong><strong>de</strong>r</strong> Angabe <strong><strong>de</strong>r</strong> Ereignisse die<br />
Schlüsselwörter FOR EACH ROW o<strong><strong>de</strong>r</strong> FOR EACH STATEMENT. Wenn man z.B. mit<br />
<strong><strong>de</strong>r</strong> SQL-Anweisung DELETE Datensätze löscht, so kann es se<strong>in</strong>, dass davon mehrere<br />
Datensätze betroffen s<strong>in</strong>d, also mehrere Datensätze gelöscht wer<strong>de</strong>n. Gibt man FOR<br />
EACH STATEMENT an, so wird <strong><strong>de</strong>r</strong> Trigger nur e<strong>in</strong>mal aufgerufen, egal wie viele<br />
Datensätze gelöscht wer<strong>de</strong>n sollen. Wird dagegen FOR EACH ROW verwen<strong>de</strong>t, so<br />
wird <strong><strong>de</strong>r</strong> Trigger für je<strong>de</strong>n zu löschen<strong>de</strong>n Datensatz aufgerufen.<br />
Um zu ermitteln, welche Datensätze e<strong>in</strong>gefügt, gelöscht o<strong><strong>de</strong>r</strong> geän<strong><strong>de</strong>r</strong>t wer<strong>de</strong>n, erzeugt<br />
das RDBMS e<strong>in</strong>e sche<strong>in</strong>bare Tabelle, <strong>in</strong> <strong><strong>de</strong>r</strong> diese Datensätze enthalten s<strong>in</strong>d. Über das<br />
Schlüsselwort REFERENCING kann auf diese Datensätze zugegriffen wer<strong>de</strong>n, <strong>in</strong><strong>de</strong>m<br />
man e<strong>in</strong>en Namen für diese sche<strong>in</strong>bare Tabelle vergibt.
Erzeugen e<strong>in</strong>es »Triggers«<br />
Sehen wir uns hierzu nun e<strong>in</strong> Beispiel an. Immer wenn <strong>in</strong> die Tabelle »K<strong>in</strong>d« e<strong>in</strong> Datensatz<br />
e<strong>in</strong>gefügt wird, soll überprüft wer<strong>de</strong>n, ob das angegebene Geburtsdatum <strong>de</strong>s K<strong>in</strong><strong>de</strong>s<br />
auch nicht <strong>in</strong> <strong><strong>de</strong>r</strong> Zukunft liegt.<br />
CREATE TRIGGER K<strong>in</strong>dPruefGeburtsdatum<br />
BEFORE INSERT ON K<strong>in</strong>d REFERENCING NEW ROW AS neuerSatz<br />
FOR EACH ROW<br />
BEGIN<br />
IF neuerSatz.Geburtsdatum >= CURRENT_TIMESTAMP THEN<br />
ROLLBACK;<br />
END IF;<br />
END<br />
Über CREATE TRIGGER erzeugen wir e<strong>in</strong>en Trigger mit <strong>de</strong>m Namen »K<strong>in</strong>dPruef-<br />
Geburtsdatum« . Die Trigger-Prozedur soll bei je<strong>de</strong>m E<strong>in</strong>fügen e<strong>in</strong>es Datensatzes <strong>in</strong> die<br />
Tabelle »K<strong>in</strong>d« ausgeführt wer<strong>de</strong>n. Über das Schlüsselwort BEFORE legen wir fest, dass<br />
<strong><strong>de</strong>r</strong> Datensatz zum Zeitpunkt <strong>de</strong>s Aufrufes noch nicht <strong>in</strong> die Datenbank e<strong>in</strong>gefügt<br />
wur<strong>de</strong>. Dadurch haben wir die Möglichkeit über ROLLBACK das E<strong>in</strong>fügen zu verh<strong>in</strong><strong><strong>de</strong>r</strong>n.<br />
Da wir <strong>in</strong> diesem Trigger ausschließlich auf das E<strong>in</strong>fügen von Datensätzen reagieren,<br />
kann h<strong>in</strong>ter REFERENCING nur das Schlüsselwort NEW folgen. OLD wird dann<br />
verwen<strong>de</strong>t, wenn man auf die Daten e<strong>in</strong>es zu löschen<strong>de</strong>n Datensatzes zugreifen möchte,<br />
also bei E<strong>in</strong>treten <strong>de</strong>s Ereignisses DELETE. Reagiert man dagegen auf e<strong>in</strong>e Än<strong><strong>de</strong>r</strong>ung<br />
e<strong>in</strong>es Datensatzes, so gibt NEW die geän<strong><strong>de</strong>r</strong>ten Daten an und OLD die bisherigen Daten.<br />
Sehen wir uns hierzu e<strong>in</strong> weiteres Beispiel an: Wir wollen je<strong>de</strong> Än<strong><strong>de</strong>r</strong>ung am Geburtsdatum<br />
<strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle K<strong>in</strong>d <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle Protokoll mitprotokollieren. Die Tabelle Protokoll<br />
soll die Spalten GeburtsdatumAlt, GeburtsdatumNeu, Benutzer und Datum enthalten.<br />
In <strong>de</strong>n ersten bei<strong>de</strong>n Spalten soll das bisherige und das neue Geburtsdatum<br />
festgehalten wer<strong>de</strong>n. In <strong><strong>de</strong>r</strong> Spalte Benutzer soll <strong><strong>de</strong>r</strong> Name <strong>de</strong>sjenigen, <strong><strong>de</strong>r</strong> die Än<strong><strong>de</strong>r</strong>ung<br />
vorgenommen hat und <strong>in</strong> <strong><strong>de</strong>r</strong> Spalte Datum <strong><strong>de</strong>r</strong> Zeitpunkt <strong><strong>de</strong>r</strong> Än<strong><strong>de</strong>r</strong>ung gespeichert<br />
wer<strong>de</strong>n. Da wir nur protokollieren und die Daten nicht auf Gültigkeit prüfen, soll<br />
<strong><strong>de</strong>r</strong> Trigger erst nach Ausführen <strong><strong>de</strong>r</strong> Än<strong><strong>de</strong>r</strong>ung aufgerufen wer<strong>de</strong>n. Das Erzeugen <strong>de</strong>s<br />
Triggers sieht also folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
CREATE TRIGGER ProtokolliereAen<strong><strong>de</strong>r</strong>ungGeburtsdatum<br />
AFTER UPDATE ON K<strong>in</strong>d REFERENCING NEW ROW AS neuerSatz<br />
OLD ROW AS alterSatz<br />
FOR EACH ROW<br />
BEGIN<br />
...<br />
In »neuerSatz« bef<strong>in</strong><strong>de</strong>t sich <strong><strong>de</strong>r</strong> Datensatz nach <strong><strong>de</strong>r</strong> Än<strong><strong>de</strong>r</strong>ung und <strong>in</strong> »alterSatz« <strong><strong>de</strong>r</strong><br />
Datensatz vor <strong><strong>de</strong>r</strong> Än<strong><strong>de</strong>r</strong>ung. Also verwen<strong>de</strong>n wir die INSERT-Anweisung, um das<br />
bisherige und das neue Geburtsdatum <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »Protokoll« zu speichern:<br />
INSERT INTO Protokoll<br />
VALUES (alterSatz.Geburtsdatum, neuerSatz.Geburtsdatum,<br />
CURRENT_USER, CURRENT_TIMESTAMP);<br />
END<br />
211
212<br />
13 Trigger<br />
Immer wenn FOR EACH ROW verwen<strong>de</strong>t wird, kann man h<strong>in</strong>ter REFERENCING<br />
auch nur auf e<strong>in</strong>e Zeile referenzieren, da ja <strong><strong>de</strong>r</strong> Trigger für je<strong>de</strong> Zeile e<strong>in</strong>zeln aufgerufen<br />
wird. Verwen<strong>de</strong>t man dagegen FOR EACH STATEMENT, so muss man bei REFEREN-<br />
CING entsprechend NEW bzw. OLD TABLE angeben. In diesem Fall verweist man auf<br />
alle geän<strong><strong>de</strong>r</strong>ten bzw. gelöschten Datensätze. Betrachten wir hierzu das Beispiel noch<br />
e<strong>in</strong>mal, wollen aber diesmal <strong>de</strong>n Trigger nur für je<strong>de</strong> Anweisung e<strong>in</strong>mal aufrufen lassen.<br />
Die Trigger-Prozedur wür<strong>de</strong> dann folgen<strong><strong>de</strong>r</strong>maßen aussehen:<br />
CREATE TRIGGER ProtokolliereAen<strong><strong>de</strong>r</strong>ungGeburtsdatum<br />
AFTER UPDATE ON K<strong>in</strong>d REFERENCING NEW TABLE AS neueSaetze<br />
OLD TABLE AS alteSaetze<br />
FOR EACH STATEMENT<br />
BEGIN<br />
INSERT INTO Protokoll(GeburtsdatumAlt, GeburtsdatumNeu,<br />
Benutzer, Datum)<br />
SELECT alteSaetze.Geburtsdatum, neueSaetze.Geburtsdatum,<br />
CURRENT_USER, CURRENT_TIMESTAMP<br />
FROM alteSaetze JOIN neueSaetze USING(Kun<strong>de</strong>nnummer, Vorname);<br />
END<br />
Im Gegensatz zu unserem vorherigen Trigger wird die Prozedur diesmal für je<strong>de</strong><br />
Anweisung nur e<strong>in</strong>mal aufgerufen. Trigger, die pro Datensatz aufgerufen wer<strong>de</strong>n, s<strong>in</strong>d<br />
zwar e<strong>in</strong>facher zu programmieren, dafür beanspruchen sie <strong>in</strong> <strong><strong>de</strong>r</strong> Regel aber auch das<br />
RDBMS mehr.<br />
Da Trigger nicht explizit aufgerufen wer<strong>de</strong>n, sollte man darauf achten, Trigger so zu<br />
programmieren, dass ihre Ausführungszeit möglichst kurz bleibt. Wer<strong>de</strong>n beim<br />
Löschen e<strong>in</strong>es Datensatzes langwierige Berechnungen <strong>in</strong>nerhalb e<strong>in</strong>es Triggers von<br />
mehreren M<strong>in</strong>uten durchgeführt, so dauert natürlich auch das Löschen dieses e<strong>in</strong>en<br />
Datensatzes mehrere M<strong>in</strong>uten. Außer<strong>de</strong>m kann e<strong>in</strong> Trigger, <strong><strong>de</strong>r</strong> nach Ausführen e<strong>in</strong>er<br />
Aktion (also mit AFTER <strong>de</strong>klariert ist) aufgerufen wird, natürlich nicht zur Überprüfung<br />
von Daten verwen<strong>de</strong>t wer<strong>de</strong>n. Dementsprechend kann man bei e<strong>in</strong>em AFTER-<br />
Trigger ke<strong>in</strong> ROLLBACK verwen<strong>de</strong>n.<br />
13.4 Zusammenfassung<br />
In diesem Kapitel haben wir gesehen, dass e<strong>in</strong> RDBMS durch Trigger auch selbst aktiv<br />
wer<strong>de</strong>n kann. Trigger s<strong>in</strong>d auf <strong>de</strong>m RDBMS-Server gespeicherte Prozeduren, die bei<br />
e<strong>in</strong>er Datenän<strong><strong>de</strong>r</strong>ung e<strong>in</strong>er Tabelle automatisch vom RDBMS aufgerufen wer<strong>de</strong>n. Der<br />
Hauptzweck von Triggern dient vorwiegend <strong><strong>de</strong>r</strong> Abbildung komplizierter Geschäftsregeln,<br />
die man über normale Integritätsbed<strong>in</strong>gungen nicht mehr ohne weiteres abbil<strong>de</strong>n<br />
kann.<br />
Der allgeme<strong>in</strong>e Aufbau <strong><strong>de</strong>r</strong> Anweisung zum Erzeugen e<strong>in</strong>es Triggers sieht folgen<strong><strong>de</strong>r</strong>maßen<br />
aus:
Aufgaben<br />
CREATE TRIGGER <br />
BEFORE | AFTER<br />
INSERT | DELETE | UPDATE[ OF (Spaltenliste)]<br />
ON [REFERENCING {OLD | NEW} {ROW |TABLE} [AS] <br />
[ FOR EACH { ROW | STATEMENT ]<br />
Neben e<strong>in</strong>er Bezeichnung für <strong>de</strong>n Trigger muss angegeben wer<strong>de</strong>n, ob <strong><strong>de</strong>r</strong> Trigger vor<br />
o<strong><strong>de</strong>r</strong> nach Ausführen <strong><strong>de</strong>r</strong> Datenän<strong><strong>de</strong>r</strong>ung aufgerufen wer<strong>de</strong>n soll (BEFORE o<strong><strong>de</strong>r</strong><br />
AFTER). Weiterh<strong>in</strong> muss spezifiziert wer<strong>de</strong>n, bei welchen DML-Anweisungen <strong><strong>de</strong>r</strong> Trigger<br />
aufgerufen wer<strong>de</strong>n soll (INSERT, DELETE, UPDATE). Soll <strong><strong>de</strong>r</strong> Trigger bei e<strong>in</strong>em<br />
UPDATE aufgerufen wer<strong>de</strong>n, so kann <strong><strong>de</strong>r</strong> Trigger entwe<strong><strong>de</strong>r</strong> auf die Än<strong><strong>de</strong>r</strong>ung aller<br />
o<strong><strong>de</strong>r</strong> ganz bestim<strong>mt</strong>er Spalten reagieren. Dazu führt man h<strong>in</strong>ter <strong>de</strong>m Schlüsselwort<br />
UPDATE die gewünschten Spalten auf. Über das Schlüsselwort ON gibt man an, auf<br />
welche Tabelle <strong><strong>de</strong>r</strong> Trigger sich bezieht. Über OLD und NEW schließlich kann auf die<br />
neuen bzw. die bisherigen Werte zugegriffen wer<strong>de</strong>n.<br />
E<strong>in</strong> Trigger wird bei e<strong>in</strong>er Datenän<strong><strong>de</strong>r</strong>ung entwe<strong><strong>de</strong>r</strong> für je<strong>de</strong>n geän<strong><strong>de</strong>r</strong>ten Datensatz<br />
e<strong>in</strong>zeln (FOR EACH ROW) o<strong><strong>de</strong>r</strong> für e<strong>in</strong>e e<strong>in</strong>zelne DML-Anweisung (FOR EACH<br />
STATEMENT) aufgerufen.<br />
13.5 Aufgaben<br />
Wie<strong><strong>de</strong>r</strong>holungsfragen<br />
1) Wie muss die REFERENCING-Klausel lauten, wenn FOR EACH STATEMENT angegeben<br />
wur<strong>de</strong>?<br />
2) Wie muss die REFERENCING-Klausel lauten, wenn FOR EACH ROW angegeben<br />
wur<strong>de</strong>?<br />
3) Sie wollen e<strong>in</strong>en Trigger schreiben, <strong><strong>de</strong>r</strong> auf das Löschen von Datensätzen reagiert.<br />
Wie können Sie im Trigger auf die zu löschen<strong>de</strong>n Daten zugreifen? Geben Sie e<strong>in</strong><br />
Beispiel für die REFERENCING-Klausel!<br />
4) Sie wollen e<strong>in</strong>en Trigger schreiben, <strong><strong>de</strong>r</strong> auf das E<strong>in</strong>fügen von Datensätzen reagiert.<br />
Wie können Sie im Trigger auf die e<strong>in</strong>zufügen<strong>de</strong>n Daten zugreifen? Geben Sie e<strong>in</strong><br />
Beispiel für die REFERENCING-Klausel!<br />
5) Wor<strong>in</strong> bestehen Vor- und Nachteile <strong><strong>de</strong>r</strong> Schlüsselwörter FOR EACH ROW bzw.<br />
FOR EACH STATEMENT?<br />
6) Was ist mit e<strong>in</strong>em aktiven Datenbanksystem geme<strong>in</strong>t?<br />
Übungen<br />
1) Erweitern Sie <strong>de</strong>n Trigger »K<strong>in</strong>dPruefGeburtsdatum« so, dass auch überprüft wird,<br />
ob das Geburtsdatum <strong>de</strong>s K<strong>in</strong><strong>de</strong>s aktueller als das <strong>de</strong>s dazugehörigen Elternteils<br />
ist!<br />
2) Schreiben Sie e<strong>in</strong>en Trigger »K<strong>in</strong>dPruefGeburtsdatum2« , <strong><strong>de</strong>r</strong> bei Än<strong><strong>de</strong>r</strong>ung e<strong>in</strong>es<br />
Datensatzes <strong>in</strong> <strong><strong>de</strong>r</strong> K<strong>in</strong>d-Tabelle das zu än<strong><strong>de</strong>r</strong>n<strong>de</strong> Geburtsdatum auf Plausibilität<br />
überprüft!<br />
213
214<br />
13 Trigger<br />
3) Schreiben Sie e<strong>in</strong>en Trigger »PruefSitzplatzFrei« , <strong><strong>de</strong>r</strong> bei E<strong>in</strong>fügen e<strong>in</strong>es Bestellpostens<br />
überprüft, ob <strong><strong>de</strong>r</strong> gewünschte Sitzplatz frei ist. Ist <strong><strong>de</strong>r</strong> Sitzplatz nicht als »frei«<br />
gekennzeichnet, soll das E<strong>in</strong>fügen verh<strong>in</strong><strong><strong>de</strong>r</strong>t wer<strong>de</strong>n!<br />
4) Schreiben Sie e<strong>in</strong>en Trigger »PruefVorstellungsTerm<strong>in</strong>« , <strong><strong>de</strong>r</strong> bei E<strong>in</strong>fügen e<strong>in</strong>es Bestellposten<br />
überprüft, ob <strong><strong>de</strong>r</strong> Term<strong>in</strong> <strong><strong>de</strong>r</strong> gewünschten Vorstellung nicht <strong>in</strong> <strong><strong>de</strong>r</strong> Vergangenheit<br />
liegt!<br />
5) Verh<strong>in</strong><strong><strong>de</strong>r</strong>n Sie über e<strong>in</strong>en Trigger, dass bei E<strong>in</strong>fügen o<strong><strong>de</strong>r</strong> Än<strong><strong>de</strong>r</strong>n e<strong>in</strong>es neuen Mitarbeiter-Datensatzes<br />
das Gehalt <strong>de</strong>s Mitarbeiters nicht höher ist als das Gehalt <strong>de</strong>s<br />
Geschäftsführers, Herrn Kowalski!<br />
6) Überprüfen Sie über e<strong>in</strong>en Trigger bei E<strong>in</strong>fügen o<strong><strong>de</strong>r</strong> Än<strong><strong>de</strong>r</strong>n e<strong>in</strong>es Datensatzes <strong>in</strong><br />
die Tabelle »Sitzplatz« , ob <strong><strong>de</strong>r</strong> Preis gleich ist, wenn es sich bei e<strong>in</strong>er Vorstellung um<br />
die gleiche Veranstaltung im gleichen Haus han<strong>de</strong>lt. Ist <strong><strong>de</strong>r</strong> Preis nicht gleich, so soll<br />
<strong>in</strong> die Spalte Beschreibung <strong><strong>de</strong>r</strong> Tabelle »Problem« e<strong>in</strong>e Zeichenkette e<strong>in</strong>gefügt wer<strong>de</strong>n,<br />
die das Problem beschreibt! (H<strong>in</strong>weis: Legen Sie vorher e<strong>in</strong>e Tabelle »Problem«<br />
an, die aus e<strong>in</strong>er Spalte <strong>de</strong>s Datentyps VARCHAR(250) besteht.)
14<br />
»User Def<strong>in</strong>ed Types«<br />
(UDT)<br />
In Kapitel 14 sollen folgen<strong>de</strong> Fragen geklärt wer<strong>de</strong>n:<br />
� Was ist mit objektorientiert und objektrelational geme<strong>in</strong>t?<br />
� Wie sieht die Zukunft relationaler Datenbanksysteme aus?<br />
� Was s<strong>in</strong>d benutzer<strong>de</strong>f<strong>in</strong>ierte Typen (»User Def<strong>in</strong>ed Types«)?<br />
� Was s<strong>in</strong>d Metho<strong>de</strong>n?<br />
14.1 Motivation<br />
Frau Kart ist zwar zufrie<strong>de</strong>n mit <strong><strong>de</strong>r</strong> enstan<strong>de</strong>nen Datenbank, <strong>de</strong>nnoch bemängelt sie,<br />
dass sie o<strong><strong>de</strong>r</strong> ihre Kollegen direkt SQL-Anweisungen e<strong>in</strong>geben müssen. Also vere<strong>in</strong>bart<br />
sie e<strong>in</strong>en Term<strong>in</strong> mit Herrn Fleissig von <strong><strong>de</strong>r</strong> Unternehmensberatung und ihrem<br />
Geschäftsführer.<br />
Aus <strong>de</strong>m Gespräch ergibt sich, dass die Unternehmensberatung e<strong>in</strong>en neuen Auftrag<br />
zur Entwicklung e<strong>in</strong>es Programmes erhalten soll. Dieses Programm soll unter <strong>de</strong>m<br />
Betriebssystem W<strong>in</strong>dows lauffähig se<strong>in</strong> und die Funktionalitäten e<strong>in</strong>es Abrechnungssystems<br />
für E<strong>in</strong>trittskarten enthalten.<br />
Herr Fleissig, erfreut darüber, e<strong>in</strong>en neuen Auftrag aquiriert zu haben, benachrichtigt<br />
nach <strong>de</strong>m Gespräch se<strong>in</strong>en Geschäftsführer: »Herr Warner, wir sollen für »KartoF<strong>in</strong>ale«<br />
e<strong>in</strong> Programm zur Abrechnung erstellen. Ich wür<strong>de</strong> folgen<strong>de</strong>n Ablauf empfehen:<br />
Zunächst ermittle ich <strong>in</strong> <strong>de</strong>n nächsten vier Wochen die Anfor<strong><strong>de</strong>r</strong>ungen an das Programm<br />
und wer<strong>de</strong> unser UML-Datenmo<strong>de</strong>ll um Funktionen erweitern, so dass wir<br />
Daten- und Funktionsmo<strong>de</strong>ll dann vorliegen haben. Danach wer<strong>de</strong> ich mit <strong>de</strong>m Entwicklungsleiter<br />
unserer Softwareabteilung sprechen und ihm empfehlen, die meisten<br />
<strong><strong>de</strong>r</strong> Funktionen auf <strong>de</strong>m RDBMS selbst zu entwickeln. Inzwischen bietet SQL nämlich<br />
mit <strong>de</strong>m neuen Standard hervorragen<strong>de</strong> Eigenschaften, um objektorientiert mit SQL zu<br />
entwickeln. Das W<strong>in</strong>dows-Programm selbst sollte unser neuer Kollege, Herr Klever, <strong>in</strong><br />
C++ entwickeln. Über C++ kann er dann die Funktionen auf <strong>de</strong>m RDBMS-Server<br />
direkt aufrufen.«<br />
14.2 Objektorientierung<br />
Die Kapitel 6 bis 13 stellen auch die geschichtliche Entstehung von SQL dar. Zuerst<br />
wur<strong>de</strong> SQL als re<strong>in</strong>e Datenbankabfragesprache entworfen. Sie sollte dazu dienen, dass<br />
Anwen<strong><strong>de</strong>r</strong> selbst SQL-Anweisungen e<strong>in</strong>geben und Ergebnisse vom RDBMS zurücker-<br />
215
216<br />
14 »User Def<strong>in</strong>ed Types« (UDT)<br />
halten. In diesem ersten Schritt war SQL e<strong>in</strong>e re<strong>in</strong> <strong>de</strong>klarative Programmiersprache,<br />
zwar leistungsfähig, aber teilweise nicht beson<strong><strong>de</strong>r</strong>s flexibel.<br />
Das än<strong><strong>de</strong>r</strong>te sich 1996 durch nachträgliches H<strong>in</strong>zufügen prozeduraler Sprachelemente<br />
zum SQL-92 Standard. SQL war nun sowohl e<strong>in</strong>e <strong>de</strong>klarative als auch e<strong>in</strong>e prozedurale<br />
Sprache. SQL wur<strong>de</strong> jetzt selten von Endanwen<strong><strong>de</strong>r</strong>n selbst verwen<strong>de</strong>t. Vielmehr wur<strong>de</strong><br />
es zur Entwicklung von Softwareprogrammen benutzt. Dazu wur<strong>de</strong>n SQL-Anweisungen<br />
<strong>in</strong> an<strong><strong>de</strong>r</strong>e Programmiersprachen wie C, C++, Java, Pascal o<strong><strong>de</strong>r</strong> Visual Basic e<strong>in</strong>gebettet<br />
und von <strong>de</strong>m Anwendungsprogramm an <strong>de</strong>n RDBMS-Server gesen<strong>de</strong>t, um von<br />
diesem e<strong>in</strong>e Ergebnistabelle zu erhalten.<br />
Inzwischen hatte sich aber auch schon e<strong>in</strong> an<strong><strong>de</strong>r</strong>es Programmierkonzept durchgesetzt,<br />
die objektorientierte Programmierung. Die meisten Än<strong><strong>de</strong>r</strong>ungen bzw. Erweiterungen<br />
am SQL-Standard im Jahr 1999 betrafen <strong>de</strong>shalb vorwiegend die Erweiterung von SQL<br />
um objektorientierte Eigenschaften. SQL als objektorientierte Sprache ist für <strong>de</strong>n<br />
Anwenungsentwickler sicherlich von größerer Be<strong>de</strong>utung als für <strong>de</strong>n Endanwen<strong><strong>de</strong>r</strong>,<br />
zumal Endanwen<strong><strong>de</strong>r</strong> SQL heutzutage <strong>in</strong> <strong><strong>de</strong>r</strong> Regel nicht mehr direkt nutzen. Zu diesem<br />
Zeitpunkt gab es bereits re<strong>in</strong> objektorientierte Datenbanksysteme. Diese enthielten<br />
eigene Datenbanksprachen zum Abfragen <strong><strong>de</strong>r</strong> Datenbank. Da man mit SQL:1999 auch<br />
weiterh<strong>in</strong> <strong>de</strong>klarativ und prozedural entwickeln kann, wer<strong>de</strong>n Datenbanksysteme, die<br />
auf relationalen Datenbanken basieren, <strong>de</strong>shalb zur Unterscheidung nicht als objektorientierte,<br />
son<strong><strong>de</strong>r</strong>n als objektrelationale Datenbanksysteme bezeichnet. Die häufig anzutreffen<strong>de</strong><br />
Me<strong>in</strong>ung, SQL:1999 sei <strong>de</strong>shalb nicht objektorientiert, ist schlichtweg falsch.<br />
SQL:1999 enthält alle wesentlichen Eigenschaften, die e<strong>in</strong>e objektorientierte Sprache<br />
ausmachen. Dennoch ist zu anzumerken, dass alle bekannten RDBMS-Produkte die<br />
objektorientierten Eigenschaften von SQL:1999 bis zum jetzigen Zeitpunkt noch gar<br />
nicht o<strong><strong>de</strong>r</strong> nicht vollständig ab<strong>de</strong>cken (am nächsten kom<strong>mt</strong> IBM DB2 hier sicherlich<br />
<strong>de</strong>m SQL:1999 Standard). Dieses Kapitel soll <strong>de</strong>shalb mehr als Überblick dienen, wie<br />
die objektorientierten Eigenschaften zukünftig <strong>in</strong> <strong>de</strong>n RDBMS-Produkten aussehen<br />
wer<strong>de</strong>n. Bevor wir uns dies <strong>in</strong> SQL selbst ansehen, folgt e<strong>in</strong>e kurze E<strong>in</strong>führung <strong>in</strong> das<br />
Thema Objektorientierung. Wer sich bereits mit objektorientierten Konzepten auskennt,<br />
kann <strong>de</strong>n Rest dieses Abschnitts also überspr<strong>in</strong>gen.<br />
Bis zum Kapitel 11 haben wir gesehen, wie man <strong>in</strong> SQL Daten e<strong>in</strong>fügt, än<strong><strong>de</strong>r</strong>t und<br />
abfragt. Wir haben SQL bis dah<strong>in</strong> ausschließlich von <strong><strong>de</strong>r</strong> Datensicht betrachtet. In Kapitel<br />
12 wur<strong>de</strong> die Entwicklung von Rout<strong>in</strong>en <strong>in</strong> SQL vorgestellt. In diesem Fall haben<br />
wir die Datensicht vernachlässigt und und uns auf die Funktionssicht konzentriert.<br />
Objektorientierung fasst nun Daten und Funktionen zu e<strong>in</strong>er E<strong>in</strong>heit, e<strong>in</strong>em Objekt,<br />
zusammen. E<strong>in</strong> Objekt entspricht, wie wir es bereits <strong>in</strong> ersten Kapiteln zur Datenmo<strong>de</strong>llierung<br />
kennen gelernt haben, weitgehend e<strong>in</strong>er Entität. Im Gegensatz zur Entität<br />
wird e<strong>in</strong> Objekt aber eben nicht nur durch Daten bzw. Attribute beschrieben, son<strong><strong>de</strong>r</strong>n<br />
auch durch Funktionen, die dieses Objekt ausführen kann. Funktionen, die an e<strong>in</strong><br />
Objekt gebun<strong>de</strong>n s<strong>in</strong>d, wer<strong>de</strong>n zur Unterscheidung als Metho<strong>de</strong> bezeichnet.<br />
In Kapitel 3 haben wir zur Datenmo<strong>de</strong>llierung bereits die UML kennen gelernt. Dort<br />
wur<strong>de</strong> auch erwähnt, dass e<strong>in</strong> Objekt bzw. e<strong>in</strong>e Klasse durch e<strong>in</strong>e Rechteck dargestellt<br />
wird, das <strong>in</strong> drei Bereiche aufgeteilt ist. Im oberen Bereich ersche<strong>in</strong>t <strong><strong>de</strong>r</strong> Name <strong><strong>de</strong>r</strong><br />
Klasse, im mittleren Bereich die Attribute und im unteren Bereich die Metho<strong>de</strong>n. UML<br />
ist die e<strong>in</strong>zige Mo<strong>de</strong>llierung, die wir kennen gelernt haben, mit <strong><strong>de</strong>r</strong> man also sowohl
Objektorientierung<br />
Daten- als auch Funktionsmo<strong>de</strong>llierung vornehmen kann. Um die Konzepte <strong><strong>de</strong>r</strong><br />
Objektorientierung zu verstehen, verwen<strong>de</strong>n wir die Notation <strong><strong>de</strong>r</strong> UML. Betrachten<br />
wir hierzu aus unserem Fallbeispiel <strong>de</strong>n Objekttyp bzw. die Klasse Kun<strong>de</strong>. E<strong>in</strong> Kun<strong>de</strong><br />
besteht aus mehreren Attributen, wie »Name« , »Vorname« , »Strasse« , »Hausnummer« ,<br />
»Ort« usw. Aus <strong><strong>de</strong>r</strong> realen Welt wissen wir aber, dass e<strong>in</strong> Kun<strong>de</strong> auch bestim<strong>mt</strong>e Aktionen<br />
ausführt: Er kann e<strong>in</strong>e Bestellung aufgeben, er kann e<strong>in</strong> K<strong>in</strong>d bekommen, er kann<br />
umziehen und damit e<strong>in</strong>e neue Adresse erhalten usw. Objektorientiert heißt also: Man<br />
betrachtet nicht nur die Attribute e<strong>in</strong>es Objektes, son<strong><strong>de</strong>r</strong>n auch <strong>de</strong>ssen Funktionen. In<br />
e<strong>in</strong>em UML-Klassendiagramm wür<strong>de</strong> das dann folgen<strong><strong>de</strong>r</strong>maßen aussehen:<br />
������������� � �������<br />
����� � ������� ����<br />
�������� � ������� ����<br />
�������� � ������� ����<br />
����������� � ������� ���<br />
���� � �������<br />
���� � ������� �����<br />
�����<br />
+bestellt ( Datum : DATE ) : INTEGER<br />
+neuesK<strong>in</strong>d ( Vorname : VARCHAR(20), Geburtsdatum : DATE, Geschlecht VARCHAR(20) ) : BOOLEAN<br />
+neueAdresse ( Kun<strong>de</strong>nnummer INTEGER, NeueStrasse : VARCHAR(50), NeueHausnummer : VARCHAR(6),<br />
NeuePlz : VARCHAR(10), NeuerOrt : VARCHAR(200) : BOOLEAN<br />
Abbildung 14.1: Klasse »Kun<strong>de</strong>« mit Attributen und Metho<strong>de</strong>n<br />
Metho<strong>de</strong>n e<strong>in</strong>er Klasse verän<strong><strong>de</strong>r</strong>n nun <strong>in</strong> <strong><strong>de</strong>r</strong> Regel die zur Klasse gehörigen Attribute.<br />
Über e<strong>in</strong>e objektorientierte Sprache kann man Attribute als privat <strong>de</strong>klarieren, so dass<br />
diese nur von Metho<strong>de</strong>n <strong><strong>de</strong>r</strong> Klasse selbst geän<strong><strong>de</strong>r</strong>t wer<strong>de</strong>n können. Wollen Sie also<br />
<strong>de</strong>n Namen o<strong><strong>de</strong>r</strong> Vornamen e<strong>in</strong>es Kun<strong>de</strong>n än<strong><strong>de</strong>r</strong>n, so müssten Sie e<strong>in</strong>e Metho<strong>de</strong> »Aen<strong><strong>de</strong>r</strong>eName«<br />
erstellen. Diese Metho<strong>de</strong> kann dann auf die klasseneigenen Attribute<br />
zugreifen.<br />
Doch warum so umständlich, warum kann man nicht direkt auf die Attribute zugreifen<br />
und diese verän<strong><strong>de</strong>r</strong>n?<br />
Zwei wesentliche Grün<strong>de</strong> sprechen dagegen. Nehmen wir e<strong>in</strong>mal an, Sie haben e<strong>in</strong><br />
Anwendungsprogramm erstellt, <strong>in</strong> <strong><strong>de</strong>r</strong> an mehreren Stellen direkt auf das Attribut<br />
Postleitzahl <strong>de</strong>s Kun<strong>de</strong>n zugegriffen wird. Bisher haben wir dieses Attribut als Ganzzahl<br />
<strong>de</strong>klariert. Nun soll das Attribut Plz aber 8-stellig se<strong>in</strong> und alphanumerisch. Da<br />
Zeichenketten <strong>in</strong> SQL <strong>in</strong> Anführungsstrichen dargestellt wer<strong>de</strong>n, müssen nun überall<br />
dort, wo auf Plz verwiesen wird, Anführungsstriche verwen<strong>de</strong>t wer<strong>de</strong>n. Das kann bei<br />
e<strong>in</strong>er komplexen Anwendung sehr aufwändig und fehleranfällig se<strong>in</strong>.<br />
Betrachten wir nun <strong>de</strong>n an<strong><strong>de</strong>r</strong>en Fall: Än<strong><strong>de</strong>r</strong>ungen an <strong><strong>de</strong>r</strong> Postleitzahl erfolgen nur <strong>in</strong><br />
<strong><strong>de</strong>r</strong> Metho<strong>de</strong> »neueAdresse« selbst. Diesmal müssen Sie ihr Anwendungsprogramm<br />
nur an e<strong>in</strong>er Stelle än<strong><strong>de</strong>r</strong>n, nämlich <strong>in</strong> <strong><strong>de</strong>r</strong> Metho<strong>de</strong> »neueAdresse« . Sie sehen also, dass<br />
<strong><strong>de</strong>r</strong> Än<strong><strong>de</strong>r</strong>ungsaufwand wesentlich ger<strong>in</strong>ger und daher auch bei weitem nicht so fehleranfällig<br />
ist. Gera<strong>de</strong> bei sehr komplexen Anwendungen wird <strong><strong>de</strong>r</strong> Wartungsaufwand<br />
e<strong>in</strong>es Anwendungsprogramms erheblich m<strong>in</strong>imiert. Der zweite Grund, Attribute nicht<br />
direkt zu än<strong><strong>de</strong>r</strong>n, besteht <strong>in</strong> <strong><strong>de</strong>r</strong> Lesbarkeit <strong>de</strong>s Anwendungsprogramms. Verwen<strong>de</strong>t<br />
217
218<br />
14 »User Def<strong>in</strong>ed Types« (UDT)<br />
man e<strong>in</strong>e Metho<strong>de</strong> mit e<strong>in</strong>em <strong>de</strong>m Inhalt entsprechen<strong>de</strong>n Namen wie »neueAdresse« ,<br />
so ist <strong>de</strong>m Programmierer <strong>in</strong> <strong><strong>de</strong>r</strong> Regel klar, dass mit dieser Metho<strong>de</strong> die Adresse <strong>de</strong>s<br />
Kun<strong>de</strong>n geän<strong><strong>de</strong>r</strong>t wird. Das Programm wird dadurch besser verständlich und damit<br />
auch leichter wartbar.<br />
Doch das ist noch nicht alles, was Objektorientierung uns zu bieten hat! Schließlich<br />
könnten wir das oben beschriebene Problem ja auch durch Verwendung e<strong>in</strong>er gespeicherten<br />
Prozedur, wie wir sie <strong>in</strong> Kapitel 12 kennen gelernt haben, lösen. Rout<strong>in</strong>en wie<br />
<strong>in</strong> Kapitel 12 s<strong>in</strong>d jedoch nicht an bestim<strong>mt</strong>e Objekttypen gebun<strong>de</strong>n. Dadurch neigt<br />
man dazu, Funktionen zu schreiben, die sich auf mehrere Objekttypen beziehen. Dies<br />
ist <strong>de</strong>shalb nachteilig, weil man dann Programmzeilen erzeugt, die <strong>in</strong> <strong><strong>de</strong>r</strong> Regel nicht<br />
wie<strong><strong>de</strong>r</strong>verwendbar s<strong>in</strong>d, also von an<strong><strong>de</strong>r</strong>en Anwendungsprogrammen nicht e<strong>in</strong>gesetzt<br />
wer<strong>de</strong>n können. E<strong>in</strong> wesentlicher Punkt bei <strong><strong>de</strong>r</strong> Entstehung objektorientierter Sprachen<br />
ist also die Wie<strong><strong>de</strong>r</strong>verwendung und Wartbarkeit von Anwendungsprogrammen.<br />
Neben <strong><strong>de</strong>r</strong> Zusammengehörigkeit von Daten und Funktionen (Datenkapselung) wird<br />
dies auch erreicht durch die so genannte Vererbung. Betrachten wir hierzu wie<strong><strong>de</strong>r</strong><br />
unser Fallbeispiel: Neben <strong><strong>de</strong>r</strong> Klasse »Kun<strong>de</strong>« haben wir e<strong>in</strong>e weitere Klasse »Mitarbeiter«<br />
. Vergleichen wir diese bei<strong>de</strong>n Klassen mite<strong>in</strong>an<strong><strong>de</strong>r</strong>, so stellen wir fest, dass es viele<br />
Übere<strong>in</strong>stimmungen zwischen <strong>de</strong>n Attributen und Metho<strong>de</strong>n gibt, aber auch e<strong>in</strong>ige<br />
Spezialisierungen.<br />
Kun<strong>de</strong><br />
-Kun<strong>de</strong>nnummer : INTEGER<br />
-Name : VARCHAR (30)<br />
-Vorname : VARCHAR (20)<br />
-Strasse : VARCHAR (50)<br />
-Hausnummer : VARCHAR (6)<br />
-Plz : INTEGER<br />
-Ort : VARCHAR (200)<br />
+neueAdresse ( ) : BOOLEAN<br />
+bestellt ( ) : INTEGER<br />
+neuesK<strong>in</strong>d ( ) : BOOLEAN<br />
Mitarbeiter<br />
-Personalnummer : INTEGER<br />
-Name : VARCHAR (30)<br />
-Vorname : VARCHAR (20)<br />
-Strasse : VARCHAR (50)<br />
-Hausnummer : VARCHAR (6)<br />
-Plz : INTEGER<br />
-Ort : VARCHAR (200)<br />
-Abteilungsbezeichnung : VARCHAR (30)<br />
-Gehalt : DECIMAL (10,2)<br />
+neueAdresse ( ) : BOOLEAN<br />
+festlegenGehalt ( ) : BOOLEAN<br />
Abbildung 14.2: Gleiche Attribute und Metho<strong>de</strong>n zwischen »Kun<strong>de</strong>« – »Mitarbeiter«<br />
So kommen die Attribute »Kun<strong>de</strong>nnummer« bzw. »Personalnummer« , »Name« , »Vorname«<br />
und die Attribute für die Adresse <strong>in</strong> bei<strong>de</strong>n Klassen vor. »Mitarbeiter« hat dagegen<br />
zwei Attribute, die <strong>in</strong> <strong><strong>de</strong>r</strong> Klasse »Kun<strong>de</strong>« nicht vorkommen, nämlich »Abteilungsbezeichnung«<br />
und »Gehalt« . Bei <strong>de</strong>n Metho<strong>de</strong>n existiert »neueAdresse« <strong>in</strong> bei<strong>de</strong>n<br />
Klassen, ansonsten haben bei<strong>de</strong> Klassen weitere spezielle Metho<strong>de</strong>n.<br />
Bereits bei <strong><strong>de</strong>r</strong> Datenmo<strong>de</strong>llierung haben wir so etwas schon e<strong>in</strong>mal gesehen, nämlich<br />
bei Sub- und Supertypen. Da viele übere<strong>in</strong>stimmen<strong>de</strong> Merkmale zwischen <strong>de</strong>n Klassen<br />
existieren, können wir also e<strong>in</strong>e neue so genannte Oberklasse bil<strong>de</strong>n, die wir Person<br />
nennen. Person enthält nun alle Attribute und Metho<strong>de</strong>n, die sowohl <strong>in</strong> »Kun<strong>de</strong>« als<br />
auch <strong>in</strong> »Mitarbeiter« auftreten.
Kun<strong>de</strong><br />
+bestellt ( ) : INTEGER<br />
+neuesK<strong>in</strong>d ( ) : BOOLEAN<br />
Objektorientierung<br />
Person<br />
-Nummer : INTEGER<br />
-Name : VARCHAR (30)<br />
-Vorname : VARCHAR (20)<br />
-Strasse : VARCHAR (50)<br />
-Hausnummer : VARCHAR (6)<br />
-Plz : INTEGER<br />
-Ort : VARCHAR (200)<br />
+neueAdresse ( ) : BOOLEAN<br />
Mitarbeiter<br />
-Abteilungsbezeichnung : VARCHAR (30)<br />
-Gehalt : DECIMAL (10,2)<br />
+festlegenGehalt ( ) : BOOLEAN<br />
Abbildung 14.3: »Kun<strong>de</strong>« und »Mitarbeiter« »erben« von »Person«<br />
Die Klassen »Kun<strong>de</strong>« und »Mitarbeiter« »erben« also die Eigenschaften ihrer Oberklasse<br />
»Person« . Da die Metho<strong>de</strong> »neueAdresse« nur noch <strong>in</strong> »Person« vorkom<strong>mt</strong>,<br />
muss diese nur e<strong>in</strong>mal gespeichert wer<strong>de</strong>n und nicht wie zuvor redundant bei<br />
»Kun<strong>de</strong>« und »Mitarbeiter« . Vererbung dient also dazu, Verallgeme<strong>in</strong>erungen abzubil<strong>de</strong>n<br />
und dadurch <strong>de</strong>n Programmieraufwand zu m<strong>in</strong>imieren.<br />
Neben <strong><strong>de</strong>r</strong> Datenkapselung und <strong><strong>de</strong>r</strong> Vererbung besteht die letzte wesentliche Eigenschaft<br />
e<strong>in</strong>er objektorientierten Sprache <strong>in</strong> <strong><strong>de</strong>r</strong> Unterstützung <strong>de</strong>s Polymorphismus<br />
(»Vielgestaltigkeit« ). Wir wollen uns <strong>de</strong>n Polymorphismus wie<strong><strong>de</strong>r</strong> an unserem Fallbeispiel<br />
ansehen. Kun<strong>de</strong>n und Mitarbeiter sollen e<strong>in</strong>e Metho<strong>de</strong> »kuendigen« besitzen. Bei<br />
Aufruf <strong><strong>de</strong>r</strong> Metho<strong>de</strong> »kuendigen« <strong><strong>de</strong>r</strong> Klasse »Kun<strong>de</strong>« soll <strong><strong>de</strong>r</strong> Kun<strong>de</strong> aus <strong><strong>de</strong>r</strong> Datenbank<br />
gelöscht wer<strong>de</strong>n, <strong>in</strong>klusive <strong><strong>de</strong>r</strong> Datensätze <strong><strong>de</strong>r</strong> K<strong>in</strong><strong><strong>de</strong>r</strong> und se<strong>in</strong>er Bestellungen.<br />
Bei e<strong>in</strong>em Mitarbeiter dagegen, soll die Metho<strong>de</strong> »kuendigen« <strong>de</strong>n Datensatz aus <strong><strong>de</strong>r</strong><br />
Tabelle »Mitarbeiter« löschen und <strong>de</strong>n Fremdschlüssel <strong>in</strong> <strong><strong>de</strong>r</strong> Tabelle »Bestellung« auf<br />
NULL setzen. Obgleich die Metho<strong>de</strong> <strong>de</strong>n gleichen Namen hat, ist ihre Funktionalität<br />
unterschiedlich bzw. polymorph. Für unser UML-Diagramm be<strong>de</strong>utet dies, dass wir<br />
e<strong>in</strong>e zusätzliche Metho<strong>de</strong> »kuendigen« <strong>in</strong> »Person« e<strong>in</strong>tragen, aber auch <strong>in</strong> »Kun<strong>de</strong>«<br />
und »Mitarbeiter« . Der Programmco<strong>de</strong> dieser Metho<strong>de</strong> sieht bei bei<strong>de</strong>n Klassen natürlich<br />
unterschiedlich aus.<br />
Wir haben damit die wichtigsten Eigenschaften <strong><strong>de</strong>r</strong> Objektorientierung kennen gelernt:<br />
� Datenkapselung<br />
� Vererbung<br />
� Polymorphismus<br />
Wir wollen uns im Folgen<strong>de</strong>n ansehen, wie SQL:1999 diese Eigenschaften umgesetzt<br />
hat.<br />
219
14.3 Klassen<br />
220<br />
14 »User Def<strong>in</strong>ed Types« (UDT)<br />
Klassen wer<strong>de</strong>n <strong>in</strong> SQL:1999 im Gegensatz zu <strong>de</strong>n meisten an<strong><strong>de</strong>r</strong>en objektorientierten<br />
Sprachen nicht als Klassen, son<strong><strong>de</strong>r</strong>n als benutzer<strong>de</strong>f<strong>in</strong>ierte Typen (»User Def<strong>in</strong>ed<br />
Types« – UDT) bezeichnet. UDT's wer<strong>de</strong>n über die SQL-Anweisung CREATE TYPE<br />
erzeugt und über DROP TYPE wie<strong><strong>de</strong>r</strong> gelöscht. Zum Anlegen <strong><strong>de</strong>r</strong> Klasse »Person« lautet<br />
die SQL-Anweisung also folgen<strong><strong>de</strong>r</strong>maßen:<br />
CREATE TYPE cPerson AS<br />
(<br />
...<br />
Hier wur<strong>de</strong> bewusst das kle<strong>in</strong>e »c« vor <strong>de</strong>n Klassennamen gesetzt, um zwischen <strong><strong>de</strong>r</strong><br />
Klassen<strong>de</strong>f<strong>in</strong>ition und <strong><strong>de</strong>r</strong> eigentlichen späteren Tabelle, <strong>in</strong> <strong><strong>de</strong>r</strong> die Daten gespeichert<br />
wer<strong>de</strong>n sollen, zu unterschei<strong>de</strong>n. Innerhalb <strong><strong>de</strong>r</strong> CREATE TYPE-Anweisungen wer<strong>de</strong>n<br />
dann die Attribute <strong>de</strong>f<strong>in</strong>iert, so wie wir es von CREATE TABLE her kennen:<br />
CREATE TYPE cPerson AS<br />
(<br />
Nummer INTEGER,<br />
Name VARCHAR (30),<br />
Vorname VARCHAR (20),<br />
Strasse VARCHAR (50),<br />
Hausnummer VARCHAR (6),<br />
Plz INTEGER,<br />
Ort VARCHAR (200),<br />
...<br />
Bisher unterschei<strong>de</strong>t sich das Anlegen e<strong>in</strong>es benutzer<strong>de</strong>f<strong>in</strong>ierten Typs nicht son<strong><strong>de</strong>r</strong>lich<br />
vom Anlegen e<strong>in</strong>er Tabelle. E<strong>in</strong> wesentlicher Unterschied besteht jedoch jetzt schon:<br />
Das Anlegen e<strong>in</strong>es UDT's erzeugt ausschließlich e<strong>in</strong>e »Schablone« zum eigentlichen<br />
Anlegen e<strong>in</strong>er Tabelle. Letztendlich arbeitet e<strong>in</strong> RDBMS nur mit Tabellen, e<strong>in</strong> UDT<br />
kom<strong>mt</strong> also immer <strong>in</strong>nerhalb e<strong>in</strong>er CREATE TABLE-Anweisung vor. Bevor wir uns das<br />
allerd<strong>in</strong>gs ansehen, müssen wir erst e<strong>in</strong>mal unsere CREATE TYPE-Anweisung zu En<strong>de</strong><br />
schreiben. E<strong>in</strong>e wesentliche Eigenschaft <strong><strong>de</strong>r</strong> Klasse fehlt noch, nämlich se<strong>in</strong>e Metho<strong>de</strong>n.<br />
In unserem Fall hat »cPerson« nur die Metho<strong>de</strong> »neueAdresse« :<br />
CREATE TYPE cPerson AS<br />
(<br />
Nummer INTEGER,<br />
Name VARCHAR (30),<br />
Vorname VARCHAR (20),<br />
Strasse VARCHAR (50),<br />
Hausnummer VARCHAR (6),<br />
Plz INTEGER,<br />
Ort VARCHAR (200),<br />
METHOD neueAdresse( Nr INTEGER,<br />
NeueStrasse VARCHAR(50),
)<br />
Zugriff auf Attribute und Metho<strong>de</strong>n<br />
NeueHausnummer VARCHAR(6),<br />
NeuePlz INTEGER, NeuerOrt VARCHAR(200) )<br />
RETURNS BOOLEAN<br />
Damit haben wir <strong>de</strong>n UDT erzeugt. Allerd<strong>in</strong>gs haben wir noch nicht beschrieben, wie<br />
<strong><strong>de</strong>r</strong> Programmco<strong>de</strong> <strong><strong>de</strong>r</strong> Metho<strong>de</strong> »neueAdresse« <strong>de</strong>nn nun aussieht. E<strong>in</strong>e Metho<strong>de</strong><br />
wird ähnlich wie e<strong>in</strong>e Funktion erzeugt. Schließlich s<strong>in</strong>d Funktionen und Metho<strong>de</strong>n<br />
sehr ähnlich, mit <strong>de</strong>m Unterschied, dass Metho<strong>de</strong>n immer an e<strong>in</strong>en UDT gebun<strong>de</strong>n<br />
s<strong>in</strong>d. Zum Erzeugen e<strong>in</strong>er Metho<strong>de</strong> verwen<strong>de</strong>t man die SQL-Anweisung CREATE<br />
METHOD. Die SQL-Anweisungen dieser Metho<strong>de</strong> könnten folgen<strong><strong>de</strong>r</strong>maßen aussehen:<br />
CREATE METHOD neueAdresse(Nr INTEGER,<br />
NeueStrasse VARCHAR(50),<br />
NeueHausnummer VARCHAR(6),<br />
NeuePlz INTEGER, NeuerOrt VARCHAR(200) )<br />
RETURNS BOOLEAN FOR cPerson<br />
BEGIN<br />
UPDATE Person SET<br />
Strasse = NeueStrasse,<br />
Hausnummer = NeueHausnummer,<br />
Plz = NeuePlz,<br />
Ort = NeuerOrt<br />
WHERE Nummer = Nr;<br />
END;<br />
Zunächst wird nach CREATE METHOD noch e<strong>in</strong>mal <strong><strong>de</strong>r</strong> Aufbau <strong><strong>de</strong>r</strong> Metho<strong>de</strong> mit se<strong>in</strong>em<br />
Rückgabewert <strong>de</strong>klariert. Danach wird über das Schlüsselwort FOR festgelegt, an<br />
welchen UDT die Metho<strong>de</strong> gebun<strong>de</strong>n wer<strong>de</strong>n soll. Schließlich folgt <strong><strong>de</strong>r</strong> Anweisungsblock,<br />
<strong><strong>de</strong>r</strong> <strong>de</strong>n Programmco<strong>de</strong> <strong><strong>de</strong>r</strong> Metho<strong>de</strong> darstellt. In diesem Fall besteht die<br />
Metho<strong>de</strong> nur aus e<strong>in</strong>er SQL-Anweisung, die über UPDATE <strong>de</strong>n Datensatz än<strong><strong>de</strong>r</strong>t.<br />
Bisher haben wir ja nur e<strong>in</strong>e »Schablone« erzeugt, die man über CREATE TABLE verwen<strong>de</strong>n<br />
kann, um e<strong>in</strong>e Tabelle physikalisch zu erzeugen. Will man e<strong>in</strong>e Tabelle erzeugen,<br />
die auf e<strong>in</strong>em UDT basiert, so gibt man e<strong>in</strong>fach an:<br />
CREATE TABLE Person OF cPerson;<br />
Damit haben wir e<strong>in</strong>e Tabelle »Person« erzeugt, die die Attribute <strong><strong>de</strong>r</strong> Klasse »cPerson«<br />
und <strong>de</strong>ssen Metho<strong>de</strong>n enthält.<br />
14.4 Zugriff auf Attribute und Metho<strong>de</strong>n<br />
Doch wie fügt man nun Daten <strong>in</strong> e<strong>in</strong>e solche erzeugte Tabelle e<strong>in</strong> und wie kann man<br />
diese Daten über SELECT wie<strong><strong>de</strong>r</strong> ausgeben?<br />
221
222<br />
14 »User Def<strong>in</strong>ed Types« (UDT)<br />
Zum E<strong>in</strong>fügen von Daten <strong>in</strong> diese Tabelle muss man zunächst e<strong>in</strong>e Variable <strong><strong>de</strong>r</strong> Klasse<br />
cPerson <strong>de</strong>klarieren. Dieser Variablen weist man die Daten zu, die e<strong>in</strong>gefügt wer<strong>de</strong>n<br />
sollen und verwen<strong>de</strong>t diese Variable dann beim E<strong>in</strong>fügen:<br />
DECLARE p cPerson;<br />
SET p = cPerson();<br />
SET p.Nummer = 8;<br />
SET p.Name = 'Petri';<br />
SET p.Vorname = 'Paul';<br />
SET p.Strasse = 'Malerstr.';<br />
SET p.Hausnummer= '26';<br />
SET p.Plz = 22222;<br />
SET p.Ort = 'Karlstadt';<br />
INSERT INTO Person VALUES (p);<br />
Es gibt noch e<strong>in</strong>e etwas e<strong>in</strong>fachere Variante über das Schlüsselwort NEW. Damit sieht<br />
das Ganze folgen<strong><strong>de</strong>r</strong>maßen aus:<br />
INSERT INTO Person VALUES (NEW( 8, 'Petri', 'Paul', 'Malerstr.',<br />
'26', 22222, 'Karlstadt')<br />
14.5 Vererbung<br />
Als Letztes wollen wir uns ansehen, wie Vererbung im aktuellen SQL Standard umgesetzt<br />
wur<strong>de</strong>. Hierzu gibt es e<strong>in</strong> e<strong>in</strong>ziges Schlüsselwort, nämlich UNDER. Um <strong>de</strong>n UDT<br />
»cMitarbeiter« zu erzeugen und alle Eigenschaften <strong>de</strong>s UDT »cPerson« auf diese zu<br />
vererben, erzeugt man <strong>de</strong>n UDT wie folgt:<br />
CREATE TYPE cMitarbeiter UNDER cPerson<br />
(<br />
Abteilungsbezeichnung VARCHAR(30),<br />
Gehalt DECIMAL(10,2),<br />
METHOD festlegenGehalt( neuesGehalt DECIMAL(10,2) )<br />
RETURNS DECIMAL(10,2)<br />
)<br />
Über das Schlüsselwort UNDER erhält <strong><strong>de</strong>r</strong> UDT »cMitarbeiter« automatisch alle Attribute<br />
und Metho<strong>de</strong>n <strong>de</strong>s UDT »cPerson« .<br />
Das Schlüsselwort UNDER lässt sich auch ohne die Verwendung von UDT's direkt für<br />
Tabellen e<strong>in</strong>setzen. Zunächst erzeugen wir die Tabelle »Person« , so wie wir es <strong>in</strong><br />
Kapitel 6 kennen gelernt haben und anschließend die Tabelle »Mitarbeiter« . Dabei wird<br />
über UNDER auf die Tabelle »Person« verwiesen. Beim Anlegen <strong><strong>de</strong>r</strong> Tabelle »Mitarbeiter«<br />
wer<strong>de</strong>n alle speziellen Attribute dieser angegeben:
CREATE TABLE Person<br />
(<br />
Nummer INTEGER,<br />
Name VARCHAR (30),<br />
Vorname VARCHAR (20),<br />
Strasse VARCHAR (50),<br />
Hausnummer VARCHAR (6),<br />
Plz INTEGER,<br />
Ort VARCHAR (200),<br />
)<br />
CREATE TABLE Mitarbeiter UNDER Person<br />
(<br />
Abteilungsbezeichnung VARCHAR(30),<br />
Gehalt DECIMAL(10,2)<br />
)<br />
Zusammenfassung<br />
14.6 Zusammenfassung<br />
Im letzen Kapitel haben wir uns angesehen, wie sich die Verwendung von SQL <strong>de</strong>mnächst<br />
verän<strong><strong>de</strong>r</strong>n wird bzw. teilweise schon verän<strong><strong>de</strong>r</strong>t hat. Mit <strong><strong>de</strong>r</strong> Verbreitung objektorientierter<br />
Konzepte wur<strong>de</strong>n diese auch im aktuellen SQL Standard übernommen, so<br />
dass SQL heutzutage sowohl e<strong>in</strong>e <strong>de</strong>klarative und prozedurale als auch e<strong>in</strong>e objektorientierte<br />
Sprache darstellt.<br />
Im ersten Abschnitt wur<strong>de</strong> die Philosophie, die h<strong>in</strong>ter Objektorientierung steht, erläutert.<br />
Danach haben wir gesehen, wie die e<strong>in</strong>zelnen Eigenschaften <strong><strong>de</strong>r</strong> Objektorientierung<br />
<strong>in</strong> SQL umgesetzt wur<strong>de</strong>n. In benutzer<strong>de</strong>f<strong>in</strong>ierten Typen (UDT) wer<strong>de</strong>n sowohl<br />
Daten als auch Funktionen (Metho<strong>de</strong>n) als e<strong>in</strong>e E<strong>in</strong>heit gespeichert. Auf Basis e<strong>in</strong>es<br />
UDT wird e<strong>in</strong>e Tabelle erzeugt, <strong>in</strong> <strong><strong>de</strong>r</strong> die Daten gespeichert wer<strong>de</strong>n, auf die man über<br />
die Metho<strong>de</strong>n zugreift.<br />
E<strong>in</strong>en UDT erzeugt man über die SQL-Anweisung CREATE TYPE. Hierbei gibt man<br />
zunächst die Attribute und die Metho<strong>de</strong>n an. Danach müssen die e<strong>in</strong>zelnen Metho<strong>de</strong>n<br />
über CREATE METHOD mit »Leben« gefüllt wer<strong>de</strong>n.<br />
Über das Schlüsselwort UNDER kann die I<strong>de</strong>e <strong><strong>de</strong>r</strong> Vererbung realisiert wer<strong>de</strong>n.<br />
Sowohl UDT's, als auch Tabellen können damit <strong>in</strong> e<strong>in</strong>er Hierarchie abgebil<strong>de</strong>t wer<strong>de</strong>n.<br />
14.7 Aufgaben<br />
Wie<strong><strong>de</strong>r</strong>holungsfragen<br />
1) Wor<strong>in</strong> besteht <strong><strong>de</strong>r</strong> Unterschied zwischen Prozedur, Funktion und Metho<strong>de</strong>?<br />
2) Wie erzeugt man e<strong>in</strong>en benutzer<strong>de</strong>f<strong>in</strong>ierten Typ <strong>in</strong> SQL?<br />
3) Wie erzeugt man e<strong>in</strong>e Metho<strong>de</strong>?<br />
223
224<br />
14 »User Def<strong>in</strong>ed Types« (UDT)<br />
4) Wie unterstützt SQL das objektorientierte Konzept <strong><strong>de</strong>r</strong> Vererbung?<br />
5) Nennen Sie Beispiele für Metho<strong>de</strong>n <strong><strong>de</strong>r</strong> Klasse »Bestellung« !<br />
6) Nennen Sie Beispiele für Metho<strong>de</strong>n <strong><strong>de</strong>r</strong> Klasse »Vorstellung« !<br />
7) Was ist mit »Polymorphismus« geme<strong>in</strong>t? Geben Sie e<strong>in</strong> Beispiel!<br />
8) Was könnte mit »Klassenhierachie« geme<strong>in</strong>t se<strong>in</strong>?<br />
Übungen<br />
1) Erzeugen Sie e<strong>in</strong>en UDT zum Speichern e<strong>in</strong>er Adresse unter <strong>de</strong>m Namen »cAdresse«<br />
. Der UDT soll die Spalten »Strasse« , »Hausnummer« , »Plz« und »Ort« enthalten.<br />
2) Erzeugen Sie e<strong>in</strong>e Tabelle »Person« , die aus <strong>de</strong>n Spalten »Name« , »Vorname« und<br />
<strong>de</strong>m UDT »cAdresse« besteht!<br />
3) Erzeugen Sie e<strong>in</strong>e Tabelle »Musiker« , die aus <strong><strong>de</strong>r</strong> Spalte »Musik<strong>in</strong>strument« besteht<br />
und alle weiteren Spalten von <strong><strong>de</strong>r</strong> Tabelle »Person« aus Übung 2 erbt!
Literaturverzeichnis<br />
[Achilles97] Achilles, Albrecht: »SQL«, Ol<strong>de</strong>nbourg, 1997<br />
[ANSI99-1] ANSI/ISO/IEC: » 9075-1-1999 Database Languages – SQL – Part 1:<br />
Framework (SQL/Framework)«, http://www.ansi.org, 1999<br />
[ANSI99-2] ANSI/ISO/IEC: » 9075-2-1999 Database Languages – SQL – Part 2:<br />
Foundation (SQL/Foundation)«, http://www.ansi.org, 1999<br />
[ANSI99-3] ANSI/ISO/IEC: » 9075-3-1999 Database Languages – SQL – Part 3:<br />
Call-Level Interface (SQL/CLI)«, http://www.ansi.org, 1999<br />
[ANSI99-4] ANSI/ISO/IEC: » 9075-4-1999 Database Languages – SQL – Part 4:<br />
Persistent Stored Modules (SQL/PSM)«, http://www.ansi.org, 1999<br />
[ANSI99-5] ANSI/ISO/IEC: » 9075-3-1999 Database Languages – SQL – Part 5:<br />
Host Language B<strong>in</strong>d<strong>in</strong>gs (SQL/B<strong>in</strong>d<strong>in</strong>gs)«, http://www.ansi.org, 1999<br />
[Barker90] Barker, R: »CASE*Method: Tasks and Deliverables, Addison-Wesley, 1990<br />
[Bat<strong>in</strong>i92] Bat<strong>in</strong>i, Carlo / Ceri, Stefano / Navathe, Shamkant B.: »Conceptual<br />
Database Design«, Benjam<strong>in</strong> Cumm<strong>in</strong>gs Publish<strong>in</strong>g, 1992<br />
[Booch99] Booch, Grady / Rumbaugh, Jim / Jacobson, Ivar: »Das UML-Benutzerhandbuch«<br />
[Carlis01] Carlis, John V. / Maguire, Joseph D.: »Master<strong>in</strong>g Data Mo<strong>de</strong>l<strong>in</strong>g«,<br />
Addison-Wesley, 2001<br />
[Chen76] Chen, Peter P.: »The Entity-Relationship Mo<strong>de</strong>l – Toward a Unified View of<br />
Data«, ACM Trans. Database System 1, No. 1, 1976<br />
[Codd70] Codd, E. F.: »A Relational Mo<strong>de</strong>l for large Shared Data Banks«, Comm.<br />
ACM 13, No. 6, 1970<br />
[Date95] Date, Chris J.: »An Introduction to Database Systems«, Addison Wesley,<br />
1995<br />
[Date98] Date, Chris J. / Darwen, Hugh: »SQL – Der Standard«, Addison Wesley,<br />
1998<br />
[Delaney99] Delaney, Karen / Soukoup Ron: »Insi<strong>de</strong> Microsoft SQL Server 7.0«,<br />
Microsoft Press, 1999<br />
[Eirund00] Eirund, Helmut / Kohl, Ullrich: »Datenbanken – leicht gemacht«, Teubner,<br />
2000<br />
[Elmasri00] Elmasri, Ramez / Navathe, Shamkant B.: »Fundamentals of Database<br />
Systems«, Addison Wesley, 2000<br />
[Fortier99] Fortier, Paul J.: »SQL-3 – Implement<strong>in</strong>g the Object-Relational Database«,<br />
McGraw-Hill, 1999<br />
225
226<br />
Literaturverzeichnis<br />
[Fowler00] Fowler, M. / Scott, K.: »UML konzentriert«, Addison Wesley, 2000<br />
[Gorman00] Gorman, Michal M.: »Great News: The Relational Mo<strong>de</strong>l is <strong>de</strong>ad«,<br />
http://www.tdan.com, 2000<br />
[Gorman01] Gorman, Michal M.: »Is SQL a real Standard anymore«, http://<br />
www.tdan.com, 2001<br />
[Groff99] Groff, James R. / We<strong>in</strong>berg, Paul N.: »SQL: The Complete Reference«,<br />
McGraw-Hill, 1999<br />
[Gulutzan99] Gulutzan, Peter / Pelzer, Trudy: »SQL-99 Complete, Really «, R&D Books,<br />
1999<br />
[Halp<strong>in</strong>99] Halp<strong>in</strong>, Terry: »Entity Relationship Mo<strong>de</strong>l<strong>in</strong>g from an ORM Perspective:<br />
Part 1«,http://www.<strong>in</strong>concept.com, 1999<br />
[Halp<strong>in</strong>00-1] Halp<strong>in</strong>, Terry: »Entity Relationship Mo<strong>de</strong>l<strong>in</strong>g from an ORM Perspective:<br />
Part 2«,http://www.<strong>in</strong>concept.com, 2000<br />
[Halp<strong>in</strong>00-2] Halp<strong>in</strong>, Terry: »Entity Relationship Mo<strong>de</strong>l<strong>in</strong>g from an ORM Perspective:<br />
Part 3«,http://www.<strong>in</strong>concept.com, 2000<br />
[Halp<strong>in</strong>00-3] Halp<strong>in</strong>, Terry: »Entity Relationship Mo<strong>de</strong>l<strong>in</strong>g from an ORM Perspective:<br />
Part 4«,http://www.<strong>in</strong>concept.com, 2000<br />
[Halp<strong>in</strong>00-4] Halp<strong>in</strong>, Terry: »Entity Relationship Mo<strong>de</strong>l<strong>in</strong>g from an ORM Perspective:<br />
Part 5«,http://www.<strong>in</strong>concept.com, 2000<br />
[Hay99-1] Hay, David C.: »A Comparison of Data Mo<strong>de</strong>l<strong>in</strong>g Techniques«, Essential<br />
Strategies Inc., 1999<br />
[Hay99-2] Hay, David C.: »Object Orientation and Information Eng<strong>in</strong>eer<strong>in</strong>g:<br />
Object and Data Mo<strong>de</strong>l<strong>in</strong>g«, Essential Strategies Inc., 1999<br />
[Heuer97] Heuer, Andreas / Saake, Gunter: »Datenbanken«, Thomson Publish<strong>in</strong>g,<br />
1997<br />
[Hotek00] Hotek, Michael: »Introduction to TSQL«, http://www.mssqlserver.com,<br />
2000<br />
[Kle<strong>in</strong>schmidt97] Kle<strong>in</strong>schmidt, Peter / Rank, Christian: »Relationale Datenbanksysteme«,<br />
Spr<strong>in</strong>ger, 1997<br />
[Kuhlmann99] Kuhlmann, Gregor / Müllmerstadt, Friedrich: »SQL«, Rowohlt, 1999<br />
[Lackes01] Lackes, R. / Brandl, W. / Siepermann, M.: »Handl<strong>in</strong>g von Informationssystemen<br />
mit SQL«, Spr<strong>in</strong>ger, 2001<br />
[Mattos99] Mattos, Nelson M. u.a.: »SQL99, SQL/MM and SQLJ: An Overview of<br />
the SQL Standards«, http://www.wiscorp.com, 1999<br />
[Matthiessen97] Mathiessen, Günter / Unterste<strong>in</strong>, Michael: »Relationale Datenbanken und<br />
SQL«, Addison Wesley, 1997<br />
[Meier01] Meier, Andreas: »Relationale Datenbanken«, Spr<strong>in</strong>ger, 2001<br />
[Melton01] Melton, Jim / Simon, Alan R.: »SQL:1999«, Morgan Kaufmann, 2001<br />
[Melton99] Melton, Jim: »SQL:1999 – A Tutorial«, http://www.wiscorp.com, 2001
Literaturverzeichnis<br />
[Microsoft99-1] Microsoft Corporation, »Transact-SQL Sprachverzeichnis«, Microsoft<br />
Press, 1999<br />
[Microsoft99-2] Microsoft Corporation, »Microsoft SQL Server 7.0 – Die technische<br />
Referenz«, Microsoft Press, 1999<br />
[Microsoft99-3] Microsoft Corporation, »Microsoft SQL Server 7.0 – Datenbankimplementierung«,<br />
Microsoft Press, 1999<br />
[Moos97] Moos, Alfred / Daues, Gerhard: »Datenbank-Eng<strong>in</strong>eer<strong>in</strong>g«, vieweg, 1997<br />
[Muller99] Muller, Robert J.: »Database for Smarties : us<strong>in</strong>g UML for data mo<strong>de</strong>l<strong>in</strong>g«,<br />
Morgan Kaufmann, 1999<br />
[Oracle99] Oracle Corporation, »Oracle Designer Tutorial Release 6.0«, Oracle, 1999<br />
[Panny00] Panny, Wolfgang: »E<strong>in</strong>führung <strong>in</strong> <strong>de</strong>n Sprachkern von SQL-99«, Spr<strong>in</strong>ger,<br />
2000<br />
[Rational01] Rational Company: »Introduc<strong>in</strong>g Rational Suite AnalystStudio for the<br />
Data Analyst – Whitepaper«, http://www.rational.com/products/<br />
whitepaper, 2001<br />
[Rational00] Rational Company: »The UML and Data Mo<strong>de</strong>l<strong>in</strong>g«,<br />
http://www.rational.com/products/whitepaper, 2000<br />
[Rauh97] Rauh, Otto / Stickel, Eberhard: »Konzeptuelle Datenmo<strong>de</strong>llierung«,<br />
B. G. Teubner, 1997<br />
[Riordan00] Riordan, Rebecca M.: »Microsoft SQL Server 2000-Programmierung –<br />
Schritt für Schritt«, Microsoft Press, 2000<br />
[Scheer91] Scheer, August-Wilhelm: »Wirtschafts<strong>in</strong>formatik – Informationssysteme<br />
im Industriebetrieb«, Spr<strong>in</strong>ger, 1991<br />
[Scheer97] Scheer, August-Wilhelm: »Wirtschafts<strong>in</strong>formatik – Referenzmo<strong>de</strong>lle für<br />
<strong>in</strong>dustrielle Geschäftsprozesse«, Spr<strong>in</strong>ger, 1997<br />
[Scheer99] Scheer, August-Wilhelm: »ARIS – Vom Geschäftsprozess zum<br />
Anwendungssystem«, Spr<strong>in</strong>ger, 1999<br />
[Schicker99] Schicker, Edw<strong>in</strong>: »Datenbanken und SQL«, B. G. Teubner, 1999<br />
[Schmidt01] Schmidt, Me<strong>in</strong>hardt / Demmig, Thomas: »SQL GE-PACKT«, mitp, 2001<br />
[Sparks01] Sparks, Geoffrey: »Database Mo<strong>de</strong>l<strong>in</strong>g <strong>in</strong> UML«, Method & Tools, 2001<br />
[Shlaer96] Shlaer, Sally / Mellor, Stephen J.: »Objektorientierte Systemanalyse«,<br />
Hanser, 1996<br />
[Unterste<strong>in</strong>96] Unterste<strong>in</strong>, Michael: »Unternehmensübergreifen<strong>de</strong> Mo<strong>de</strong>llierung von<br />
Datenstrukturen«, Deutscher Universitäts Verlag, 1996<br />
[Vetter91] Vetter, Max: »Aufbau betrieblicher Informationssysteme«, B. G. Teubner,<br />
1991<br />
[Vossen94] Vossen, Gottfried: »Datenmo<strong>de</strong>lle, Datenbanksprachen und<br />
Datenbankmanagementsysteme«, Addison Wesley, 1994<br />
[Vossen00] Vossen, Gottfried: »Datenmo<strong>de</strong>lle, Datenbanksprachen und<br />
Datenbankmanagementsysteme«, Ol<strong>de</strong>nbourg, 2000<br />
227
Stichwortverzeichnis<br />
A<br />
Abhängigkeit<br />
funktional 82<br />
mehrwertig 88<br />
transitiv 87<br />
voll funktional 82<br />
ABS 133<br />
abstrakte Datentypen 13<br />
ACM 11, 49<br />
ADD COLUMN 111<br />
ADD CONSTRAINT 111<br />
ADT 13<br />
Aggregation 57, 62<br />
geme<strong>in</strong>same Aggregation 62<br />
zusammengesetzte Aggregation 62<br />
aktive Datenbanksysteme 210<br />
ALL 180<br />
ALTER TABLE 110<br />
AND 148<br />
ANSI 11, 96<br />
Anwendungsfall, Use Case 60<br />
ANY 180<br />
Array 110<br />
ASC 155<br />
Assoziation 43, 62<br />
Attribut 36, 40, 74<br />
Ausdrücke 142<br />
Datum-/Zeit 143<br />
Numerisch 142<br />
Zeichenketten 143<br />
AVG 140<br />
B<br />
Barker, Richard 55<br />
Bed<strong>in</strong>gungsausdruck 144<br />
Bed<strong>in</strong>gungs-Jo<strong>in</strong> 167<br />
BEGIN...END 197<br />
BETWEEN 147<br />
Bezeichner, qualifizierte 163<br />
Beziehung 36, 43, 74<br />
rekursiven Beziehung 46<br />
Beziehungstyp 36, 45, 74<br />
Booch, Grady 60<br />
Built-<strong>in</strong>-Funktionen 132<br />
Bus<strong>in</strong>ess Objects 12<br />
C<br />
CALL 194<br />
CASE 198<br />
CAST 139<br />
CHAR_LENGTH 133<br />
CHECK 106<br />
Chen 49<br />
COALESCE 138<br />
Codd 49<br />
COMMIT 184<br />
Concurreny Control 187<br />
CONSTRAINT 102<br />
COUNT 140<br />
CREATE DISTINCT TYPE 108<br />
CREATE DOMAIN 109<br />
CREATE FUNCTION 196<br />
CREATE METHOD 221<br />
CREATE PROCEDURE 194<br />
CREATE TABLE 101<br />
CREATE TRIGGER 210<br />
CREATE TYPE 220<br />
CROSS JOIN 166<br />
CUBE 152<br />
CURRENT_DATE 107, 137<br />
CURRENT_TIME 107, 137<br />
CURRENT_TIMESTAMP 107, 137<br />
CURRENT_USER 107<br />
D<br />
Dateisystem 11<br />
Daten kumulieren 150<br />
Datenbank-Management-System 18, 69<br />
Datenbanksystem 13, 19<br />
Datenchaos 11<br />
Daten<strong>in</strong>tegrität 18<br />
Datenkapselung 218<br />
Datenmo<strong>de</strong>ll 33, 36<br />
Datenmo<strong>de</strong>llierung 35<br />
Datenredundanz 18<br />
Datensicherheit 18<br />
Datensicht 18<br />
Datentypen 97<br />
benutzer<strong>de</strong>f<strong>in</strong>ierte 108<br />
BINARY LARGE OBJECT 99<br />
BIT 99<br />
BIT VARYING 99<br />
229
BOOLEAN 99<br />
CHARACTER 99<br />
CHARACTER LARGE OBJECT 99<br />
CHARACTER VARYING 99<br />
DATE 100<br />
DECIMAL 98<br />
DOUBLE 98<br />
FLOAT 98<br />
INTEGER 98<br />
INTERVAL 100<br />
NUMERIC 98<br />
REAL 98<br />
SMALLINT 98<br />
TIME 100<br />
TIMESTAMP 100<br />
Datenunabhängigkeit 18<br />
DBMS 18<br />
DBS 19<br />
DECLARE 195<br />
DEFAULT 104, 116<br />
<strong>de</strong>klarative Programmiersprache 126<br />
DELETE 117<br />
DESC 155<br />
Dirty Read-Problem 188<br />
DISTINCT 130, 150<br />
Doma<strong>in</strong> 72<br />
Doma<strong>in</strong>-Integrität 73<br />
DROP COLUMN 111<br />
DROP CONSTRAINT 111<br />
DROP DATABASE 112<br />
DROP FUNCTION 196<br />
DROP PROCEDURE 194<br />
DROP TABLE 110<br />
DROP TRIGGER 210<br />
E<br />
E. F. Codd 82<br />
Entity 49<br />
Entity-Integrität 73<br />
Entity-Relationship-Diagramm 49<br />
Entity-Relationship-Mo<strong>de</strong>ll 13, 21, 33, 49<br />
Entitytyp 49<br />
ER/Studio 78<br />
ERD 49<br />
ERM 13, 21, 49<br />
ERw<strong>in</strong> 78<br />
ESCAPE 146<br />
EXISTS 178<br />
EXTRACT 134<br />
230<br />
Stichwortverzeichnis<br />
F<br />
FOR EACH ROW 210<br />
FOR EACH STATEMENT 210<br />
FOREIGN KEY 103<br />
CASCADE 104<br />
NO ACTION 104<br />
ON DELETE 106<br />
ON UPDATE 106<br />
REFERENCES 103<br />
RESTRICT 104<br />
SET DEFAULT 104<br />
SET NULL 104<br />
Fremdschlüssel 72<br />
Compound Key 72<br />
FROM 127<br />
FULL OUTER JOIN 170<br />
Funktionen<br />
Datetime Value Functions 132<br />
Interval Value Functions 132<br />
Numeric Value Functions 132<br />
Set Functions 132<br />
Str<strong>in</strong>g Value Functions 132<br />
Funktionen, benutzer<strong>de</strong>f<strong>in</strong>iert 196<br />
Funktionsmo<strong>de</strong>ll 33<br />
G<br />
Geschäftsobjekt 36f., 74<br />
GROUP BY 150<br />
H<br />
HAVING 152<br />
hierarchische Datenbanksysteme 11<br />
I<br />
IF...THEN...ELSE 198<br />
IMS 11<br />
IN 147, 178, 195<br />
INNER JOIN 166<br />
<strong>in</strong>nere Abfrage 176<br />
INOUT 195<br />
INSERT 115<br />
Internet 12<br />
INTO 195<br />
IS NULL 145<br />
Isolationslevel 190<br />
J<br />
Jacobson, Ivar 60<br />
Jo<strong>in</strong> 162
K<br />
Kard<strong>in</strong>alität 43<br />
kartesisches Produkt 166<br />
Kategorie 95<br />
Klassen 220<br />
Klassenmo<strong>de</strong>ll, Class Mo<strong>de</strong>l 60<br />
klassisch komma-getrennter Jo<strong>in</strong> 167<br />
Kommentar 102<br />
Kontrollsteuerung 197<br />
Korrelieren<strong>de</strong> Unterabfrage 179<br />
Krähenfuß, Crows foot 56<br />
L<br />
LEAVE 200<br />
LEFT OUTER JOIN 170<br />
LIKE 145<br />
Lost Update-Problem 187<br />
LOWER 134<br />
M<br />
MAX 140<br />
Mehrbenutzerbetrieb 18, 187<br />
Mengenfunktionen 139<br />
Metho<strong>de</strong> 59, 216<br />
MIN 140<br />
MOD 133<br />
N<br />
NATURAL JOIN 169<br />
Netzwerk Datenbanksysteme 11<br />
Non-repeatable Read-Problem 188<br />
Normalform 13<br />
Normalformen 82<br />
1. Normalform 85<br />
2. Normalform 86<br />
3. Normalform 87<br />
4. Normalform 88<br />
5. Normalform 88<br />
Boyce-Codd-Normalform 88<br />
Doma<strong>in</strong>-Key-Normalform 89<br />
Normalisierung 81<br />
Schritte 89<br />
NOT 148<br />
NULL 100<br />
NULLIF 137<br />
O<br />
Object Management Group, OMG 60<br />
Objektklasse 37<br />
objektorientierte Programmierung 216<br />
Objektorientierung 216<br />
Stichwortverzeichnis<br />
objektrelationale Datenbanksysteme 216<br />
OLAP 152<br />
Optionalität 43<br />
OR 148<br />
Oracle Designer 78<br />
ORDER BY 155<br />
OUT 195<br />
OUTER JOIN 169<br />
Outputparameter 195<br />
OVERLAY 136<br />
P<br />
Parameter 194<br />
passive Datenbanksysteme 210<br />
Phantom Read-Problem 189<br />
Phasenkonzept 20<br />
Phasenkonzept siehe Projektplan<br />
phonetischen Suche 202<br />
Polymorphismus 219<br />
POSITION 134<br />
PowerDesigner 78<br />
Primärschlüssel 72<br />
Compound Key 72<br />
M<strong>in</strong>imalität 72<br />
Primärschlüssel siehe Schlüssel<br />
PRIMARY KEY 102<br />
Projektplan siehe Phasenkonzept<br />
Prozedur 194<br />
prozedurale Programmiersprache 126<br />
Prozedurale Sprachelemente 193<br />
Q<br />
qualifizierter Bezeichner 163<br />
R<br />
Rational Rose 78<br />
READ COMMITTED 190<br />
READ UNCOMMITTED 190<br />
referentielle Integrität 73, 103<br />
Rekursive Beziehung 76<br />
Relation 71<br />
Relationenmo<strong>de</strong>ll 71<br />
E. F. Codd 71<br />
logischen Mo<strong>de</strong>ll 71<br />
Umsetzung aus ERM 73<br />
Relationentheorie 71<br />
REPEAT...UNTIL 199<br />
REPEATABLE READ 190<br />
RETURNS 196<br />
RIGHT OUTER JOIN 170<br />
ROLLBACK 184<br />
231
ROLLUP 152<br />
Row Subquery 176<br />
Rumbaugh, James 60<br />
S<br />
SAVEPOINT 186<br />
Scalar Subquery 176<br />
Schema 95<br />
Schlüssel 36, 40, 74<br />
Schlüsselattribut 40<br />
Schlüsselkandidat 41<br />
SELECT 126<br />
SELECT-Anweisung 156<br />
Self Jo<strong>in</strong> 167<br />
SEQUEL 96<br />
SERIALIZABLE 190<br />
SET TRANSACTION 190<br />
SIMILAR 145<br />
SOME 180<br />
Sortieren 154<br />
Soun<strong>de</strong>x 203<br />
Spaltennamen-Jo<strong>in</strong> 167<br />
SQL 12, 95<br />
1999 96<br />
SQL-1 12<br />
SQL-1999 11<br />
SQL-3 11<br />
SQL-86 96<br />
SQL-92 96<br />
SQL-Datentypen 97<br />
Stored Procedures 13<br />
Subquery 176<br />
SUBSTRING 135<br />
Subtyp 36, 39, 74<br />
Spezialisierung 39<br />
SUM 141<br />
Supertyp 36, 39, 74<br />
Generalisierung 39<br />
Hierachie 39<br />
Synchronisation 18<br />
System/R 11<br />
232<br />
Stichwortverzeichnis<br />
T<br />
Table Subquery 176<br />
Transaktion 13, 183<br />
Trigger 13, 209<br />
AFTER 212<br />
BEFORE 211<br />
NEW 211<br />
NEW TABLE 212<br />
OLD 211<br />
OLD TABLE 212<br />
REFERENCING 210<br />
TRIM 134<br />
Tupel 71<br />
U<br />
UDM 35<br />
UDT 220<br />
Übergabeparameter 195<br />
UML 13, 21, 59<br />
Sterotype 61<br />
UML-Klassendiagramm 217<br />
UNDER 222<br />
Unfied Mo<strong>de</strong>l<strong>in</strong>g Language 59<br />
Unified Mo<strong>de</strong>l<strong>in</strong>g Language 13, 21, 33<br />
Unterabfrage 176<br />
Unterabfragen 175<br />
unternehmensweites Datenmo<strong>de</strong>ll 35<br />
UPDATE 118<br />
UPPER 132, 134<br />
User Def<strong>in</strong>ed Type 215<br />
V<br />
Variable 195<br />
Vererbung 218, 222<br />
Vergleichsprädikat 144<br />
W<br />
Wertebereich 72<br />
WHERE 144<br />
WHILE...DO 200