25.12.2012 Aufrufe

Datenbankkonzepte in der Praxis - mt-computersysteme.de

Datenbankkonzepte in der Praxis - mt-computersysteme.de

Datenbankkonzepte in der Praxis - mt-computersysteme.de

MEHR ANZEIGEN
WENIGER ANZEIGEN

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

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!