SQL Marco Skulschus
SQL
1
2
SQL
SQL Marco Skulschus Webseite zum Buch: http://www.comelio-medien.com/dedi3_557.php © 2007 Comelio Medien
SQL
3
Alle Rechte vorbehalten. Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Jeder Verwertung außerhalb der engen Grenzen des Urheberrechtsgesetzes ist ohne Zustimmung des Verlages unzulässig und strafbar. Das gilt insbesondere für die Vervielfältigung, Übersetzung, Mikroverfilmung und die Einspeicherung und Verbreitung in elektronischen Systemen.
© Comelio GmbH Rellinghauser Straße 10, D-45128 Essen Tel (0201) 437517-0, Fax (0201) 437517-10 www.comelio-medien.com,
[email protected]
Umschlaggestaltung: Daniel Winter Satz: Marcel Walla Comelio-Grafiken: Daniel Winter Printed in Germany
ISBN 3-939701-11-4 | 978-3-939701-11-8
4
SQL
Inhaltsverzeichnis 1
Einleitung.................................................................................................................................11 1.1
Was Sie im Buch finden .................................................................................................11
1.2
Die Zielgruppe ................................................................................................................12
1.3
Der Aufbau .....................................................................................................................13
1.3.1 2
Grundlagen relationaler Datenbanken ....................................................................................17 2.1
Komponenten eines Datenbanksystems........................................................................17
2.1.1
Sichten auf ein DBS ...................................................................................................19
2.1.2
Benutzergruppen eines DBS......................................................................................20
2.1.3
Anforderungen an ein DBS.........................................................................................20
2.2
Daten und Datenstrukturen ............................................................................................21
2.2.1
Eigenschaften von Daten ...........................................................................................21
2.2.2
Klassifikation von Datentypen ....................................................................................23
2.3
Beziehungsstrukturen zwischen Daten ..........................................................................24
2.3.1
Die 1:1 (eineindeutige) Beziehung .............................................................................25
2.3.2
Die 1:n (funktionale) Beziehung .................................................................................25
2.3.3
Die n:m (komplexe) Beziehung ..................................................................................25
2.4
Vom ER-Modell zum RDM .............................................................................................26
2.5
Über Normalisierung ein Datenmodell optimieren .........................................................32
2.5.1
Das Konzept der funktionellen Abhängigkeit..............................................................34
2.5.2
Von der Universal Relation zum RDM........................................................................34
2.5.3
DB-Anomalien und Redundanzen..............................................................................38
2.6 3
Wie Sie üben und testen können ...............................................................................13
Fachbegriffe für Tabellenbestandteile ............................................................................40
Datenbank und Tabellen anlegen und ändern........................................................................45 3.1
Entwicklung und Hintergrund von SQL ..........................................................................45
3.2
Mit PowerDesigner ein Datenmodell grafisch entwickeln ..............................................47
3.3
DB und Tabellen anlegen ...............................................................................................51
3.3.1
Tabellen anlegen ........................................................................................................51
3.3.2
SQL99-Datentypen.....................................................................................................55
3.3.3
Tabelle auf Existenz überprüfen.................................................................................56
3.3.4
Synonyme...................................................................................................................58
3.4
Tabellenstruktur ändern..................................................................................................58
3.5
Einschränkungen und Datenüberprüfungen...................................................................60
SQL
5
4
5
6
3.5.1
Festlegen eines Wertebereichs..................................................................................61
3.5.2
Verwenden der Einschränkung innerhalb der Tabelle ...............................................63
3.5.3
CHECK – Klausel innerhalb der Tabellendefinition....................................................64
3.5.4
Einschränkungen für Tabellen....................................................................................65
3.6
Tabellen untereinander referenzieren ............................................................................66
3.7
Daten strukturieren mit Indizes.......................................................................................67
3.8
Kommentare für DB-Objekte ..........................................................................................69
Daten einfügen und ändern.....................................................................................................75 4.1
Daten in eine DB eintragen ............................................................................................75
4.2
Daten löschen.................................................................................................................77
4.3
Daten aktualisieren und ändern .....................................................................................80
Grundstrukturen einfacher Abfragen.......................................................................................87 5.1
Übersicht über die relationale Algebra ...........................................................................87
5.2
Grundstruktur der Abfrage..............................................................................................90
5.3
Operatoren der WHERE – Klausel.................................................................................93
5.3.1
Boolesche Funktionen und logische Operatoren .......................................................93
5.3.2
Vergleichsoperatoren .................................................................................................96
5.3.3
Berechnungen mit numerischen Operatoren und Vorzeichen .................................100
5.4
Abfrage des Werts NULL..............................................................................................101
5.5
Abfragen miteinander verknüpfen ................................................................................102
5.5.1
Vereinigungsmenge von Tabellen............................................................................102
5.5.2
Schnittmenge............................................................................................................103
5.5.3
Differenzen zwischen Tabellen ................................................................................104
Komplexe Abfragen, Unterabfragen und Funktionen............................................................111 6.1
6
Mehrere Tabellen abfragen ..........................................................................................111
6.1.1
Grundprinzip und Bedeutung der Fremdschlüssel ...................................................111
6.1.2
Möglichkeiten der Verknüpfung................................................................................113
6.1.3
Tabelle mit sich selbst verknüpfen ...........................................................................117
6.1.4
Mehr als zwei Tabellen verknüpfen..........................................................................118
6.2
Aggregatfunktionen einsetzen......................................................................................120
6.3
Unterabfragen und ihre Operatoren .............................................................................124
6.3.1
Grundprinzip einer Unterabfrage..............................................................................124
6.3.2
Verwendung von Vergleichsoperatoren ...................................................................125
6.3.3
Prädikate bei Unterabfragen ....................................................................................127
6.3.4
NULL und MATCH....................................................................................................130
6.3.5
Duplikate in Unterabfragen.......................................................................................131
SQL
7
6.4
Sortierungen und Gruppierungen.................................................................................133
6.5
Werte in der WHERE – Klausel....................................................................................135
6.5.1
Text und Zahlenwerte...............................................................................................135
6.5.2
System-Variablen .....................................................................................................136
6.5.3
Skalare Funktionen...................................................................................................136
6.5.4
Ausdrucks-Operatoren .............................................................................................140
6.5.5
Bedingungen mit CASE............................................................................................141
Abfragen in virtuellen Tabellen speichern.............................................................................147 7.1 7.1.1
Funktionsweise von virtuellen Tabellen....................................................................148
7.1.2
Überlegungen zu Einsatzbereichen .........................................................................148
7.2
Sichten anlegen und löschen .......................................................................................149
7.3
Sichten aufrufen ...........................................................................................................152
7.3.1
Grundformen des Aufrufs von Sichten .....................................................................152
7.3.2
Gefahren- und Fehlerquellen bei Sichtdefinitionen ..................................................153
7.4
Einfügen, Löschen und Aktualisieren .......................................................................157
7.4.2
Gefahren- und Fehlerquellen bei Änderungsvorgängen ..........................................158
7.4.3
Überprüfungen mit WITH CHECK OPTION .............................................................159 Snapshots verwenden ..................................................................................................160
Zugriffskontrolle durch Benutzer, Rechte und Rollen ...........................................................165 8.1
Vorüberlegungen für Zugriffskontrollen ........................................................................165
8.2
Benutzer anlegen .........................................................................................................167
8.3
Rechte vergeben und versagen ...................................................................................169
8.3.1
Rechte für Benutzer anlegen....................................................................................169
8.3.2
Benutzern Rechte verweigern ..................................................................................172
8.3.3
Benutzern Rechte entziehen ....................................................................................172
8.4 9
Änderungen über Sichten realisieren ...........................................................................156
7.4.1
7.5 8
Grundprinzip der virtuellen Tabelle ..............................................................................147
Rollen einrichten...........................................................................................................174
MySQL, MS SQL Server und Oracle ....................................................................................181 9.1
Die ODBC- Schnittstelle ...............................................................................................182
9.2
MySQL und ODBC .......................................................................................................183
9.2.1
Installation von MySQL unter Windows....................................................................184
9.2.2
Arbeiten mit der Eingabeaufforderung .....................................................................186
9.2.3
Installation von MySQL- Front ..................................................................................187
9.2.4
DB und Tabellen anlegen in MySQL-Front ..............................................................189
9.2.5
ODBC- Verbindung zu MySQL mit MS Access........................................................191
SQL
7
9.3
Der MS SQL- Server und MS Access ..........................................................................195
9.3.1
Installation des MS SQL-Servers .............................................................................196
9.3.2
Arbeiten mit dem MS SQL-Server............................................................................199
9.3.3
Starten, Anhalten und Beenden des MS SQL-Servers ............................................199
9.3.4
Der Enterprise Manager ...........................................................................................200
9.3.5
Der Query Analyzer ..................................................................................................200
9.3.6
Das Anlegen der SemiTex- Datenbank....................................................................201
9.3.7
ODBC- Verbindung von MS SQL-Server zu MS Access .........................................202
9.4
Oracle installieren und einrichten .................................................................................203
9.4.1
Die Installation von Oracle........................................................................................204
9.4.2
Eine Datenbank in Oracle anlegen...........................................................................205
9.4.3
Tabellen in die DB einfügen .....................................................................................207
9.4.4
ODBC mit Oracle verbinden .....................................................................................207
10 MS SQL Server und Transact SQL.......................................................................................213 10.1
Grundprinzip von Transaktionen ..................................................................................213
10.2
Transact SQL - Variablen und ihre Datentypen ...........................................................215
10.2.1 Datentypen im MS SQL Server ................................................................................215 10.2.2 Variablen deklarieren und mit Werten füllen ............................................................216 10.3
Verzweigungen und Schleifen......................................................................................218
10.3.1 Die if - else - Anweisung...................................................................................219 10.3.2 Die if – else if – else – Anweisung ............................................................221 10.3.3 Schleifen bilden und Zähler verwenden ...................................................................223 10.4
DB-Prozeduren in MS SQL Server...............................................................................225
11 Oracle und PL/SQL ...............................................................................................................231 11.1
Grundüberlegungen......................................................................................................231
11.2
Programmstrukturen gestalten .....................................................................................233
11.2.1 Deklarationen im DECLARE-Abschnitt ....................................................................234 11.2.2 Ausgaben im Programmablauf .................................................................................237 11.2.3 Weitere Formen der Wertzuweisungen....................................................................238 11.2.4 Verzweigungen und Ausnahmen erstellen...............................................................239 11.2.5 Schleifen konstruieren ..............................................................................................242 11.3
Cursor-Behandlung ......................................................................................................243
12 Lösungen...............................................................................................................................249 13 Glossar ..................................................................................................................................274
8
SQL
Einleitung
SQL
9
EINLEITUNG
10
SQL
EINLEITUNG
1 Einleitung In der aufgebrochenen Werkzeuglandschaft der IT-Branche gibt es nur wenige Werkzeuge, die zu unterschiedlichen Arbeitsvorgängen oder Werkstücken passen. Dynamische Webseiten mit Datenbankanbindung kann man mit dieser oder jenen Programmiersprache einrichten, die Datenbank selbst kann auf unterschiedlichen DB-Servern und DB- Systemen implementiert sein, und die Gestaltung der Seite kann in der einfachsten Form in HTML, für Großprojekte in eine XML-Schicht oder alternativ in einem Flash-Film eingearbeitet werden. SQL stellt dagegen ein Werkzeug dar, das grundlegend überall eingesetzt werden kann, wo auf Datenbanken zurückgegriffen wird. Sie können die gleichen SQL-Befehle für Abfragen in PHP, Java oder in Visual Basic verwenden oder mit der annähernd gleichen Syntax DBs auf unterschiedlichen Servern anlegen. Inhaltlich haben wir uns bemüht, aus der großen Vielzahl an SQL-Befehlen die für den täglichen Gebrauch wichtigsten herauszufischen und sie sowohl syntaktisch zu erläutern, in den DB-Kontext einzubinden und dann mit Beispielen in ihrer Anwendung zu versehen. Dabei ist die Perspektive immer diejenige eines Programmierers, der zusätzlich zu einem Programm auch eine entsprechende Datenbankanbindung benötigt, sodass gerade Themen wie die Entwicklung eines Datenmodells oder Abfragen sehr großen Raum einnehmen. Zwei Schwerpunkte dieses Buchs sind also Datenbankplanung und –umsetzung sowie Abfragen. Dagegen haben wir die Themenauswahl rund um die Administration etwas eingeschränkt, da hier jedes Datenbanksystem unterschiedliche Wege geht und nicht unbedingt Standard SQL-konforme Lösungen anbietet. Zudem richtet man Benutzer und Zugriffskontrollen eher über die grafische Oberfläche ein. Alle Datenbankmanagementsysteme weisen Eigenarten für SQL auf, die wir im Zusammenhang mit dem jeweiligen DBMS ebenfalls vorstellen. Dazu zählt Transact SQL vom MS SQL Server und PL/SQL von Oracle.
1.1 Was Sie im Buch finden Autoren sind wir nebenberuflich, und das macht „meistens“ sehr viel Spaß. Unsere eigentliche Arbeit besteht darin, im Rahmen unserer Firma SeMeCon in Seminaren Freiberuflern oder angestellten IT-Fachleuten Wissen in den Bereichen Programmierung, Netzwerke und Webdesign zu vermitteln. Außerhalb der Seminare entwickeln wir entsprechende Lösungen für Unternehmen und Organisationen. Daher basiert dieser Coach auf unserer direkten Seminarerfahrung und ist als Schulungsunterlage gedacht. Nicht jeder besucht Seminare, sondern erwartet daher von einem Buch, das es die Inhalte losgelöst von einem Trainer vermitteln kann. Daher setzen wir für den Zweck des Selbststudiums auf zwei Hilfen:
SQL
11
EINLEITUNG
¾ Die vielen Abbildungen sollen Ihnen helfen, sich ein Bild von eigentlich recht abstrakten Objekten der Datenbankprogrammierung zu machen. Im Idealfall können sie alleine für einen Sachverhalt stehen, sodass Sie, nachdem Sie das Buch ein erstes Mal durchgearbeitet haben, sich anhand der Grafiken die wesentlichen Zusammenhänge ins Gedächtnis rufen können. ¾ Ein zweites Hilfsmittel stellt die konsequente Handlungsorientierung dar. Die theoretischen Begründungen und Konzepte werden zwar am Anfang jeder Lektion in Erklärungen vermittelt, doch all das, was Sie selbst tun müssen, wurde in einzelne Schritte zerlegt. Damit dürften Sie übrigens eines der wenigen Bücher in Händen halten, die Datenbankprogrammierung handlungsorientiert vermitteln. ¾ Innerhalb der Kapitel, die sich ausschließlich mit der Programmierung beschäftigen, führt Sie zunächst ein allgemeiner Abschnitt (zumindest dann, wenn es allgemeine Überlegungen zum aktuellen Thema gibt) in das Thema ein. Danach folgt eine Übersicht über die allgemeine Syntax, die wir mit einigen Hinweisen auf Wahlmöglichkeiten, Besonderheiten und Einstellungsvarianten erläutern. Diese allgemeine Syntaxübersicht finden Sie im Textteil ausschließlich bei umfangreichen Befehlen (Anlegen eine Tabelle, Erstellung einer Abfrage usw.), während kurze Befehle und ihre allgemeine Darstellung aus Platzgründen nur hinten im Anhang aufgenommen wurde. ¾ Der Glossar soll sowohl als kleines Lexikon dienen wie auch als Befehlsreferenz. Sie finden dort neben der gerade erwähnten allgemeinen Syntax auch die Syntax von kurzen Befehlen, die im Textteil nur als Beispiel erscheinen, weil sie sehr übersichtlich sind und keine Schwierigkeiten darstellen. Der Vollständigkeit halber gibt es sie daher im Glossar.
1.2 Die Zielgruppe In Seminaren ist immer wieder eine spannende Frage, warum die Teilnehmer sich überhaupt an einem bestimmten Termin in einer bestimmten Stadt einfinden, um ein neues Werkzeug kennen zu lernen. Bei einem Thema wie E-Commerce kann man die Motivation noch sehr genau vorhersagen; bei einem Thema wie SQL jedoch drehen sich die eigentlichen Fragen weniger um die Sprachsyntax, sondern mehr um die Erreichung eines Ziels wie dynamische Webseiten, Implementation einer Unternehmens- oder Vereinsdatenbank oder Datenbankzugriff innerhalb einer Programmiersprache. Auf diese unterschiedlichen Einsatzgebiete der Sprache und die daraus resultierenden Motivationstypen versuchen wir hauptsächlich durch eine große Bandbreite an Beispielen Rücksicht zu nehmen. Jemand, der ein Datenmodell für einen Webshop plant hat zwangsläufig ganz andere zu modellierende Objekte (Kunden, Produkte, Aufträge, Bestellungen) als derjenige, der für eine bestehende Unternehmensdatenbank vorgefertigte Abfragen (z.B. Sichten) vorbereiten soll und dabei mit unternehmensspezifischen Objekten (Mitarbeiter, Kunden, Abteilungen, Projekte, Produkte) hantieren muss. Im günstigsten Fall sehen Sie in den kleinen Beispielen ab und an auch Ihr eigenes Projekt hindurchschimmern, sodass die Inhalte wesentlich transparenter werden. Neben die Motivation gesellt sich als Attribut für das Objekt Teilnehmer auch das Vorwissen: Die ersten Module werden Ihnen das notwendige Basiswissen vermitteln, das man bei der Gestaltung einer Datenbank und einer Herleitung des Datenmodells benötigt. Es ist eigentlich sehr einfach, Tabellen und Felder in SQL anzulegen. Interessant für einen langfristig erfolgreichen Einsatz ist es allerdings, die „richtigen“ Tabellen anzulegen. Ein entsprechendes Verfahren stellen wir Ihnen natürlich ausführlich vor, wobei eigene und weiter gehende Projekte auch mit steigender Erfahrung einfacher zu gestalten werden. Daher erwarten wir in diesem Buch als Vorwissen grundsätzlich nichts.
12
SQL
EINLEITUNG
1.3 Der Aufbau Dieses Buch ist in Projekte aufgeteilt, die aufeinander aufbauen. Es gibt allerdings mehrere Datenbanken, anhand derer immer wieder neue Themen erörtert werden. Teilweise werden also Inhalte früherer Projekte vorausgesetzt, somit ist unsere Empfehlung sich das Buch von Anfang an zu Gemüte zu führen. Sie werden es selbst merken, sobald ein Bezug zu früheren Aussagen hergestellt wird. Innerhalb eines Projekts werden Sie Lektionen finden, in denen die einzelnen Inhalte weitestgehend schrittweise erläutert werden. Dabei haben wir uns bemüht, möglichst viel, was uns dafür geeignet schien, als Handlungsablauf darzustellen. Wenn die Skripte dagegen insbesondere durch ihre Zusammenstellung übersichtlicher sind als wenn sie durch Schrittfolgen künstlich entzerrt werden, haben wir entsprechende Erklärungen vor- und nachgeschaltet. In einer Zusammenfassung finden Sie dann die wichtigsten Erkenntnisse eines Projekts noch einmal übersichtlich aufbereitet, während die wesentlichen Inhalte dann in Form von Übungen trainiert werden. Diese Übungen stellen auch weitere Beispiele der im Projekt gezeigten Techniken und Verfahren dar, die inhaltlich teilweise auch für die folgenden Projekte relevant sind. Hier finden Sie gerade auch in den Lösungen weitere Hinweise, wie die Lösung entstanden ist.
1.3.1 Wie Sie üben und testen können Wie es sich für einen Kurs gehört, müssen die Teilnehmer genügend Spielmaterial für die Erkundung des Werkzeugs erhalten. Nur wenige Datenbanken, die in den einzelnen Modulen verwendet werden, enthalten auch beispielhaftes Datenmaterial wie z.B. der MS SQL Server mit der Ihnen sicherlich aus MS Access bekannten Nordwind-Datenbank. Neben einigen Datenbanken können Sie SQL-Skripte und Beispieltabellen im Format aus dem Internet herunterladen. Dazu steht Ihnen erstens die Verlagsseite www.vmi-buch.de mit dem Downloadbereich und unsere Firmenseite www.semecon.de mit dem Geschäftsbereich Medien zur Verfügung.
Hinweise zu Übungsdateien, Ergebnissen und weiteren Informationen finden Sie in diesem Format. Die Dateien stehen im .sql-Format zur Verfügung. Es handelt sich dabei um eine Textdatei mit Inhalten (Kommentare und Befehle) für ein Datenbanksystem.
In den Übungsdateien von den beiden Webseiten finden Sie die SQL-Skripte aus dem Textteil, den Übungen und Lösungen. Zwar sollen Sie selbst auch SQL tippen, aber gerade bei umfangreichen Texten wie z.B. Daten (die wir natürlich automatisch haben erzeugen lassen) ist es sicherlich angenehmer, wenn Sie diese Texte importieren können. Bitte achten Sie dabei unbedingt darauf, ob z.B. die Datentypen oder die Syntaxkonventionen mit dem Datenbanksystem, das Sie für Ihre Übungen ausgewählt haben. Typischerweise gibt es Unterschiede bei den Datentypen, wenn Sie die Datenbanken und Tabellen neu anlegen, und dann späterhin bei der Verwendung von Anführungszeichen. Ab und an sind nur gewöhnliche Redezeichen erlaubt, manchmal nur Hochkommata und manchmal auch Beides. Über Suchen/Ersetzen im Textverarbeitungsprogramm könnten Sie dies dann ebenfalls schnell anpassen, sodass die Übungsdateien schnell für Ihre SQLUmgebung nutzbar sind. Standard-SQL ist in der Praxis mehr ein Konzept oder ein Vorschlag der ISO (Internatonal Standard Organization), das in Reinform – also so, wie in der offiziellen Standarddokumentation beschrieben – fast nirgendwo eingesetzt wird. SQL 92 ist dabei in drei Unterlevel aufgeteilt: EntrySQL-92, Intermediate-SQL-92 und Full-SQL-92. In Kürze wird eine neue Version erwartet. Die Inhalte der Dokumente (wie wir sie eingesehen haben) beschäftigen sich mit Multimedia-Daten und
SQL
13
EINLEITUNG
Textstrukturen. Bis dies jedoch umgesetzt ist, bleibt für längere Zeit abzuwarten, da ja schon der aktuelle Standard nicht komplett im Einsatz ist. Verschiedene Datenbanksysteme unterstützen unterschiedliche Befehle und Konzepte, gehen über den Standard hinaus oder bieten nicht alle Möglichkeiten an. Daher war es ein Problem, für ein handlungs- und praxisorientiertes Buchkonzept die Balance zu finden zwischen einer Übersicht über die Sprache SQL und anwendungsbezogenen Beispielen. Als Kompromiss wurde das Buch in drei Teile aufgebaut: ¾ Datenbank-Planung und Konzeption: In diesem Teil erhalten Sie Hinweise zu Begriffen, die im Zusammenhang mit Datenbanken auftauchen und für alles Weitere grundlegend wichtig sind. Zudem stellen wir Ihnen das Konzept des Relationen Datenmodells sowie eine Planungshilfe mit dem Entity-Relationship-Modell vor. Mit Hilfe von SQL setzen Sie dann die geplante Datenbank um. ¾ SQL-Standard: Dieser Teil stellt anhand des SQL-Standards die typischen DB-Aktionen wie einfache/komplexe Abfragen oder Sichten dar. Sooft wie möglich erhalten Sie die Ergebnisse der einzelnen Abfragen als Abbildung neben den Quelltexten. Da nicht alle Datenbanken (wie Sie noch sehen werden) alle Abfragentypen unterstützen, haben wir mit Hilfe eines Programms in PHP verschiedene Datenbanken angesprochen und die Ergebnisse automatisch ausgeben lassen. So ist das Ausgabeformat immer einheitlich. Besonders ausführlich lernen Sie das Thema Abfragen kennen, da diese Befehle für den alltäglichen Gebrauch innerhalb anderer Programmiersprachen fast ohne Unterschiede zum Standard gültig sind. Teilweise stellen die verschiedenen DBS weitere Funktionen als der Standard zur Verfügung, um Ergebnisse zu formatieren oder zu analysieren. ¾ SQL-Erweiterungen und Datenbanksysteme: Da sich in diesem Buch alles primär um SQL dreht, erhalten Sie innerhalb des Hauptteils nur bei großen Unterschieden zum Standard weitergehende Hinweise auf einzelne Datenbanksysteme. Damit Sie dennoch eine eigene SQLUmgebung für eigene Experimente mit den Inhalten einrichten können, stellen wir Ihnen drei ausgewählte Systeme vor: MySQL (für den privaten und nicht-kommerziellen Gebrauch kostenloses DBS, das im Internet sehr häufig eingesetzt wird), MS SQL-Server (typischer Einsatz zusammen mit einer Windows-Umgebung und MS Access als Benutzerschnittstelle und in Unternehmenslösungen) und Oracle (Alleskönner und Spezialist für Großdatenbanklösungen in größeren und größten Zusammenhängen offline und online). Wir hoffen, Ihnen damit eine gute Auswahl aus verschiedenen Bereichen bieten zu können. Jedes dieser drei Systeme stellen wir Ihnen so vor, dass Sie es installieren und im System Datenbanken und Tabellen anlegen sowie Abfragen ausführen können. Soweit es geht, wird die Bedienung dabei SQL-basiert ablaufen. Weitere Informationen übersteigen die Zielsetzung des Buchs, sodass wir auf andere Werke dieser Reihe und dieses Verlags verweisen. Nehmen Sie diese Projekte also als Möglichkeit, DBS zu vergleichen und eine oder mehrere als Übungsumgebung einzurichten.
Wenn Sie die SQL-Befehle der folgenden Projekte bereits testen wollen, dann lesen Sie bitte zunächst die Projekte zu den einzelnen DBS. So können Sie sich eine SQLUmgebung für Übungszwecke einrichten.
14
SQL
2 Grundlagen realationaler Datenbanken
SQL
15
16
SQL
2 Grundlagen relationaler Datenbanken
Lernen Sie wichtige Datenbankkonzepte kennen
Allgemeine Vorstellungen besitzt jeder, wenn es um Begriffe wie Daten, Datenbankmodell oder zu modellierende Objekte geht. Vielleicht erscheint es sogar ein wenig übervorsichtig, sich Gedanken um die einzelnen Begriffe zu machen, doch im Rahmen dieses Moduls werden Sie anhand eines zunächst einfach erscheinenden Beispiels sehen, wie komplex die Entwicklungsarbeit einer Datenbank ist und welche typischen Schwierigkeiten (Herausforderungen) zu meistern sind. Anhand der hier vorgestellten Regeln können diese Klippen erfolgreich umschifft werden.
ein Datenbanksystem zu beschreiben mit dem ER-Modell umzugehen und ein ER-Diagramm zu zeichnen einen Weltausschnitt in ein Datenmodell zu überführen ein Datenmodell mit Hilfe von Normalenformen zu optimieren
2.1 Komponenten eines Datenbanksystems Im Alltag verschwimmen oft die Begriffe Datenbanksystem und Datenbank zu einer Einheit, die sie zwar im Endeffekt bilden, aber aus technischer Sicht nicht sind. Der trügerische Eindruck entsteht, weil die Daten innerhalb der eigentlichen Datenbank oftmals direkt verbunden mit ihrem Ausgabemedium gesehen werden. Im Internet ist es vielleicht noch am einfachsten, die klare Trennung von Datenbank und Ausgabemedium festzumachen: Ergebnisse einer Abfrage z.B. in einem Webshop gelangen im Browser innerhalb einer HTMLSeite zum Benutzer. Sobald die ausgegebenen Bücher, Preise, ISBN-Nummern und was sonst noch bei einem Internet-Buchhändler abgefragt werden kann, vom Webserver in eine HTML-Datei geschrieben werden, dient die HTML-Seite bzw. der Internet-Browser als Ausgabemedium, während die Datenbank von dieser Ausgabe losgelöst ist und auch keine direkter Verbindung mehr zu ihr besteht. Diese
SQL
17
GRUNDLAGEN
RELATIONALER
DATENBANKEN
müsste erst wieder durch eine erneute Abfrage aufgenommen werden. Das Datenbanksystem besteht aus zwei Komponenten, von denen die eine die Datenbank mit den Daten selbst und die andere das Datenbankmanagementsystem ist, das die Datenbank verwaltet. Verwaltung bedeutet im obigen Beispiel, dass das DMBS die Anfrage nach einem speziellen Buch oder nach beliebig vielen Büchern, die die vom Benutzer vorgegebenen Kriterien erfüllen, an die Datenbank schickt und die zurückgegebenen Daten über den Webserver an den Shopbesucher weiterleitet. Gleichzeitig erfüllt es eine Sicherungsfunktion, da über die Schnittstelle Browser dem Benutzer nur bestimmte Aktionen innerhalb des DBS gestattet werden. Er kann so bspw. nur Daten abfragen und Daten in Form einer Bestellung schreiben. Es wird ihm darüber hinaus vollständig verwehrt, Datensätze zu löschen, welche die angebotenen Bücher betreffen. ¾ Datenbanksystem heißt eine Struktur, die aus Datenbank und Datenbankmanagementsystem besteht. Der korrekte Oberbegriff für die Datenbank mit ihren Daten und das Datenbankmanagementsystem mit Verwaltungsfunktionen lautet Datenbanksystem. ¾ Datenbank heißt der Speicherort strukturierter Daten. Die Datenbank (engl. Data Base) als solche stellt den Speicherort sämtlicher Daten auf einem physikalischen Datenträger wie CD-ROM, DVD, Festplatte usw. dar. In Abhängigkeit vom jeweiligen Dateisystem und Datenbankmodell werden diese Daten verwaltet. Zugriffszeit und Speicherplatz wiederum sind hauptsächlich abhängig von der Hardware des Speicherträgers als solchen und der Hardware der Zugriffsgeräte (z.B unterschiedliche Geschwindigkeiten bei Festplatten und CD-ROM-Laufwerken). Eine weitere Einflussquelle stellt auch das Datenmodell selbst dar. Auf dieser Ebene unterscheidet man auch einen Basisbereich, der die tatsächlichen Daten enthält, und einen Systemkatalog (engl. Data Dictionary) mit Informationen über die logische Struktur der gesamten Datenbank. Diese Informationen können auch mit dem Begriff der Metadaten (Daten über Daten) bezeichnet werden. ¾ Datenbankmanagementsystem heißt die Komponente eines DBS, das Datenverwaltung und Datensicherheit bereitstellt. Der zweite Bestandteil eines Datenbanksystems ist das Datenbankmanagementsystem (engl. Data Base Management System), das die Schnittstelle zwischen der Datenbank und der Kommunikationsschnittstelle zum Benutzer bildet. MySQL ist beispielsweise eine solches DBMS mit vielen verschiedenen Funktionen für die Einrichtung und Benutzung der Datenbank: Datenzugriff, Gewährleistung von Datensicherheit, Datenmanipulation, Datenverwaltung und Einrichtung des Datenmodells.
18
SQL
GRUNDLAGEN
RELATIONALER
DATENBANKEN
2.1.1 Sichten auf ein DBS Mit dem Begriff Sicht (engl. View) sollen unterschiedliche Betrachtungsweisen einer Datenbankkonzeption bezeichnet werden. Es entspricht einem Drei-Ebenen-Modell, das von ANSI/SPARC (engl. American National Standards Institute/Standards Planning and Requirements Committee) in den 70er Jahren empfohlen wurde. Diese Konzeption diente der Vereinheitlichung und Vereinfachung aktueller und künftiger Datenbanksysteme. Man hatte bereits die Bedeutung der Fähigkeit eines DBS erkannt, sich weiterzuentwickeln und den Datenbestand auch in neuen Technologien weiterhin benutzbar zu machen. Um kompatibel zu allen System und migrationsfähig für alle kommenden Technologien zu bleiben, bildete die Forderung nach Unabhängigkeit der drei Ebenen untereinander das Kernelement der Empfehlung. Die Arbeit, die Sie sich heute machen, müssten Sie also zumindest laut dieser Theorie noch in 20-30 Jahren verwenden können. Die einzelnen Begriffe sind dabei durchaus wörtlich zu nehmen, wie die folgenden Erklärungen zeigen: ¾ Interne Sicht: Direkt auf Datenbankebene beschreibt diese Sichtweise den Blick auf die Datenorganisation und die Art und Weise, wie die Datensätze auf einem geeigneten Speichermedium abgelegt werden. Mögliche Aufgaben aus dieser Perspektive sind die Zugriffszeiten, die vorhandene Datenmenge und Eigenschaften des Datenmodells. ¾ Konzeptionelle Sicht: Schaut man aus dieser Perspektive auf eine Datenbank, tritt das Datenmodell zu Tage, also die Objekte im Weltausschnitt, der mit Hilfe der Datenbank modelliert werden sollte. Die in der Realität gefundenen Objekte erhalten in der Konzeption bzw. im Datenmodell bestimmte Eigenschaften, die mit den Eigenschaften in der Wirklichkeit übereinstimmen. Ein Unternehmen würde hier also für das Objekt Mitarbeiter die Eigenschaften Sozialversicherungsnummer, Alter, Adresse und natürlich den Namen oder die Fertigkeiten erfassen. Zusätzlich kümmert sich die konzeptionelle Sicht darum, Beziehungen zwischen diesen Objekten einzurichten, die schnelle und einfache Abfragen erlauben. ¾ Externe Sicht: Benutzer können von außen mit Hilfe von vorbereiteten oder eigenen Abfragen Datensätze suchen und ändern. Dabei kann man entweder direkt SQL-Befehle benutzen oder verschiedene Hilfsmittel (Stichwörter, Auswahllisten, Berichte oder Profisuche). Diese Möglichkeiten werden Ihnen vom DB-Administrator oder DB-Entwickler zur Verfügung gestellt. Sie regeln gleichzeitig auch die Art und Weise der verschiedenen Möglichkeiten, eine DB von außen zu betrachten. Nicht jeder darf alle Daten sehen, da Informationen wie Umsatzzahlen zwar hochinteressant, aber nicht so sehr für Kunden bestimmt sind, z.B. die Produktinformationen.
SQL
19
GRUNDLAGEN
RELATIONALER
DATENBANKEN
2.1.2 Benutzergruppen eines DBS Im einleitenden Beispiel tauchte bereits eine der drei Gruppen auf, die in Zusammenhang mit einem DBS genannt werden können. Der Besucher eines Webshops, der Controller, der mit Abfragen die Daten untersucht oder der Buchhalter, der über die Buchungssätze Daten generiert, zählen zu den so genannten Anwendern. Sie haben eine externe Sicht auf die Datenbank und greifen mit speziell konfigurierten Programmen auf die Datenbank zu. Ein Zugriff kann dabei über eine Abfrage oder über Dateneingabe erfolgen. Änderungen wie das Entfernen von Tabellen oder ihre Vergrößerung führt der Administrator aus. Er ist in dieser Hinsicht für die Weiterentwicklung und den Erhalt der Datenbank verantwortlich und betreut sie mit speziellen Hilfsmitteln. Manchmal arbeitet der Modellierer in Personalunion auch als Administrator, doch gerade bei großen Projekten, die extern betreut werden, wird die Datenbank von einem externen Berater bzw. einer anderen Firma entworfen und implementiert. Mit Hilfe von Schulungen wird dann eine Gruppe von Mitarbeitern des Kunden in die Lage versetzt, als Administratoren der neuen Datenbank zu wirken.
2.1.3 Anforderungen an ein DBS Um wie in den nächsten Lektionen ein gutes Datenmodell zu erzeugen, das nicht bereits nach den ersten Einträgen oder ersten umständlichen Abfragen geändert oder sogar gelöscht werden muss, kann man sich in jede einzelne Personengruppe hineindenken, die eine DB benutzen wird. Ihre verschiedenen Motivationen und Interessen führen zu allgemeinen Wünschen, wie der Weltausschnitt in einer DB abgebildet sein sollte. Diese Wünsche lassen sich folgendermaßen in einer Kriterienliste zusammenfassen: ¾ Gute Repräsentation der realen Welt: Die Datenbank muss ein getreues Abbild der Realität mit aktuellen Daten liefern. ¾ Keine Datenredundanz: Die Informationen einer Datenbank sollen in ihrer Beschreibung und Speicherung einzigartig sein. ¾ Unabhängigkeit der Daten mit Blick auf Benutzung: Die Programme zur Benutzung der Datenbank sollen auf Hard- und Software-Seite (physische Unabhängigkeit) wie auf organisatorischer Seite (logische Unabhängigkeit) unabhängig sein. ¾ Leichter Datenzugriff: Auch mit Datenbanken nicht vertrauten Benutzern muss ein einfacher Informationszugriff möglich sein. ¾ Sicherheit und Vertraulichkeit: Sowohl auf physischer (Datenverlust durch Hardwarebeschädigung oder Mutwillen) wie auch auf logischer Seite (inhaltliche Zugriffskontrolle) müssen Sicherheitsstandards bestehen. ¾ Leistung der Abfragen und Anwendungsprogramme: Auch bei gleichzeitigem Zugriff auf die Daten muss eine akzeptable Antwortzeit gegeben sein.
20
SQL
GRUNDLAGEN
RELATIONALER
DATENBANKEN
2.2 Daten und Datenstrukturen Die kleinsten Einheiten in einem DBS sind zweifellos die Daten, die in einem sinnvollen Zusammenhang stehen und von Programmen unterschiedlicher Art für Zwecke der Kontrolle (Finanzsituation), des Marketing (personalisierte Kundenprofile) oder der Verwaltung (Plattensammlung) verarbeitet werden. Dieser sinnvolle Zusammenhang ist in nebenstehender Abbildung illustriert: Interessant sind nicht alle möglichen Namen und Adressen, die in den Telefonbüchern der Welt stehen (Grundgesamtheit), sondern nur die Namen und Adressen von Menschen, die wenigstens einmal ein Zimmer einer Hotelkette gebucht haben. Diese Daten und noch wesentlich mehr werden in die Datenbank aufgenommen, sobald ein Gast über ein Hotelreservierungssystem als Benutzerschnittstelle ein Zimmer bucht. Damit trägt er seinen Namen sowie weitere Informationen wie Beginn und Ende seines Aufenthalts und natürlich den Hotelnamen in ein Formular ein. Entweder wird dieses Formular direkt im Internet entgegengenommen oder wandert erst über eine zentrale Stelle wie z.B. das Fremdenverkehrsamt. Im letzteren Fall würden die Daten vermutlich zusätzlich für Kontroll- und Werbezwecke gespeichert, die nicht das Hotel, aber die Stadt als solche betreffen. In einer erste Phase benötigt das Hotel die Daten lediglich, um die Zimmerbelegung und die Rechnungserstellung zu automatisieren. In einer zweiten Phase könnte man dann diesen Gast in den regelmäßigen Verteiler des Hotelwerbematerials aufnehmen, sodass er für mindestens drei Jahre jährlich eine Broschüre über die weltweit zu buchenden Hotels der Kette erhält. Je mehr Daten vorhanden sind, desto genauer könnte diese personalisierte Marketingstrategie ausgeführt werden: Kennt man den Beruf und weiß man zusätzlich, dass der Grund für den Aufenthalt ein Messebesuch war, so könnte man in einem regelmäßig ablaufenden Programm die Messetermine mit den Aufenthaltsgründen abgleichen und zielgenau die vorjährigen Messebesucher anschreiben, um das Hotel in Erinnerung zu rufen.
2.2.1 Eigenschaften von Daten Mit Hilfe von drei Kategorien kann man die Eigenschaften von Daten beschreiben. Insbesondere bei der Neu- oder Weiterentwicklung einer Datenbank ist es wichtig, diese drei Eigenschaftsräume mit Leben zu füllen. Dass dies natürlich dann in ihrer Verarbeitung auch für die Programme gilt, in denen sie z.B. als Variablen auftreten, wird Ihnen schon bekannt sein.
SQL
21
GRUNDLAGEN
RELATIONALER
DATENBANKEN
¾ Der Datentyp dürfte die bekannteste Achse sein, mit der Daten beschrieben werden können. Er ordnet Informationen in bestimmte Kategorien, für die jeweils unterschiedliche Verarbeitungsmöglichkeiten bestehen. Der Name des Hotelgastes kann sinnvollerweise nur vom Datentyp Text sein, damit entsprechende Programmfunktionen und SQL selbst eine Spalte nach dem Alphabet sortieren oder eine Zeichenkette in ihre Bestandteile zerlegen kann. Die kleinste Einheit dieses Datentyps wiederum ist der einzelne Buchstabe. Anreise und Abreise dagegen könnten als Zahl oder Text gespeichert werden, wobei aber zusätzlich für diesen speziellen Typ auch noch ein Typ Datum existiert. Mit Zahlen lässt sich natürlich rechnen. Verwenden Sie den Typ Datum, können Sie später über entsprechende Funktionen auch Rechenoperationen durchführen und somit zum Beispiel die Anzahl der Übernachtungen automatisch berechnen lassen. Erst über diese Definition kann man mit Hilfe entsprechender Programmfunktionen die Dauer des Aufenthalts berechnen. Bei der Verwendung des Datentyps Text sind solche mathematischen Berechnungen dagegen gar nicht erst möglich. ¾ Die Eigenschaft Datenformat stellt oftmals kleine Hürden bei ersten Programmierarbeiten dar, wenn z.B. ein amerikanisches Datum in ein europäisches überführt werden soll oder Währungsbeträge nicht mit beliebig vielen Dezimalstellen (Benzin natürlich wieder ausgenommen), sondern mit genau zwei Dezimalstellen ausgegeben werden sollen. Das Problem tritt sicherlich öfters auf und muss manchmal an einer ganz anderen Baustelle gelöst werden. Das Format lässt sich mit SQL in einigen Fällen von vorne herein vorgeben, in anderen dagegen müssen die Ergebnisdaten eigens in das benötigte Format überführt werden. Damit gehört diese Eigenschaft eher zur externen Problemsicht der Abfrage und wird prinzipiell von SQL nicht weiter berücksichtigt. In einer Programmiersprache Ihrer Wahl können Sie mit den entsprechenden Funktionen sicherlich das Format nach Ihren Wünschen anpassen. ¾ Das wohl häufigste Beispiel für die Vorgabe eines Wertebereichs (Domäne) im Internet dürfte die Verwendung der möglichen Werte Herr und Frau für die Spalte Anrede oder Geschlecht sein. Menschen werden typischerweise mit diesen beiden Werten katalogisiert, um z.B. eine korrekte Anrede zu ermöglichen. Gerade bei Auswahl über Optionsfelder lässt sich nichts anderes in die Datenbank eintragen. Möchte man diesen Punkt sehr genau betrachten, so kann man diese Eigenschaft weiter differenzieren: Während der natürliche Wertebereich der in der Realität vorkommende Wertebereich ist (die Zahl Pi besitzt schlicht und einfach unendlich viele Nachkommastellen), muss dieser Wertebereich oft für die Verwendung in einem Rechner eingeschränkt werden (ein Rechner verarbeitet sehr lange Zahlen, aber letztlich doch nur endlich lange). Der Wertebereich letztendlich, der wirklich Eingang in die Datenbank findet, ist noch einmal kleiner, denn neben der rechnerbedingten Endlichkeit und damit Begrenzung von Zahlen oder auch anderen Daten, gibt es Daten, die nur in einer bestimmten Größe (Postleitzahlen haben in Deutschland fünf Stellen, in der Schweiz und in Österreich dagegen vier) oder einem bestimmten Muster (Kreditkartennummern, Telefonnummern, ISBN-Nummern) auftreten. Dieser Eigenbereich kann bereits von der Datenbank mit entsprechenden SQL-Befehlen auf Korrektheit überprüft werden. Das Format wird dabei überprüft und mit einem Musterformat verglichen.
22
SQL
GRUNDLAGEN
RELATIONALER
DATENBANKEN
2.2.2 Klassifikation von Datentypen Wie immer könnte man feinere Verästelungen der Klassifikation von Daten verwenden, doch sollen diese Informationen Ihnen lediglich die wesentlichen Grundlagen vermitteln. Eine einfache Bildung von Unterkategorien im Eigenschaftsraum Datentypen ist die Unterscheidung zwischen elementaren und zusammengesetzten Datentypen. Sie konzentriert sich auf die Elemente der Wertemenge und damit auf die Struktur der Objekte. Typischerweise bewegt man sich bei der Entwicklung von Attributen bzw. Feldnamen von komplexen Begriffen zu elementaren. Dies werden Sie insbesondere bei der Normalisierung von Datenmodellen kennen lernen. ¾ Elementare Datentypen sind die Datentypen, die mit SQL für ein Feld vergeben werden und die bereits oben angesprochen wurden. Relationale Datenbanksysteme verwenden u.a. solche elementare Datentypen wie ganze Zahlen im Gegensatz zu reellen Zahlen, wobei die reellen Zahlen Nachkommastellen aufweisen können und damit genauer sind, wenn z.B. Rechenoperationen auf die einzelnen Daten angewandt werden. Zwei als ganze Zahlen definierte Daten ergeben bei einer nicht ganzzahligen Division keine Nachkommastellen, womit zwangsläufig Ungenauigkeiten auftreten, die man entweder wie bei der Modulo-Rechnung in Algorithmen einsetzen kann oder die man lieber vermieden hätte. Weitere Datentypen wie logische Daten, deren Wertebereich gleichzeitig auf WAHR und FALSCH beschränkt ist, können ebenfalls in Programmierabläufen eingesetzt werden. ¾ Zusammengesetzte Datentypen ergeben sich aus den Oberbegriffen zu Objekten, die in einem Datenmodell eingearbeitet werden sollen. Innerhalb einer Datenbank für eine Hotelkette werden neben den Gastinformationen natürlich auch Informationen zum Aufenthalt gespeichert. Die Aufenthaltsinformationen sind zunächst für die gegenwärtige Abrechnung wichtig. Da aber der Datensatz des Gastes nicht aus der DB entfernt wird, können die Gastinformationen für die oben erwähnten Marketing-Aktivitäten genutzt werden. Bei dieser Überlegung, die auf den Einsatzmöglichkeiten der Daten beruht, trennt man automatisch beide Bereiche voneinander ab. So wird zum Beispiel der Name atomatisiert und in Vorname und Nachname aufgeteilt. Der Datentyp Name ist dann also zusammengesetzt aus Vorname und Nachname. Weitere Oberbegriffe wären dann im Rahmen der Gastinformationen die Adresse, wobei diese ebenfalls jeweils in zusätzliche Feldnamen aufgespaltet werden kann. Hier ist es wichtig zu erwähnen, dass unterschiedliche elementare Datentypen das komplexe Objekt Adresse bilden. Während die Postleitzahl eine Ganzzahl ist, sind Straßen- und Stadtnamen vom Typ Text. Die
SQL
23
GRUNDLAGEN
RELATIONALER
DATENBANKEN
Hausnummer dagegen ist ebenfalls vom Typ Text, da ja Kombinationen aus Zahlen und Buchstaben (Bahnhofstr. 3a) möglich sind.
2.3 Beziehungsstrukturen zwischen Daten Eine letzte wichtige Eigenschaft von Daten innerhalb eines Datenmodells ist die Beziehungsstruktur. Sie ist zunächst in der Realität vorhanden und wird durch die Abbildung im Datenmodell für die DB bedeutsam. Zwei hierarchische Ebenen müssen unterschieden werden: ¾ Beziehungen innerhalb eines Objekts: Die Beziehungen, die in den Attributen für den Hotelgast existieren, sind nur für ihn als Individuum bzw. – sofern sie wie bei Messebesuchen bei einer Gruppe von Individuen auftreten – als kleine Unterkategorie des Objekts Hotelgast interessant. Geht aus irgendeinem Grund die Information verloren, dass er wegen eines Messebesuchs im März im Hotel ein Zimmer gebucht hat, verschwindet in diesem kleinen Beispiel auch die Möglichkeit, ihn personalisiert zu bewerben. Es ist gerade diese Information bzw. ihre Beziehung zu den Attributen Namen und Adresse, die ihn ein wenig heraushebt und besser beschreibt. ¾ Beziehungen zwischen Objekten: Zwischen verschiedenen Objekten mit weitestgehend unterschiedlichen Attributen, also Daten, die pro Objekt erfasst werden, sind Beziehungen besonders bedeutsam, da sie die Grundkonzeption relationaler DBS bilden. Erst über spezielle Beziehungen, wie sie bspw. über das Schlüsselkonzept gebildet werden, können Netze von Objekten entstehen und Vorteile wie z.B. Redundanzfreiheit genutzt werden. In diesem Zusammenhang sei nur kurz darauf verwiesen, dass ein Hotel, das sich durch günstigen OnlineAnschluss im Hotelzimmer, lange Abendessenszeit und Transferdienst auf Messebesucher spezialisiert hat, die Messen ebenfalls als eigenes Objekt in der DB erfassen könnte. So könnten über die Verwendung eines eindeutigen Messenamens (oder typischerweise eine Nummer / einen Schlüssel) im Objekt Messebesucher genauere Messeinformationen mit den Hotelgästen kombiniert werden. Beziehungstyp Definition Eineindeutig
Jedem Objekt vom Typ A ist genau ein Objekt vom Typ B zugeordnet.
1:1 Funktional 1:n Komplex n:m
24
Jedes Objekt vom Typ A steht mit beliebig vielen Objekten vom Typ B in Beziehung. Dagegen steht ein Objekt vom Typ B höchstens mit einem Objekt vom Typ A in Beziehung. Beliebig viele Objekte vom Typ A stehen mit beliebigen Objekten vom Typ B in Beziehung und umgekehrt.
SQL
GRUNDLAGEN
RELATIONALER
DATENBANKEN
2.3.1 Die 1:1 (eineindeutige) Beziehung In einem Ehepaarkreis mit vier Ehepaaren kann man die beiden Objekte Ehemänner und Ehefrauen unterscheiden. Da die Objektanzahl begrenzt ist, ist auch der Wertebereich für das Attribut Vorname auf insgesamt acht Werte beschränkt. Jeweils vier davon lassen sich auf eine der Gruppen verteilen. Kein Vorname taucht doppelt auf, sodass unterschiedliche Personen auch unterschiedliche Vornamen besitzen. In einer eineindeutigen Beziehung zwischen zwei Wertebereichen gehört zu jedem Wert des einen Wertebereichs ein Wert des anderen Wertebereichs. In diesem Fall ist Ralf mit Susanne, Reinhard mit Birte, Tom mit Tina und Nils mit Anja verheiratet. Wie das bei deutschen Ehepaaren so üblich ist, hat jeder nur einen einzigen Ehepartner.
2.3.2 Die 1:n (funktionale) Beziehung Sobald man Kinder mit zu der Familie zählt, wird alles bunter, und der Organisationsaufwand nimmt zu. So ist es natürlich auch bei der Bestimmung der Beziehungen. Susanne und Tina sind bereits Mütter, während Birte und Anja noch keine Kinder haben. Eine funktionale Beziehung zeichnet sich dadurch aus, dass zu den Werten des einen Wertebereichs null, einer oder mehrere Werte des anderen Wertebereichs gehören. Die funktionale Beziehung bedeutet also: Jeweils ein Kind hat genau eine Mutter. Umgekehrt kann aber eine Mutter mehrere Kinder haben. Daher auch die Beziehung 1:n. So kann also Susanne zwei Kinder haben, Tina eines und die anderen Mütter keine. Bei der funktionalen Beziehung ist also nur erlaubt, dass ein Wertebereich uneindeutige Werte hat, sodass es wie in der Realität ausgeschlossen ist, dass ein Kind zwei Mütter hätte.
2.3.3 Die n:m (komplexe) Beziehung Eine komplexe Beziehung liegt vor, wenn keine Einschränkungen wie bei der funktionalen Beziehung gemacht werden können. Ein solcher Fall stellt sich, wenn weitere Verwandten das Bild betreten. Eine Tante kann sowohl einen als auch mehrere Neffen oder Nichten haben. Umgekehrt ist es auch möglich, dass ein Kind mehrere Tanten besitzt. So ist Birte sowohl von Stefan als auch von Kristina die
SQL
25
GRUNDLAGEN
RELATIONALER
DATENBANKEN
Tante, während Holger als Tanten Tina und Anja nennen kann. Eine komplexe Beziehung liegt vor, wenn es zu jedem Wert eines Wertebereichs null, einen oder mehrere Werte eines anderen Wertebereichs gibt und umgekehrt. Damit sind die Beschränkungen der funktionalen Beziehung aufgehoben.
2.4 Vom ER-Modell zum RDM Bevor man sich daranmacht, für ein Datenbankprojekt sofort Tabellen und Feldnamen mit SQL zu tippen, kann man mit Hilfe eines grafischen Modells versuchen, die zu modellierenden Objekte zu finden und sich einen Überblick über die Beziehungen zu verschaffen. Als Beispiel soll ein privates Beispiel dienen: Eine Plattensammlung soll komplett mit Hilfe einer DB erfasst werden. Die Daten müssen am Ende so vorliegen, dass ohne Schwierigkeiten ein Überblick über die Songs und verschiedenen Versionen abgefragt werden kann. Ein weiteres Ziel könnte hier eine Informationsbörse sein, da ausschließlich ein Künstler mit allen möglichen Varianten seiner Stücke betrachtet wird. Gerade unter diesem Blickwinkel – also bei Künstlern wie Tina Turner, den Rolling Stones, Rod Stewart oder Joe Cocker – ergeben sich unterschiedliche Schwierigkeiten und die Gefahr der Datenredundanz. 1. Entwickeln Sie ein semantisches Modell. ¾ Tina Turner hat verschiedene Lieder in ihrem Repertoire. Ein SONG hat einen Titel, Autoren, die Musik und Text geschrieben haben und ein Erstellungsdatum, zu dem die Autoren das Lied verfasst haben. ¾ SONGS existieren in verschiedenen Varianten: Die beiden großen Gruppen sind LiveAufnahmen und Studio-Aufnahmen. Teilweise gibt es bis zu 20 verschiedene Live-Aufnahmen eines Titels aus verschiedenen Jahren und Städten. Die Studio-Aufnahmen lassen sich noch einmal unterteilen in Mixe und Versionen, die auf einer Single bzw. auf dem Album veröffentlicht wurden. Die Mixe unterscheiden sich normalerweise durch einen speziellen Namen wie „The best (extended muscle mix)“, allerdings existieren auch Mixe, die zwar auf unterschiedlichen CDs mit verschiedenen Namen veröffentlicht wurden, aber in Wirklichkeit die gleichen sind. ¾ Die SONGS befinden sich auf verschiedenen DATENTRAEGERN wie 5-inch und 3-inch-CDs, Maxi- und Single-LPs, DVDs, Videos, MiniDiscs usw. Vom gleichen DATENTRAEGER existieren unter dem gleichen Titel verschiedene Ausgaben in unterschiedlichen Ländern. So gibt es bspw. vom Album „Wildest Dreams“ unterschiedliche Ausgaben aus Europa, den USA, Kanada und Japan. Zusätzlich gibt es aus Europa und Australien zwei „special tour editions“ mit einer Bonus-CD in einer Pappbox. Gleiche Titel werden auch auf verschiedenen Datenträgertypen veröffentlicht. So kann man ein Konzert aus Rio de Janeiro von 1988 auf Video, DVD (USA und Europa verschieden), LaserDisc und CD-i kaufen. ¾ Sämtliche Audio- und Videoträger sollen gemeinsam erfasst werden.
26
SQL
GRUNDLAGEN
RELATIONALER
DATENBANKEN
¾ Weitere Objekte, die zu einem späteren Zeitpunkt in der Datenbank erfasst werden sollen, sind Tourdaten und Bücher über TT.
Ein semantisches Modell versucht, die Objekte der Realität möglichst genau zu erfassen und so eine Basis für die endgültig zu erstellende Datenbank zu liefern. Im Idealfall entsteht ein Text, der bereits alle Objekte, Beziehungen und Attribute nennt. Die Entwicklung des semantischen Modells stellt die erste analytische Phase dar.
2. Leiten Sie aus dem semantischen Modell die benötigten Objekte ab. Offensichtlich gibt es zumindest zwei verschiedene Objekte, die in einer Datenbank erfasst werden sollen: Zum einen die einzelnen Songs und zum anderen die Datenträger. Beide erhalten eine vorläufige Liste an Attributen, die sich direkt aus dem semantischen Modell ableitet. Es ist nachher nicht weiter schwierig, sich mehr und mehr Attribute auszudenken, sodass wir uns hier auf die wichtigsten beschränken, um die Vorgehensweise besser zu verdeutlichen. Normalerweise findet man die benötigten Attribute über eine Tätigkeitsanalyse oder eine Objektanalyse. ¾ In einer Tätigkeits- oder Prozessanalyse durchläuft man die gesamten Tätigkeiten, die ein Objekt ausführt. Sie verlaufen teilweise auch parallel zu den Tätigkeiten anderer Objekte, die entweder schon von Anfang an bestehen oder sich erst im Prozessverlauf herausbilden. Für die Entwicklung einer Datenbank, die für die Programmierung eines Webshops eingesetzt werden soll, ist die Tätigkeitsanalyse sehr gut geeignet, Objekte und Attribute herauszufiltern. Als Analogie kann man zusätzlich den Einkaufsprozess in einem online vorhandenen Supermarkt vorstellen: Ein BESUCHER ruft die Seite mit dem Webshop auf und wird dadurch registriert. Dies entspricht bspw. dem Klingeln einer Glocke oder der Aufzeichnung einer Kamera, wie es bei real vorhandenen Tankstellen und Banken oft zu finden ist. Eine entsprechende eindeutige Besuchernummer und eine Zeitinformation könnten hier gespeichert werden. Der BESUCHER könnte den Laden wieder verlassen oder sich für die angebotenen PRODUKTE interessieren. Diese Produkte müssen natürlich die auch in einem realen Laden vorhandenen Attribute wie Preis, Bild, Funktionsbeschreibung oder Menge besitzen. Aus dem Angebot wählt er verschiedene PRODUKTE in seinen WARENKORB, der lediglich seine Auswahl, aber noch nicht seine Kaufentscheidung repräsentiert. Es ist weiterhin möglich, aus dem Laden zu verschwinden, ohne einen Kauf zu tätigen. Erst in dem Augenblick, wo der BESUCHER aus seinem WARENKORB bestimmte PRODUKTE auch wirklich bestellt, liegt eine BESTELLUNG vor. Um eine solche BESTELLUNG auszuführen, muss aus dem BESUCHER ein KUNDE werden, indem er alle nötigen Kontaktdaten hinterlässt. Gleichzeitig entsteht aus dieser Auswahl auch ein AUFTRAG an den Shop-Betreiber. ¾ Die Objektanalyse fokussiert mehr die Beschreibung von Objekten, die real vorhanden sind. So schimmerte sie gerade bereits bei den Objekten KUNDE und PRODUKT durch die Tätigkeitsanalyse hindurch. Bei der Plattendatenbank des Beispiels in dieser Lektion ist sie dagegen die einzig sinnvolle Vorgehensweise, wie Sie bereits im semantischen Modell gesehen haben. Die Tonträger üben keine Aktivität aus, man kann ihnen nicht gedanklich folgen und Zustandsände-
SQL
27
GRUNDLAGEN
RELATIONALER
DATENBANKEN
rungen oder irgendwelche Prozessabschnitte feststellen. Stattdessen besitzen sie real vorhandenen Unterschiede, die man versuchen muss, ordentlich zu klassifizieren. Als Illustration können hier noch einmal die unterschiedlichen Datenträgerarten dienen, welche die Songs enthalten und somit ein wichtiges Unterscheidungsmerkmal darstellen. Der gleiche Song kann demnach auf so unterschiedlichen Trägern wie CD; DVD, LP, LaserDisc, VideoCD oder CD-i gespeichert sein. Damit ist keine Handlung verbunden, sondern ein statischer Zustand der Speicherung oder Adressierung. 3. Erstellen Sie das Entity-RelationshipDiagramm. Dabei werden die einzelnen gefundenen Objekte zueinander in Beziehung gesetzt und in ein Diagramm gezeichnet. Es kann bei vielen Objekten oder Attributen oder komplexen Beziehungsstrukturen beträchtliche Größen erreichen. Wahlweise wird auch ein Name für die Beziehung vergeben, wobei das nicht mehr ganz en vogue ist. Hier tritt nämlich regelmäßig das Problem auf, dass die Beziehung durch den Namen scheinbar von einem Objekt dominiert wird. Element
Bedeutung
Entity
zu modellierendes Ob- Rechteck jekt
Entity-Typ
Objekte mit ähnlichen Rechteck Eigenschaften
Relationship Beziehung Objekten Attribut
Zeichen
zwischen Raute
Eigenschaft eines Ob- Oval jekts
Seit 1976 wird das von P.P. Chen vorgeschlagene Entity-Relationship-Modell (ER-Modell oder ERM) für eine erste Annäherung verwendet, dessen Vorteile in der grafischen Darstellung und der mathematischen Verständlichkeit liegen. Es besteht aus den Elementen Entity, Entity-Typ, Relationship und Attribut.
4. Analysieren Sie die Beziehungen zwischen den Objekten. Wie das so in Einführungsbeispielen üblich ist, liegt natürlich sofort der ungünstigste aller Zustände vor. In nebenstehender Abbildung sehen Sie einen Ausschnitt aus der so genannten Universal Relation, in der alle Daten einer Datenbank in einer großen Tabelle erfasst werden. Diese Tabelle ist besonders ungünstig, da viele Wiederholungen innerhalb der einzelnen Zellen auftreten. Befindet sich der gleiche Song wie „The best (extended mix)“ auf verschiedenen CDs (Maxi-CD, Promo-CD für Radio-Stationen usw.), so würden die Informationen über die Autoren oder das Erstellungsdatum in jedem Datensatz auftauchen. Dies vergrößert den Speicherbe-
28
SQL
GRUNDLAGEN
RELATIONALER
DATENBANKEN
darf der ganzen Datenbank und kann nur als Ausgangsmodell für ein relationales DBS verwendet werden. Über Normalisierungstechniken, die Sie in der nächsten Lektion kennen lernen werden, kann man systematisch eine optimierte Version dieser Universal Relation erhalten und so ein relationales Datenmodell entwickeln. 5. Transformieren Sie das ER-Modell in das relationale Daten-Modell: ¾ Ein Objekt bildet eine eigene Tabelle. ¾ Die Datensätze sind die einzelnen Zeilen einer solchen Tabelle. ¾ Die Attribute stellen die Spalten (Feldnamen) dar. ¾ Ein Schlüssel ist ein spezielles Attribut, das einen Datensatz eindeutig identifiziert. Oft können die übrig bleibenden Attribute bei Entfernung eines Attributes einen Datensatz nicht mehr korrekt oder eindeutig identifizieren. ¾ Der Wertebereich einer Spalte entspricht der Domäne, die dem Attribut zugeordnet wurde. ¾ Eine Beziehung wird entweder über Fremdschlüssel oder über eine eigene Beziehungstabelle ausgedrückt. Es dürfte nicht allzu kompliziert oder schwer verständlich sein, dass das Objekt SONG eine Tabelle namens SONGS erhält, die als Spaltennamen songtitel, autoren und jahr aufweist. Um einen Song bzw. einen Datensatz (Zeile) einer Tabelle eindeutig zu identifizieren, verwendet man eine zusätzliche Spalte für den so genannten Primärschlüssel. Dies kann eine einfache, fortlaufende Nummer wie 25 oder ein komplexer Wert sein, der sich aus bestimmten Teilen wie eine ISBN-Nummer zusammensetzt. Dies verhindert, dass Songs mit gleichen Namen wie z.B. „Don´t leave me this way“ wirklich unterschieden werden. Zwar stammen beide Songs aus verschiedenen Jahren, doch die Spalte jahr kann unter keinen Umständen als Hilfe für die Identifikation eines Datensatzes dienen, da typischerweise mehr als ein Song pro Jahr aufgenommen wurde.
Das RDM (relationale Datenmodell) beruht auf der Überführung der einzelnen Objekte im ER-Modell in Tabellen, die über die Primärschlüssel, die in der anderen Tabelle Sekundärschlüssel sind, in Beziehung stehen. Dieses Datenmodell wurde von E.F.Codd 1970 entwickelt und bildet die Grundlage für relationale Datenbanksysteme. In diesem Zusammenhang wird ein Datenmodell mit nur einer einzigen Tabelle und sämtlichen Informationen als Universal Relation bezeichnet.
6. Spalten Sie die Beziehungen auf. Interessant und vielleicht sogar ein wenig überraschend im Vergleich zum vorhergehenden Schritt ist die Lösung des Beziehungsproblems, das oben kurz erläutert wurde. Zum einen existieren viele verschiedene Versionen des gleichen Titels in Live-Aufnahmen und Mixen, zum anderen wurden diese verschiedenen Versionen mehrfach auf unterschiedlichen Datenträgern veröffentlicht.
SQL
29
GRUNDLAGEN
RELATIONALER
DATENBANKEN
Dem ersten Problem wird durch die Einrichtung einer Tabelle AUFNAHMEN Rechnung getragen. Diese Tabelle sammelt die einzelnen Attribute, die eine Aufnahme annahmegemäß eindeutig klassifizieren. Dazu gehören ein Titel aufntitel und ein aufntyp. Beide Spalten sollen gleichzeitig das Phänomen beschreiben, dass ein Song sowohl in mehreren Mixen als auch in mehreren Live-Aufnahmen vorliegt. Die Beziehung zwischen diesen Tabellen wird durch die Spalte songnr gewährleistet, die als Fremdschlüssel in die Tabelle AUFNAHMEN eingebunden wird. Diese Aufnahmen sind auf verschiedenen Datenträgern veröffentlicht, sodass es am einfachsten ist, eine eigene Tabelle für dieses Phänomen einzurichten, die VEROEFFENTLICHUNGEN heißt. In ihr erhält jedes einzelne Vorkommen eines Songs auf einem Datenträger eine Veröffentlichungsnummer in der Spalte veroeffnr. Die Tabelle AUFNAHMEN wird dann über die Spalte aufnnr als Fremdschlüssel in der Tabelle VEROEFFENTLICHUNGEN verbunden. Zum Schluss muss noch berücksichtigt werden, dass die Datenträger diejenigen Objekte sind, die die nur aus datenbanktechnischen Gründen eingeführten irrealen Objekte der Veröffentlichungen enthalten. Da jeder Datenträger ein abgrenzbares Objekt der realen Welt ist und über hinreichend viele Attribute auch klassifiziert werden kann, enthalten die Datenträger in diesem Datenmodell keine Songs mehr, sondern Veröffentlichungen. Diese Veröffentlichungen wiederum sind mit den Aufnahmen verbunden. In der Tabelle VEROEFFENTLICHUNGEN werden die Beziehungen zu der Tabelle DATENTRAEGER über den Fremdschlüssel datnr geleistet, während sich in der Tabelle DATENTRAEGER eine Spalte veroeffnr befindet. Die entstehende Tabelle bezeichnet man schlagwortartig mit dem Begriff Beziehungstabelle, da mit ihrer Hilfe eine m:m-Beziehung in zwei 1:n-Beziehungen aufgespalten wird. 7. Verhindern Sie Dateninkonsistenzen. Bisher hat sich die Erfassung der Plattensammlung von Tina Turner als reichlich komplex erwiesen. Mit einem letzten Schritt muss nun sichergestellt werden, dass die Daten korrekt eingetragen werden. Hierbei müssen entsprechende Konventionen aus realen Gegebenheiten abgeleitet werden, um die Daten konsistent zu machen. Nur so können Sie garantieren, dass Abfragen auch tatsächlich korrekt ablaufen. Zwei typische Konzepte helfen bei diesem Ziel:
30
SQL
GRUNDLAGEN
RELATIONALER
DATENBANKEN
¾ Wertebereiche oder Domänen: So besteht der Wertebereich für die Spalte aufntyp lediglich aus den Werten {live, nicht live}. Per Entscheidung müssen dann Live-Aufnahmen, die im Tonstudio nachbearbeitet wurden, ebenfalls zu den Live-Aufnahmen zählen, da sie ihnen näher verbunden sind als reine Studio-Aufnahmen. Ebenfalls unter den Begriff „live“ subsumiert werden Fernsehauftritte, bei denen TT live gesungen hat. Da wiederum einige Konzerte im Fernsehen übertragen wurden, könnten hier Gefahrenquellen liegen, wenn eine eindeutige Zuordnung nicht sofort einsichtig ist. Ist daher von vorneherein bekannt, dass nur diese beiden Werte in der Spalte eingetragen sind, können Abfragen der Form „Zeige alle Song mit aufntyp=live“ korrekt abgearbeitet werden. Ähnliche Wertebereiche gelten für die Spalten datart und datunterart. Während Vinyl ein Material ist, das symbolisch für alle Tonträger stehen kann, die aus diesem Material gefertigt werden, muss allerdings in der datunterart unterschieden werden zwischen {maxi, single, LP}. ¾ Namensdefinitionen: Sollen die Werte suchbar bleiben, was z.B. für Titel notwendig ist, dann kann man bei Namen, die nicht von vorneherein vorgegeben werden, sondern vom DB-Benutzer eingetragen werden, sich über Namenskonventionen behelfen. Dieses Problem stellt sich in der Tabelle AUFNAHMEN in der Spalte aufntitel. Mixe haben einen eindeutigen Namen, der vom Produzenten festgelegt ist und sich meistens auf einem Datenträger befindet. In den seltenen Fällen, in denen ein Mix zwar laut Datenträger existiert, sich aber in Wirklichkeit gar nicht als solcher oder als ein anderer entpuppt („Missing you“ und „On silent wings“CD-singles aus Großbritannien, 1996), müsste man sich mit einem entsprechenden Kommentar z.B. in einer Klammer behelfen. Sämtliche Live-Aufnahmen jedoch müssen vom DBBenutzer benannt werden, da sie von der Plattenfirma nicht mit einem informativen Namen versehen wurden. Hier könnte man folgenden Wertebereich mit einer Namensdefinition vorgeben: {stadt, land; land; kontinent; unbekannt}. Im günstigsten Fall kennt man also bei einer Live-Aufnahme die Stadt und das Land: „The best“ – Amsterdam, The Netherlands. In anderen Fällen besitzt man nur Informationen über das Land oder kann nur einen Kontinent zuordnen wie bei einigen Aufnahmen vom Live-Album „Live in Europe“. Da gleichzeitig eine Radioaufnahme der BBC existiert, kann man einige Aufnahmen dem Konzert in London, Wembley Arena zuordnen, während für alle anderen nur der Kontinent als Ortsangabe übrig bleibt. Mit Hilfe eines Jokerwerts wie unbekannt kann dann auch ein Titel vergeben werden, der sich über die Konventionsrichtlinien nicht ermitteln lässt. 8. Testen Sie das Datenmodell durch beispielhafte Einträge. Es empfiehlt sich zusätzlich, lieber mit schlechten als mit guten Daten einen Testlauf zu machen, damit evtl. Fehler noch früh genug gefunden werden können. Schlechte Daten in diesem Zusammenhang sind vom DB-Entwickler aus der Prozessanalyse gewonnene Beispieldaten oder solche, die der Auftraggeber / Benutzer ihm als typische übermittelt hat. In jedem Fall sind es nicht die guten Daten, die nachher im normalen Arbeitsprozess, wenn alles funktionieren sollte, eingegeben werden. Mögliche Fehler, die insbesondere durch unerfasste Ausnahmeregelungen entstehen können, können Sie mit Testeinträgen versuchen zu entdecken. In diesem Fall sollte man also einen Titel wählen, der erstens auf sehr vielen Datenträgern erscheint, zweitens in Mixen und in Live-Aufnahmen vorliegt und drittens sogar noch als Duett mit Mixen vorhanden ist. In der Tabelle SONGS wird daher der einzelne Song nur einmal erfasst, wie es ja auch geplant war: songnr
SQL
titel
autoren
Jahr
31
GRUNDLAGEN
25
The best
RELATIONALER
DATENBANKEN
Chapman / Knight
1989
Für die Tabelle AUFNAHMEN ergeben sich bereits einige verschiedene Varianten, wobei die jeweils in den Tabellen angegebenen noch lange nicht der Realität entsprechen. Mit Hilfe der Songnummer können einzelne Aufnahmen identifiziert werden. Interessant ist hier, dass der aufntitel für die Solo-Fassung von 1989 laut Plattenfirmen der gleiche ist wie die Duettversion aus Australien. Als Auswahl aus den verschiedenen Live-Aufnahmen unterscheiden sich die beiden Fassungen sowohl im Datum als auch im Titel. Zwar hat TT sie beide in Deutschland gesungen, aber die Städte sind verschieden. aufnr
songnr typ
aufntitel
36
25
nicht live
album version
37
25
nicht live
single edit
38
25
live
germany, Munich
1998
39
25
live
germany, Hamburg
1996
25
nicht live
single edit
1989
40
duettpartner
datum 1989
Jimmy Barnes
1993
In der Tabelle VEROEFFENTLICHUNGEN testet man nun den komplizierten Fall der australischen Ausgabe des Albums „Simply the best“, das als Doppel-CD erschienen ist und zwei verschiedene Versionen von „The best“ enthält: Zum einen die single-edit-Version, die auch auf die europäische und amerikanische CD gepresst wurde, und zum anderen das Duett mit Jimmy Barnes. Alle Versionen existieren zusätzlich in gleicher Form auf CD-Singles, die hier nicht betrachtet werden. vnr
aufnr
datnr
12
37
89
13
36
90
Zum Schluss führt die Tabelle DATENTRAEGER für beide Versionen zur richtigen CD. Da sowohl eine von der Plattenfirma vergebene Nummer für das CD-Paket als auch eine Nummer für jede einzelne CD vorliegt, wird die Reihenfolge der CDs durch die Spalte teil festgelegt. Das gesamte Paket kann man über die gleiche Packnummer abrufen. datnr
vnr titel
art
unterart verlagnr
Packnr
Teil
89
12
Simply The Best
cd
5-inch
TVD 93359 (TVD 53359)
CDP 7979612
2/2
90
13
Simply The Best
cd
5-inch
TVD 93349 (RMD 53349)
CDP 7979612
1/2
91
14
The best
cd
3-inch
CDP 506 (2034983)
1/ 1
2.5 Über Normalisierung ein Datenmodell optimieren Auf dem Weg von der real existierenden Plattensammlung bis hin zu einem funktionsfähigen relationalen Datenmodell wurden am Rande bereits einige Normalisierungsvorgänge unternommen. Sie standen allerdings bewusst unter dem Blickwinkel der Übertragung von einem semantischen Modell zu den notwendigen Tabellen, die dann die DB konstituieren. In dieser Lektion wird dieser Prozess noch einmal durchlaufen, wobei als neue Perspektive dieses Mal der Algorithmus der
32
SQL
GRUNDLAGEN
RELATIONALER
DATENBANKEN
Normalisierung dient. Die in diesem Algorithmus ablaufenden Regeln und die ihn begründenden Gesetze haben folgende Ziele: ¾ Der Aufwand für die Weiterentwicklung der Anwendungsprogramme soll gesenkt werden. ¾ Die einzelnen Datenstrukturen sind logisch so weit wie möglich entflochten, sodass die Daten möglichst flexibel verwaltet werden können und Änderungen sowohl bei einzelnen Objekten als auch in der Anwendungssoftware leicht durchführbar bleiben. ¾ Eine fast redundanzfreie Speicherung von Daten verkleinert den Speicherplatz und nutzt Rechenzeit besser aus. Folgendes Anti-Beispiel erfüllt kein einziges der der oben genannten Merkmale, sodass es mit den folgenden Abschnitten als durchgehendes Beispiel schrittweise in ein geeignetes Datenmodell überführt werden kann. In einer Firma, die sich mit Seminaren und der Lösung von E-CommerceProblemen beschäftigt, sind verschiedene Mitarbeiter abteilungsübergreifend in Projekten eingesetzt. Jeder Mitarbeiter hat eine Personalnummer (PersNr), einen Namen (Name) und ein Einstiegsjahr (Jahr). Die Mitarbeiter arbeiten in Abteilungen, die eine Abteilungsnummer (AbtNr), einen Abteilungsnamen (AbtName), eine Mitarbeiterzahl (MaZahl) und einen Abteilungsleiter (AbtLeit) besitzen. Die Projekte haben verschiedene Nummern (ProjNr) und einen Projektleiter (LeitNr). Die Mitarbeiter beschäftigen sich unterschiedlich intensiv (Zeit) mit den aktuellen Projekten. PersNr
ProjNr
LeitNr
Zeit
Name
Jahr
AbtNr
AbtName
MaZahl
AbtLeit
1020
C13
1020
15%
Ralf Tauzieh
1995
2
Medien
4
1020
1020
B12
1042
30%
Ralf Tauzieh
1992
2
Medien
4
1020
1035
C13
1020
50%
Jana Grün
2001
3
FiBu
2
1035
1042
B12
1042
25%
Tom Schnell
1993
1
Seminare
3
1042
1042
D10
1049
30%
Tom Schnell
1990
1
Seminare
3
1042
1048
D10
1049
15%
Fritz Bachler
1999
4
Programmierung 5
1048
1049
C13
1020
40%
Tanja Sieben
1996
4
Programmierung 5
1048
SQL
33
GRUNDLAGEN
RELATIONALER
DATENBANKEN
2.5.1 Das Konzept der funktionellen Abhängigkeit Zwischen Daten können unterschiedliche Abhängigkeiten bestehen. Mit ihrer Hilfe können Daten in eine vernünftige relationale Form gebracht werden, wenn man die Daten entsprechend analysiert. Im nebenstehenden Beispiel werden Schiffe und Kabinen erfasst. Typischerweise werden Kabinen auf Schiffen oder Zimmer in Hotels nicht mit einem komplizierten Code gezählt, sondern einfach in Ganzzahlen von 1 bis zu einer bestimmten anderen Zahl. Innerhalb eines Schiffs reicht es vollkommen aus, seine eigene Kabinennummer zu kennen, um seine Kabine wiederzufinden bzw. zumindest einen Steward zu bitten, den Weg zu der so eindeutig identifizierten Kabine zu beschreiben. Diese Kabinennummer ist aber nicht ausreichend, um andererseits im Reisebüro für die nächste große Weltreise die gleiche Kabine zu buchen. Nicht einmal innerhalb der gleichen Flotte wird eine Nummer wie 112 aushelfen können. Vielmehr ist dieser Primärschlüssel abhängig von der Schiffnummer, die als weiteres Kriterium die einzelne Kabine einem bestimmten Schiff zuordnet. Damit gehört das Objekt KABINE zu den schwachen Einheiten, da ihre eindeutige Bestimmung von einem weiterem Objekt abhängt. Für die funktionale Abhängigkeit gilt, dass zwei Attribute eines Objekts dann funktional voneinander abhängen, wenn zu jedem Wert von A nur ein Wert von B gehört. In obiger Tabelle besteht also bspw. eine solche Abhängigkeit zwischen PersNr und Name, da über die Personalnummer (1020) sofort auf den zugehörigen Namen (Ralf Tauzieh) geschlossen werden kann. In diesem Fall sagt man, dass der Name funktional abhängig ist von der Personalnummer. Wenn Sie mit so häufigen Namen wie Ralf Müller oder Ralf Schmidt den gleichen Test machen, könnte es sein, dass auch noch ein Anderer im Betrieb den gleichen Namen hat und deswegen die Personalnummer nicht vom Namen abhängt.
2.5.2 Von der Universal Relation zum RDM 1. Analysieren Sie die vorliegende Datenstruktur. 2. Richten Sie die Tabelle MITARBEITER ein. Ganz deutlich fällt auf, dass ein besonders einfach zu modellierendes Objekt der einzelne Mitarbeiter ist. Er wird in der Übersichtstabelle hauptsächlich durch seine PersNr, seinen Namen und sein Eintrittsjahr gekennzeichnet. Die Aufnahme der anderen Attribute verbietet sich deswegen schon, weil sie u.a. die Datenredundanz
34
PersNr
Name
Jahr
1020
Ralf Tauzieh
1995
1035
Jana Grün
2001
1042
Tom Schnell
1990
1048
Fritz Bachler
1999
1049
Tanja Sieben
1996
SQL
GRUNDLAGEN
RELATIONALER
DATENBANKEN
hervorgerufen haben. Sobald ja ein Mitarbeiter an zwei Projekten teilnimmt, taucht er mit zwei Datensätzen und seinen gesamten anderen Daten in der Übersichtstabelle auf. 3. Bringen Sie die Tabelle MITARBEITER in die 1. Normalenform. Für die 1. Normalenform gilt, dass sie einen Schlüssel besitzt und alle Attribute atomisiert sind. Ein Schlüssel ist durch die Personalnummer vorhanden. Die Atomisierung muss noch umgesetzt werden, da im Attribut Name sowohl der Vorname als auch der Nachname eingetragen sind. Atomisiert sind Attribute also dann, wenn sie nicht weiter aufgeteilt werden können.
PersNr
Vorname
Name
Jahr
1020
Ralf
Tauzieh
1995
1035
Jana
Grün
2001
1042
Tom
Schnell
1990
1048
Fritz
Bachler
1999
1049
Tanja
Sieben
1996
Klassische Beispiele sind das vorliegende Namensproblem und das Adressproblem mit einer Straße und einer Hausnummer in einer Zelle, die dann in jeweils eigene Spalten gebracht werden. Diskussionswürdig und eigentlich nur in Spezialfällen umgesetzt sind Atomisierungen bei z.B. Zeitdaten wie ein Datum in der Form Tag/Monat/Jahr. Sofern nicht Abfragen zu diesen einzelnen Informationen ausgeführt werden, begnügt man sich damit, diese Daten in einer Spalte zu speichern. Anders dagegen verläuft diese Überlegung insbesondere für Namen. Da Vornamen wesentlich häufiger auftreten als Nachnamen, werden sie vermutlich in einer Mitarbeitertabelle nur sehr selten (falls überhaupt jemals) abgefragt. Dagegen ist allein die alphabetische Sortierung für ein Firmenadressbuch über diese Atomisierung sehr einfach zu bewerkstelligen. 4. Analysieren Sie erneut die vorliegende Datenstruktur. Die Tabelle MITARBEITER ist bereits in der 1. Normalenform und kann durch weitere Attribute leicht erweitert werden. Diese Erweiterungen wie z.B. Informationen über die Adresse, die zugehörige Abteilung, Gehaltsstufe oder Ausbildung beeinflussen nicht wie in der Übersichtstabelle auch die anderen Datensätze. Sie beschränken sich dagegen auf jeweils einen Datensatz, der über die Personalnummer identifiziert wird. In der nun vorliegenden, geschrumpften Übersichtstabelle liegen noch weitere DatenredundanPersNr zen vor wie die oben schon erwähnte Abteilungsnu mmerVorname . Sie kann Name einfach auJahr s der Tabelle entfernt und in die Tabelle MITARBEITER eingebettet werden. 1020
Ralf
Tauzieh
1995
Als weitere Besonderheit der jetzt existierenden Übersichtstabelle muss man die funktionale 1035 Jana Grün 2001 Abhängigkeit zwischen den Attributen Projektleiternummer (LeitNr) und Projektnummer (ProjNr) betrachten. In dieser Konstellation hän1042 gt LeitTom Nr ausschSchnell ließlich von1990 ProjNr ab. Ähnliche Überlegungen gelten für die Zusammenstellung der Projekte sowie der Zeitverteilung 1048 Fritz Bachler 1999 pro Mitarbeiter.
SQL
PersNr
ProjNr
LeitNr
Zeit
AbtNr
1049 Tanja AbtName
Sieben 1996 MaZahl AbtLeit
1020
C13
1020
15%
2
Medien
4
1020
1020
B12
1042
30%
2
Medien
4
1020
1035
C13
1020
50%
3
FiBu
2
1035
35
GRUNDLAGEN
RELATIONALER
DATENBANKEN
1042
B12
1042
25%
1
Seminare
3
1042
1042
D10
1049
30%
1
Seminare
3
1042
1048
D10
1049
15%
4
Programmierung 5
1048
1049
C13
1020
40%
4
Programmierung 5
1048
5. Bringen Sie die Übersichtstabelle in die 2. Normalenform. Gemäß Definition ist ein Objekt in der 2. Normalenform, wenn es in der 1. Normalenform ist und die funktionalen Abhängigkeiten zwischen Schlüssel und den anderen Attributen elementar sind. Nebenstehende Abbildung zeigt also den Zustand einer Modellierung, die gerade wegen dieser nicht elementaren funktionalen Abhängigkeit nicht in der 2. Normalenform ist. Es besteht neben dem Schlüssel ein weiteres Attribut, das ein anderes bestimmt. Eine Aufspaltung wird also folgende Tabellen ergeben: Tabelle
Spalten
PROJEKTE
PersNr, Name, Jahr, AbtNr, AbtName, MaZahl, AbtLeit
ZEITEN
PersNr, ProjNr, Zeit
PROJEKTLEITER
ProjNr, LeitNr
Konkret erhält man neben der neuen Struktur der Tabelle MITARBEITER folgende Einzeltabellen: PersNr
Zeit
Vorname Name
1020
15%
Ralf
1020
30%
1035
Jahr
AbtNr
AbtName
MaZahl
AbtLeit
Tauzieh 1995
2
Medien
4
1020
Ralf
Tauzieh 1992
2
Medien
4
1020
50%
Jana
Grün
2001
3
FiBu
2
1035
1042
25%
Tom
Schnell
1993
1
Seminare
3
1042
1042
30%
Tom
Schnell
1990
1
Seminare
3
1042
1048
15%
Fritz
Bachler
1999
4
Programmierung 5
1048
1049
40%
Tanja
Sieben
1996
4
Programmierung 5
1048
Tabellen und PROJEKTLEITER und ZEITEN:
36
SQL
GRUNDLAGEN
RELATIONALER
DATENBANKEN
ProjNr
LeitNr
PersNr
ProjNr
Zeit
C13
1020
1020
C13
15%
B12
1042
1020
B12
30%
B12
1042
1035
C13
50%
D10
1049
1042
B12
25%
1042
D10
30%
1048
D10
15%
1049
C13
40%
Ganz deutlich sehen Sie schon an der Struktur der letzten Tabellen, wie sich langsam ein relationales Datenmodell aus der ehemaligen Übersichtstabelle entwickelt. Die Tabellen PROJEKTLEITER und ZEITEN sind nämlich bereits durch die Spalte ProjNr verbunden. 6. Analysieren Sie die neue Datenstruktur. Ein weiteres Problem ergibt sich danach sofort aus der Struktur der erneut verkleinerten Übersichtstabelle. Zwischen den Nichtschlüssel-Attributen (was in der 2. Normalenform gegenteilig war) bestehen nun weiterhin funktionale Abhängigkeiten, die behoben werden können.
Der Abteilungsleiter kann direkt aus der Abteilungsnummer ermittelt werden. Obwohl dieses Attribut kein Schlüssel-Attribut ist, kann es dennoch ein weiteres Attribut identifizieren. Dies steht im Gegensatz zur oberen Untersuchung, wobei das Schlüssel-Attribut ProjektNr das NichtSchlüssel-Attribut LeitNr identifizierte. Damit ist die funktionale Abhängigkeit zwischen dem Schlüssel- Attribut und den anderen Attributen nicht direkt. 7. Erzeugen Sie die 3. Normalenform. Damit ein Datenmodell in der 3. Normalenform ist, muss es zunächst in der 2. Normalenform sein und die Eigenschaft besitzen, dass die funktionalen Abhängigkeiten zwischen dem Schlüssel und den anderen Attributen direkt ist. Daher muss einerseits die Tabelle MITARBEITER erneut geändert und um die Abteilungsnummer ergänzt werden und andererseits eine letzte neue Tabelle namens ABTEILUNGEN eingerichtet werden, die alle Informationen zu den einzelnen Abteilungen der Firma aufnimmt, die nicht den anderen Spalten zugeordnet werden dürfen. Nach diesem Schritt ist das Datenmodell in der 3. Normalenform und könnte in einem DBS umgesetzt werden. In einer rückblickenden Analyse kann man feststellen, dass im Hintergrund für die Erzeugung der Tabellen auch der in der vorherigen Lektion gezeigte Weg über die Tätigkeits- oder die Objektanalyse gelungen wäre. Die Objektanalyse hätte für die ersten drei Tabellen MITARBEITER, ABTEILUNGEN und PROJEKTE als in der Realität beobachtbare Objekte Pate stehen können. Sogar ein stofflich nicht direkt vorhandenes Objekt wie verschiedene Projekte in dieser Firma könnten indirekt repräsentiert werden über entsprechende Ordner und Projektbeschreibungen. Im Gegensatz dazu steht die Tabelle ZEITEN für eine Tätigkeit, die die Tätigkeitsanalyse ans Tageslicht gezerrt hätte. Sie beschreibt die Tätigkeit, dass Mitarbeiter in Abteilungen an Projekten arbeiten und stellt als Relationstabelle die direkte Verbindung zu MITARBEITER über PersNr und zu PROJEKTE über ProjNr her. Die Abteilungen werden dann indirekt über die Tabelle MITARBEITER referenziert. Das macht auch insoweit Sinn, als dass ja gerade die Projekte von den Abteilungen unabhängig sind und von Mitarbeitern verschiedener Abteilungen bearbeitet werden. Folgende Tabellen sind also das endgültige Ergebnis:
SQL
37
GRUNDLAGEN
DATENBANKEN
RELATIONALER
Tabelle
Spalten
MITARBEITER
PersNr, Vorname, Name, Jahr, AbtNr
ABTEILUNGEN
AbtNr, AbtName, AbtLeiter, MaZahl
PROJEKTE
ProjNr, LeitNr
ZEITEN
PersNr, ProjNr, Zeit
Folgende Daten können endgültig in den Tabellen untergebracht werden: Tabelle PROJEKTE und Tabelle ZEITEN: ProjNr
LeitNr
PersNr
ProjNr
Zeit
C13
1020
1020
C13
15%
B12
1042
1020
B12
30%
B12
1042
1035
C13
50%
D10
1049
1042
B12
25%
1042
D10
30%
1048
D10
15%
1049
C13
40%
Tabelle MITARBEITER Tabelle ABTEILUNGEN:
Die drei hier vorgestellten Normalenformen stellen nicht die einzigen dar. Weitere Aufspaltungen der Datenstruktur sind z.B. mit der Boyce-Codd-Normalenform möglich. Für die allermeisten Fälle genügt jedoch der hier gezeigte Umwandlungsprozess. Je weiter die Datenstruktur in einzelne Tabellen zerlegt wird, desto komplizierter können sich dann Abfragen gestalten, die permanent komplex sind und mehrere Tabellen verknüpfen müssen.
2.5.3 DB-Anomalien und Redundanzen Mögliche Schwierigkeiten mit ungünstig bzw. sogar falsch strukturierten Datenmodellen schimmerten bereits im Laufe der Überlegungen zur Normalisierung der oben verwendeten DB hindurch. PersNr
Vorname
Name
Jahr
AbtNr
AbtNr
AbtName
MaZahl
AbtLeit
1020
Ralf
Tauzieh
1995
2
2
Medien
4
1020
1035
Jana
Grün
2001
3
3
FiBu
2
1035
1042
Tom
Schnell
1990
1
1
Seminare
3
1042
1048
Fritz
Bachler
1999
4
4
Programmierung 5
1048
1049
Tanja
Sieben
1996
4
Abschließend sollen die wichtigsten Probleme noch einmal am oberen Beispiel erläutert und zusammengefasst werden. Es bietet sich an, diese Ausführungen nach der erledigten Normalisie-
38
SQL
GRUNDLAGEN
RELATIONALER
DATENBANKEN
rungsarbeit zu geben, weil Sie die hergeleitete Datenstruktur jetzt kennen und daher sicherlich die einzelnen Punkte besser zu deuten wissen: ¾ Redundanz: Mit Redundanz ist das Auftreten von doppelten Informationen in Datensätzen gemeint. Dies lässt sich nicht immer ganz vermeiden: Wenn 100 Leute ein Buch kaufen, ist klar, dass irgendwo die Zahl 100 auftaucht wie z.B. in Form von 100 Bestellungen mit unterschiedlichen Bestellnummern und 100 gleichen ISBN-Nummern. In diesem Datenmodell existiert aber bereits eine offenbar irgendwie normalisiert Form, da die Tätigkeit Bestellen mit Hilfe einer Tabelle BESTELLUNGEN erfasst wurde. Die Projektverwaltung aus dem vorherigen Beispiel jedoch startete mit einer großen Übersichtstabelle, die vor Redundanzen förmlich überquoll. Die unten folgenden Anomalien sollen die Gefahren mit Redundanzen zeigen. Ziel sollte immer sein, Redundanzen weitestgehend zu vermeiden. Je größer eine Datenbank wird, desto mehr Speicherplatz fressen unnötige Informationsdoppelgänger. Wirkt sich dies bei 100 Datensätzen noch nicht dramatisch aus, so können Abfragen bei über 10.000 Datensätzen jedoch erheblich beschleunigt werden, wenn gerade keine unnötigen Wiederholungen in den Tabellen zu finden sind. Eine der vielen verzichtbaren Redundanzen im obigen Beispiel bestand darin, dass für jedes neue Projekt, das ein Mitarbeiter beginnt, sämtliche verfügbaren Mitarbeiter-, Abteilungsund Leitungsdaten wiederholt werden mussten. Dieses Problem ist durch den Normalisierungsvorgang vollkommen behoben worden. ¾ Abfrage-Anomalie: Wenn das Datenmodell, mit dem der Normalisierungsprozess startete, in aller Konsequenz so eingerichtet worden wäre, hätte es sein können, dass nur Mitarbeiter, die an einem Projekt teilnehmen, auch in der Übersichtstabelle erfasst werden. Sollte aber der vermutlich nicht lange auf sich warten lassende Fall eintreten, dass ein Mitarbeiter nicht an einem Projekt teilnimmt, könnte er gar nicht gefunden werden. ¾ Einfüge-Anomalie: Die Abfrage-Anomalie aus der gegenüber liegenden Perspektive betrachtet, zeigt zusätzlich, dass es eigentlich gar nicht möglich ist, einen neuen Mitarbeiter zu erfassen, der nicht an einem Projekt teilnimmt. Würde man ihn dennoch erfassen, dann müssten sämtliche Felder, die eigentlich mit Projekten zusammenhängen, leer bleiben. ¾ Lösch-Anomalie: Den aktuellen Gedanken weitergesponnen, muss man sich darüber hinaus vorstellen, was mit dem Datensatz eines Mitarbeiters nach dem Ausscheiden aus einem Projekt geschieht. Zwar konnte er hervorragend eingetragen werden, weil er ja an einem Projekt teilnahm, doch nun sinkt seine Zeit für die Projektarbeit auf 0 %. Entweder verschwindet sein Datensatz komplett aus der Übersichtstabelle und er ist gar nicht mehr als Mitarbeiter vorhanden, oder man führt notgedrungen einen Erinnerungswert in Form von 0 % für das ehemalige Projekt ein. Sollte dieses dann wiederum irgendwann einmal abgeschlossen sein, stünde es dennoch mit 0 % für diesen Mitarbeiter in der Tabelle. ¾ Aktualisierungs-Anomalie: Auf den allgemeinen Fall übertragen, meint der letzte Gedanke, dass jegliche Aktualisierung in Zusammenhang mit Projekten für die Mitarbeiter bedeuten können, dass sie aus der Tabelle ausgetragen werden. Andersherum kann es aber ebenso passieren, dass Änderungen an Mitarbeitern wie Ausscheiden aus der Firma im ungünstigsten Fall heißen können, dass ein Projekt nicht mehr in der Tabelle erscheint. Gerade bei Projekten, die nur mit zwei Mitarbeitern durchgeführt werden, könnte dies sofort passieren, wenn beide die Firma verlassen. In diesem Fall wäre eine erneute Eintragung des Projekts z.B. nach zwei Wochen möglich, aber vielleicht waren die Daten so miteinander verquickt, dass gleichzeitig die gesamte Abteilung mit Nummer, Name und Chef durch den Abgang des Mitarbeiters verschwunden sind...
SQL
39
GRUNDLAGEN
RELATIONALER
DATENBANKEN
2.6 Fachbegriffe für Tabellenbestandteile Die einzelnen Bestandteile lassen sich mit verschiedenen Begriffen beschreiben, die hier (noch einmal) im Zusammenhang für die Erfassung von Produkten eines Blumenladens gezeigt werden sollen: ¾ Die gesamte Tabelle heißt Relation. ¾ Ein Datensatz der Relation / Tabelle nennt sich Tupel. ¾ Die Breite der Tabelle / die Anzahl der Spalten oder Felder heißt Grad der Relation. ¾ Ein einzelnes Feld oder eine einzelne Spalte heißt Attribut der Tabelle. ¾ Mit Domänen werden die Wertebereiche bezeichnet, die für ein Attribut bzw. ein Feld der Relation vorgegeben wurden. ¾ Kardinalität bedeutet die Höhe / Länge der Relation / Tabelle.
2.6.1
Zusammenfassung
9 Ein Großteil moderner Datenbanken basiert auf dem Relationalen Daten-Modell. Hier werden die zu modellierenden Objekte in einzelnen Tabellen erfasst. Für jeden einzelnen Datensatz existiert ein Primärschlüssel. Beziehungen zwischen den einzelnen Tabellen werden durch die Aufnahme von Primärschlüsseln anderer Tabellen in einer Tabelle erzeugt. Diese aufgenommenen Schlüssel heißen Fremd- oder Sekundärschlüssel. 9 Ein einfaches Hilfsmittel zur Generierung eines RDM besteht in einem vorgeschalteten Entity-Relationship-Modell. In diesem Datenmodell werden die zu erfassenden Objekte und Beziehungen durch grafische Symbole (Rechteck für Objekt, Raute für Beziehung und Oval für Attribut) veranschaulicht. Aus dem entstehenden ER-Diagramm kann man dann leicht das RDM erzeugen. 9 Gerade bei großen Datenmengen hilft der relationale Ansatz, Redundanzen (Datenwiederholungen) zu vermeiden. Dadurch werden gleichzeitig Ziele wie Geschwindigkeit, Vermeidung von DB-Anomalien und Änderungserleichterungen erreicht. 9 Ein in einer Universal-Relation vorliegendes Datenmodell kann über Normalisierungen in ein relationales Schema überführt werden. Dabei werden für die 1NF alle Attribute atomisiert, für die 2NF die funktionalen Abhängigkeiten zwischen Primärschlüssel und anderen Attributen elementar gemacht und in der 3NF die funktionalen Abhängigkeiten der Attribute untereinander direkt gemacht.
40
SQL
GRUNDLAGEN
RELATIONALER
DATENBANKEN
9 Zwischen Datenstrukturen können drei unterschiedliche Beziehungen bestehen: eineindeutige (1:1), funktionale (1:n) und komplexe (n:m). Bei der Überführung in ein RDM müssen komplexe Beziehungen meistens in eigene Beziehungstabellen überführt werden, während für die anderen Beziehungen die Verwendung von Schlüsseln genügt. 9 Man unterscheidet drei Sichten, mit denen man ein Datenbanksystem betrachten kann: die interne (Datenorganisation, Speichermedien), die externe (Benutzersicht am Ausgabemedium) und die konzeptionelle (Datenmodell) Sicht.
2.6.2
Übungen
1. Zeichnen Sie ein Diagramm für die Projektverwaltung, wie sie nach dem Normalisierungsprozess vorliegt. 2. Entwickeln Sie für folgendes semantische Modell ein Datenbank-Konzept und erstellen Sie ein ER-Diagramm bzw. ein Schema: ¾ Die Firma SemiTex möchte ihre Seminare mit einer DB verwalten. Sie vermittelt Seminare an Einzelteilnehmer im Rahmen von offenen Kursen und an Firmen als Firmenseminare. Die Kursthemen werden für beide Bereiche zusammen erfasst. Für einen Kurs sollen Informationen wie Titel, Bereich (Programmierung, Webdesign etc.), Dauer, Preis, Vorkenntnisse und detaillierte Themen erfasst werden. ¾ Es muss möglich sein, Teilnehmer getrennt von den Unternehmen zu erfassen, damit sowohl die Kunden der offenen Kurse als auch die der Firmenschulungen erfasst werden können. Gleichzeitig muss aber jederzeit die Möglichkeit bestehen, Teilnehmer einer Firma zuzuordnen. ¾ Als Vereinfachung wird vorausgesetzt, dass es pro Unternehmen nur einen Ansprechpartner für die Firmenseminare gibt. Auf eine eigene Tabelle für diese Gruppe kann also verzichtet werden. 3. Beschreiben Sie mit Hilfe der Objekt- und der Tätigkeitsanalyse, wie Sie die Tabellen für die Firma SemiTex gefunden haben. 4. Welche Objekte könnte man in Zukunft integrieren? 5. Wie können diese Objekte nachträglich noch in das Schema eingebaut werden? Besteht die Gefahr von DB-Anomalien? Wie kann sie gelöst werden? 6. Wie können offene Kurse mit Terminen angeboten werden? 7. Welche Datentypen in diesen Tabellen können als zusammengesetzt betrachtet werden? 8. Die Vollkornmühle im Sauerland möchte ihre Spezialprodukte auch im Internet mit Hilfe eines neuen Webshops vertreiben. Dazu benötigen sie neben der Programmierung eine entsprechende Datenbank mit folgenden Eigenschaften:
SQL
41
GRUNDLAGEN
RELATIONALER
DATENBANKEN
¾ Alle Besucher des Webshops sollen für statistische Zwecke und die Einrichtung eines späteren Logins erfasst werden. Erst in dem Augenblick einer Bestellung, sollen aus den Besuchern Kunden werden, die sich mit allen nötigen Kontaktinformationen in die DB eintragen müssen. ¾ Die Besucher sollen Produkte in einen Warenkorb legen und wieder löschen können. (Der Warenkorb muss mit der Besuchernummer verbunden werden, damit der Webserver den Besucher erkennt.) ¾ Die Produkte werden in Produktfamilien verwaltet, wobei auf eine Auslagerung der Familien in weitere Tabellen verzichtet werden kann. Des Weiteren werden die Eigenschaften Preis, Verpackungsmenge, Name, Bestellnummer und eine Beschreibung gespeichert. ¾ Es soll deutlich zwischen Aufträgen und Bestellungen unterschieden werden. Während der Auftrag die Gesamtheit der bestellten Produkte beschreibt (ein Kunde erteilt einen Auftrag), soll mit einer Bestellung der einzelne bestellte Artikel verbucht werden.
42
SQL
GRUNDLAGEN
RELATIONALER
DATENBANKEN
3 Datenbank und Tabellen anlegen und ändern
SQL
43
GRUNDLAGEN
44
RELATIONALER
DATENBANKEN
SQL
DATENBANK
UND
TABELLEN
3 Datenbank und Tabellen anlegen und ändern Nachdem nun klar ist, welche Tabellen und welche Felder anzulegen sind, um ein funktionsfähiges Datenmodell in einer DB einzurichten, dreht sich in diesem Modul jetzt alles um die Verarbeitung der Planungsarbeit in SQL. Vorgeschaltet wird ein kurzer Abriss über die Hintergründe und die Entwicklung von SQL als Werkzeug für die DB-Entwicklung und – verwaltung.
ANLEGEN UND ÄNDERN
Lernen Sie eine Datenbank in SQL anzulegen und zu löschen Tabellen einzurichten, zu ändern und wieder zu entfernen Datentypen in Tabellen zu benennen und zu modifizieren Primär- und Sekundärschlüssel für die Relationen einzubinden Indizes erstellen zu lassen
Die in diesem Buch verwendeten SQL-Skripte entsprechen dem SQL-Standard, wenn sie nicht anders eingeführt werden. Für diejenigen Leser ohne spezielle Datenbank oder Programmierer, die SQL ausschließlich in anderen Programmiersprachen für z.B. Abfragen nutzen möchten und vielleicht mit der DB an sich keinen direkten Umgang haben, haben wir kein spezielles System ausgewählt, weil die Unterschiede doch immer recht detailreich sind. Getestet wurden diese Skripte auf MySQL und MS SQL. Server. MySQL wird häufig im Internet, gerade auch bei kleineren Lösungen, eingesetzt. Als alternative größere Lösung kann man dann wiederum auf den MS SQL Server zurückgreifen. Dieses DBS hat den Vorteil, dass es relativ leicht mit den gängigen Microsoft-Anwendungen wie z.B. MS Access harmoniert und wesentlich mehr SQL unterstützt als MySQL. Wenn Sie dagegen keine von beiden Möglichkeiten einsetzen – und die Wahrscheinlichkeit ist angesichts der Vielfalt sehr groß -, dann beachten Sie bitte beim Testen der Skripte die jeweiligen Eigenarten der Server. In diesem Kapitel würde in dieser Hinsicht insbesondere die Bezeichnung von Datentypen variieren. Prinzipiell stellen wir natürlich den SQL-Standard vor, doch sollen die Skripte zumindest auf bekannten Systemen einfach lauffähig sein.
3.1 Entwicklung und Hintergrund von SQL SQL bedeutet „Structured Query Language“ (Strukturierte Abfragesprache) und wird von so unterschiedlichen DBS wie Oracle, MySQL oder MS SQL unterstützt. Zusätzlich finden Sie Implementierungen in MS Access oder auch in MS Excel über die MS Query Schnittstelle. Drei verschiedene Sprachbereiche sind zu unterscheiden. Die Reihenfolge der nächsten Module orientiert sich grundsätzlich an diesen Bereichen, wobei wir nicht eindeutig auf die einzelnen Teilbereiche hinweisen. Sie können u.a. auch verschiedenen Sichten einer DB zugeordnet werden, was ja bereits im vorherigen Modul ein Thema darstellte. Für uns ist bei der Vorstellung der einzelnen Befehle wichtiger, einen Handlungsbezug herzustellen und damit eher den Prozess nachzubilden, den man bei der Einrichtung einer Datenbank durchläuft.
SQL
45
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
¾ Datendefinitionssprache (DDL: Data Definition Language): Bei der Entwicklung eines neuen DB-Projekts stellen diese Sprachelemente die ersten Befehle dar, die von einem DB-Entwickler ausgeführt werden. Sie erzeugen die DB mit ihren Tabellen und den zugehörigen Datentypen. Ergänzt werden diese Befehle um Kontrollmechanismen, was z.B. den zugelassenen Wertebereich eines Feldes anbelangt. ¾ Datenmanipulationssprache (DML: Data Manipulation Language): Mit Hilfe von einfachen Befehlen können Datensätze in eine Tabelle eingetragen, gelöscht oder inhaltlich geändert werden. Zusätzlich stellt dieses Sprachsegment von SQL sämtliche Abfragewerkzeuge zur Verfügung, die insbesondere auf die Besonderheiten von relationalen Datenbanken eingehen. Hierzu zählt bspw. die Verknüpfung von Tabellen, um die über die Fremdschlüssel eingerichteten Beziehungen zu nutzen. ¾ Datenkontrollsprache (DCL: Data Control Language): In diesem Bereich stellt SQL Befehle zur Verfügung, mit denen man Transaktionen festlegen kann. Dabei stellen Transaktionen eine Folge von DB-Operationen dar, die sicherstellen, dass bei Zugriffen von außen das Datenmodell von einem aktuellen konsistenten Zustand in einen neuen konsistenten Zustand überführt wird. Durch Einsatz der Möglichkeiten der DCL können Sie den Einfluss von unerwünschten, zerstörerischen Einwirkungen auf die Daten Ihrer Datenbank minimieren. Dabei wird vor allen Dingen darauf Rücksicht genommen, dass z.B. Abfragen und Änderungen gleichzeitig vorgenommen werden könnten. Änderungen in einem Warenbestand, die von einem Mitarbeiter A ausgeführt werden, dürfen nicht dazu führen, dass ein gleichzeitig auf den Warenbestand zugreifender Mitarbeiter B plötzlich falsche Werte erhält, weil sich gewisse Waren nicht mehr in der Tabelle WAREN, sondern in einer virtuellen Tabelle WARENAENDERUNGEN befinden. Die Data Control Language stellt also Befehle zur Verfügung, mit denen man die in der Datenbank enthaltenen Daten schützen kann. Leider unterstützen nicht alle Datenbanksysteme alle Funktionen der DCL, so dass Sie unter Umständen Schutzmaßnahmen, die das DBMS nicht zur Verfügung stellt, in Ihre Datenbankanwendung implementieren müssen. Die am häufigsten benutzten DCL-Befehle sind GRANT und DENY. ¾ Transaktionen werden doch teilweise noch nicht mal im DBMS implementiert (siehe z.B. den Microsoft Transcation Server, der nicht in den SQL-Server eingebaut ist).
Die hier verwendeten Datenbankskripte sind – soweit es technisch möglich ist - auf MySQL getestet worden. Die Grundstruktur der Standard-Syntax für andere DBS bleibt weitestgehend gleich. Teilweise werden hier und da zusätzliche eckige Klammern eingesetzt oder Befehle mit speziellen Schlüsselwörtern abgeschlossen. Dies sind Besonderheiten des jeweiligen Produkts und müssen in der entsprechenden Dokumentation nachgeschlagen werden. Für diese Kapitel bspw. werden Sie in allen Systemen Unterschiede finden, was die Bezeichnung der Datentypen anbetrifft. Teilweise werden sie nur anders verwendet, teilweise heißen sie anders und teilweise gibt es andere.
46
SQL
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
3.2 Mit PowerDesigner ein Datenmodell grafisch entwickeln Zu den unterschiedlichen Hilfsmitteln für die grafische Entwicklung eines Datenmodells, das auch gleichzeitig entsprechenden SQL-Quelltext produziert, zählt das von Sybase (www.sybase.com) entwickelte Programm PowerDesigner. Eine entsprechende Testversion finden Sie auf der Webseite oder ab und an auf CD-ROMs von Computerzeitschriften. Es wurde einige Jahre unter einem anderen Namen verkauft und bietet jetzt verschiedene weitere Fähigkeiten, die für die Datenmodell-Entwicklung notwendig sind. Gleichzeitig kann es dafür sorgen, dass Sie hier zu Anfang das von Ihnen präferierte DBS auswählen können, für das dann der Quelltext geschrieben wird.
Als Alternativen können Sie für die Entwicklung eines Datenmodells im MS SQL Server auch die so genannte Diagrammfunktion benutzen. Mit Oracle setzen Sie dagegen den Oracle Designer ein.
Als Beispiel gestalten Sie jetzt das Datenmodell für die Song-Datenbank. 1. Laden und installieren Sie das Programm wie andere Programme auch. Starten Sie es dann über Start / Programme / PowerDesigner / AppModeler for PowerBuilder.
2. Sobald sich das Programm öffnet, werden Sie von einem Dialogfenster gebeten, eine Zieldatenbank auszuwählen. Fast alle DBS sind in der Auswahlliste Database Name vertreten. Die nachfolgenden Skripte wurden mit der in der Abbildung angegebenen Auswahl Microsoft SQL Server erstellt. Bestätigen Sie dann Ihre Auswahl mit der Schaltfläche OK.
SQL
47
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
3. In der linken oberen Ecke des Bearbeitungsfensters finden Sie eine rechteckige Werkzeugleiste. Wir werden nicht alle Werkzeuge benutzen, da es hier nur um die Grundfunktionen des Programms gehen soll. Um eine Tabelle zu erstellen, markieren Sie die Schaltfläche Table, bewegen den Mauszeiger, der sich in eine kleine Tabelle verwandelt, auf den Arbeitsbereich und klicken, sobald Sie eine Tabelle einrichten wollen. Sie erhält automatisch einen Namen wie tab_39, in dem eine laufende Nummer vergeben wird. Ihre Nummer wird entsprechend anders laufen, wenn Sie das Programm jetzt zum ersten Mal bedienen. 4. Doppelklicken Sie die Tabelle, um ihre Eigenschaften ändern zu können. Alternativ können Sie auch zuvor die Schaltfläche Properties auswählen, die sich direkt unterhalb von Table befindet. Ein mit dieser Schaltfläche markiertes Objekt im Arbeitsbereich zeigt dann ebenfalls seine Eigenschaften an. In der Registerkarte Definition legen Sie dann unter Name einen angezeigten Namen für die Tabelle und unter Code den im SQL-Quelltext verwendeten Namen fest. Solange Sie nur wenige Tabellen verwenden, können und sollten sich vielleicht sogar beide Namen gleichen. Eigenschaft Beschreibung
Länge
Model
Name des Datenmodells. In der Testversion kann nicht das Datenmodell, sondern nur das SQL-Skript gespeichert werden.
Name
Tabellenname, der die Lesbarkeit des Modells ermöglicht.
80, muss im Modell einzigartig sein
Code
Tabellenname, der im SQL-Quelltext benutzt wird.
80, muss im Modell einzigartig sein
Label
Beschriftung für die Tabelle in der grafischen Darstellung.
254
Number
Geschätzte oder tatsächliche Anzahl der Reihen der Tabelle. Die Angabe ist fakultativ und wird zur DB-Größenberechnung herangezogen.
Primary key Name der Bedingung / Einschränkung, die für die Spalte gel- 30, muss im Modell einten soll. zigartig sein constraint name Generate table
48
Legt Tabellen in gewähltem DBS an.
SQL
DATENBANK
Tab.1:
UND
TABELLEN
ANLEGEN UND ÄNDERN
Eigenschaften einer Tabelle
5. Nachdem Sie auf die Schaltfläche Columns geklickt haben, öffnet sich ein weiteres Dialogfeld, in dem Sie die einzelnen Spalten nebst Datentypen eintragen können. Auch hier unterscheidet man wieder zwischen Name (angezeigt) und Code (im SQLQuelltext verwendet). Erstellen Sie folgende Spalten, wobei Sie die Datentypen im Auswahlfeld Data Type (Länge) bestimmen: ¾ songnr mit int (20), Ganzzahl für die SongNr, die gleichzeitig auch der Primärschlüssel (Kontrollkästchen P) der Tabelle ist. ¾ songtitel mit varchar (150), Zeichenkette. ¾ autoren mit varchar (150), Zeichenkette. ¾ jahr mit timestamp für das Erstellungsjahr des Titels. Alternativ könnte man auch auf Int (4) zurückgreifen, wenn nur eine vierstellige Jahreszahl benötigt wird. Eigenschaft
Beschreibung
Länge
Name
Angezeigter Name im Datenmodell.
80
Code
Im SQL-Quelltext verwendeter Name.
80
Data Type
Datentyp für das gewählte Feld, der aus der Auswahlliste gewählt wird.
Domain Name
Name der Domäne, des Wertebereichs, der vorgegeben werden kann.
Primary key
Kontrollkästchen legt fest, ob dieses Feld der Primärschlüssel für die Tabelle ist.
Foreign key
Zeigt an, ob das entsprechende Feld ein Sekundärschlüssel in der Tabelle ist.
Tab.2:
Eigenschaften für Spalten
6. Kontrollieren Sie das Ergebnis. Über die beiden OK-Schaltflächen kehren Sie wieder zum Arbeitsbereich zurück. Dort finden Sie eine kleine Tabelle mit den eingegebenen Spalten- und Tabellennamen. Der Name der Tabelle steht in einem eigenen Bereich, während der Primärschlüssel unterstrichen dargestellt wird. 7. Erstellen Sie die anderen Tabellen des Datenmodells gemäß den Überlegungen im vorherigen Projekt.
SQL
49
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
8. Erstellen Sie die Beziehungen, indem Sie mit dem Werkzeug Reference von der Eltern-Tabelle (mit dem benötigten Primärschlüssel) zur Kind-Tabelle eine Linie (Beziehung) ziehen. Dadurch wird der Primärschlüssel der Eltern-Tabelle zu einem Fremd-Schlüssel in der Kind-Tabelle. Theoretisch kann man dabei im Vorfeld darauf verzichten, die Fremd-Schlüssel-Felder bereits anzulegen, da sie automatisch in der Kind-Tabelle erstellt würden. In unserem Fall dagegen identifiziert das Programm automatisch die gleichnamige Spalte als potenziellen Fremd-Schlüssel. 9. Tragen Sie im Eigenschaften-Dialogfenster einen entsprechenden Namen ein. Automatisch werden die beiden betreffenden Feldnamen im mittleren Bereich angezeigt. Eigenschaft
Beschreibung
Länge
Name
Name der Beziehung
80
Code
Name für Quelltext
Label
Beschreibender Name 254 für die Beziehung
den
SQL- 80
Tab.3: Eigenschaften für Beziehungen 10.Erstellen Sie die anderen Beziehungen gemäß den im vorherigen Kapitel erläuterten Überlegungen. So erhalten Sie ein ERDiagramm, das sicherlich ein wenig besser als eine Handzeichnung ist.
50
SQL
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
3.3 DB und Tabellen anlegen
Eine Auswahl der Skripte können Sie von der Seite des Verlags (www.bhv-buch.de) und der Seite unserer Firma (www.semecon.de) herunterladen, damit Sie die Skripte für Ihr eigenes DBS anpassen und sofort testen können. Die entsprechenden Hinweise zu den Dateinamen finden Sie in diesem Buch wiederum in diesen grauen Kästen. – Wenn Sie die Datenbanken und Tabellen selbst anlegen möchten, beachten Sie bitte die Praxishinweise im Projekt 8, in dem wir verschiedene DBMS vorstellen. Eine typische Unbillquelle stellen Anführungszeichen dar. Hochkommata (also Redezeichen, die nur aus einem Häkchen bestehen) funktionieren in Oracle und MySQL hervorragend und sind dort Standard, während man dagegen im MS SQL Server sowohl auf Redezeichen als auch auf Hochkommata verzichten kann. Anführungszeichen werden z.B. von MySQL toleriert, gelten aber als falsch. Die DBS berücksichtigen Groß- und Kleinbuchstaben nur für die Bezeichnung von DB-Objekten. Tabelle personal und Tabelle Personal sind also verschiedene Tabelle. SQL-Befehle dagegen unterliegen keiner speziellen Orthographie. Lediglich um den Quelltext übersichtlich zu gestalten, schreibt man die Befehle und Schlüsselwörter traditionell in Großbuchstaben.
Der Einstiegsbefehl ist so einfach, dass man ihn nicht einmal in einzelne Handlungsschritte zerlegen kann. Um eine Datenbank anzulegen, verwenden Sie: CREATE DATABASE `songs` Um sie wieder zu entfernen, benutzen Sie: DROP DATABASE `songs` Zur Verdeutlichung des Hinweises zur Anführungszeichenproblematik : CREATE DATABASE songs und DROP DATABASE songs wären die Alternativen, die ausschließlich für den MS SQL Server syntaktisch korrekt sind.
3.3.1 Tabellen anlegen Damit Sie dieses Buch auch als Nachschlagewerk verwenden können, nachdem Sie es in einer ersten Lernphase durchgearbeitet haben, werden wir die grundlegende Syntax in einer Zusammenfassung wie der folgenden immer vor jeden neuen Abschnitt einfügen. Dabei verwenden wir folgende Notation zur Kennzeichnung und Unterscheidung der einzelnen Befehle im Druckbild. ¾ Die geschweiften Klammern {} sollen zusammengehörige Abschnitte eines Befehls zusammenfassen. In der Tabellendefinition finden Sie dies bspw. für den Abschnitt, der die einzelnen Spalten kennzeichnet. ¾ Die eckigen Klammern [ ] dagegen charakterisieren Bestandteile einer Befehlsstruktur, die fakultativ ist und für die die grundlegende Funktionsweise nicht notwendig ist. Im unteren Beispiel reicht es also aus, lediglich die Spaltennamen mit ihrem Datentyp anzugeben. Alle weiteren Befehle sind nicht verpflichtend, können aber verwendet werden. ¾ Punkte ... sollen auf eine Wiederholung oder weitere Befehle hinweisen. Nach der Definition sämtlicher Spalten einer Tabelle können entweder weitere Tabellen, Befehle für andere Aktionen oder eben mehrere Spaltendefinitionen folgen.
SQL
51
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
¾ Der senkrechte Strich | trennt mögliche Alternativen. So kann man u.a. eine Tabelleneinschränkung vorgeben, oder es steht einem frei, nicht nur einen Datentyp für eine Spalte, sondern auch einen Wertebereich (Domäne) anzugeben. Für die Definition einer Tabelle mit Spalten und weiteren Attributen steht Ihnen folgende allgemeine Syntax zur Verfügung: CREATE TABLE tabellenname ({spaltenname {domäne | datentyp} [spalteneinschränkung] [DEFAULT standardwert] [COLLATE name] | tabelleneinschränkung }, ... ); Um eine Tabelle wieder zu löschen, verwenden Sie ganz einfach: DROP TABLE tabellenname; Die einzelnen Bestandteile setzen sich aus folgenden Bausteinen zusammen, die Sie nach und nach in Beispielen kennen lernen werden: ¾ Einschränkungen für Spalten und Tabellen (Constraints) sind Bedingungen, die von den Daten erfüllt sein müssen, wenn sie in einer Tabelle eingetragen werden sollen. So könnte man bspw. verhindern, dass in einer Spalte familienstand durch irgendwelche Änderungsvorgänge in einem Datensatz der Familienstand von ledig zu geschieden wechselt, was ja nicht möglich sein kann. Damit wird zusätzlich die so genannte referenzielle Integrität der Datenstruktur eingerichtet. Dies betrifft sowohl die Beziehungen von Tabellen untereinander über die Primärschlüssel-Fremdschlüssel-Beziehung als auch die einzelnen Werte und kann gleichermaßen bei Neueinträgen wie auch bei Datenänderungen über Aktualisierungen und Löschungen wichtig sein. Ein typisches Standardbeispiel ist die Beziehung zwischen den Tabellen AUTOREN und BUECHERN. Sobald ein Autorenname gelöscht würde, der aber über seine AutorNr mit verschiedenen Veröffentlichungen (mindestens einer) in der Tabelle BUECHER verfügt, wird die referenzielle Integrität des Datenmodells verletzt. Dies liegt daran, weil die Verknüpfung zwischen den Büchern des gelöschten Autors und den Informationen über ihn in der Tabelle AUTOREN zerbrochen ist. ¾ Über die CREATE DOMAIN-Anweisung können Sie Wertebereiche (Domänen) für eine Spalte vorgeben, wobei nur die in diesem Wertebereich eingetragenen Werte in die Spalte aufgenommen werden können. Typischer Fall wäre in einem Feld anrede das Wertepaar {Herr, Frau}. Eine Verwendung vom altertümlichen Frl. wäre also unmöglich. ¾ Die DEFAULT-Anweisung kennzeichnet solche Werte, die einzufügen sind, wenn keine Werte in den Datensatz eingetragen wurden. Diese Anweisung überschreibt zusätzlich die DEFAULTEinstellung einer Domäne. Verwendet man einen solchen Standardwert, ist es möglich, eine Spalteneinschränkung zu umgehen, die unbedingt einen Wert fordert. Alternativ könnte man sich hier bemühen, immer einen Wert einzutragen, was ja auch der tiefere Sinn einer solchen Klausel ist.
Die Tabellendefinitionen finden Sie in der Datei songs1.sql.
1. Legen Sie die Tabelle aufnahmen an.
52
SQL
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
Die Kommentarzeilen sind nur in MySQL gültig, werden hier für eine bessere Lesbarkeit im Zusammenhang aber ebenfalls ausgegeben. Über den CREATE TABLE-Befehl legen Sie zunächst die Tabelle an sich an. # # Tabellenstruktur für Tabelle `aufnahmen` # CREATE TABLE aufnahmen ( 2. Geben Sie die Spalten und Datentypen ein. Nun tragen Sie in einer Zeile (der Übersichtlichkeit wegen) den Spaltennamen, die Abkürzung für den jeweiligen Datentyp und eventuelle weitere Angaben ein. In diesem ersten Beispiel beschränkt sich das auf den Hinweis, ob eine Spalte keinen Wert (NULL) enthalten darf, oder nicht (NOT NULL). Für die ersten beiden Spalten aufnr und songnr ist natürlich ein Wert obligatorisch, da ansonsten alle anderen Angaben vollkommen unsinnig wären. Es muss also mindestens ein Wert eingetragen sein. Allerdings kann es sein, dass man keine Informationen über das Aufnahmejahr hat (fehlende Information) oder Tina Turner das Lied alleine und damit ohne Duettpartner gesungen hat. Damit können die beiden Spalten aufndatum und duettpartner leer bleiben bzw. auch eine Null enthalten. Die Angabe der Datentypen wird zusätzlich von einer Längenangabe in runden Klammern begleitet. Die Standarddatentypen finden Sie in der unten stehenden Aufstellung. An dieser Stelle sehen Sie z.B. auch, dass jedes DBS verschiedene zusätzliche Datentypen enthält. In diesem Fall kann man in MySQL insbesondere für Jahreszahlen den Datentyp year auswählen. aufnr int(4) NOT NULL default '0', songnr int(4) NOT NULL default '0', aufntitel varchar(150) NOT NULL default '', aufntyp varchar(10) NOT NULL default '', duettpartner varchar(20) default NULL, aufndatum year(4) default NULL, 3. Benennen Sie den Primärschlüssel der Tabelle. Über den Befehl PRIMARY KEY wird der Spalte aufnr die Eigenschaft des Primärschlüssels zuteil. Die Typ-Angabe ist nur in MySQL von Bedeutung. PRIMARY KEY
(aufnr)
); 4. Erstellen Sie nach diesem Schema die anderen Tabellen. # # Tabellenstruktur für Tabelle `datentraeger`
SQL
53
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
# CREATE TABLE datentraeger ( datnr int(4) NOT NULL default '0', veroeffnr int(4) NOT NULL default '0', dattitel varchar(150) NOT NULL default '', datart varchar(20) NOT NULL default '', datunterart varchar(20) default NULL, verlagnr varchar(30) NOT NULL default '', packnr varchar(30) default NULL, teil varchar(4) NOT NULL default '', PRIMARY KEY
(datnr)
); # # Tabellenstruktur für Tabelle `songs` # CREATE TABLE songs ( songnr int(4) NOT NULL default '0', songtitel varchar(150) default NULL, autoren varchar(50) default NULL, jahr year(4) default NULL, PRIMARY KEY
(songnr)
); # # Tabellenstruktur für Tabelle `veroeffentlichungen` # CREATE TABLE veroeffentlichungen ( veroeffnr int(4) NOT NULL default '0', aufnr int(4) NOT NULL default '0', datnr int(4) NOT NULL default '0', PRIMARY KEY
(veroeffnr)
); Einige Besonderheiten in der Syntax ergeben sich für den MS SQL Server, die hier wir am gleichen Beispiel verdeutlichen wollen, ohne jedoch noch einmal die Schrittfolge abzubilden. Folgende Punkte gilt es dabei zu beachten: ¾ Der Datentyp int kann nicht mit einer Längenangabe verbunden werden. ¾ Datentypen wie year (MySQL) finden keine exakte Entsprechung. ¾ Kommentare werden durch zwei Bindestriche anstatt zwei Rautenzeichen abgegrenzt.
54
SQL
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
¾ Befehle können durch Semikolon abgeschlossen werden.
Die Tabellendefinitionen finden Sie in der Datei songs1_MSSQL.sql.
--- Tabellenstruktur für Tabelle `aufnahmen` -CREATE TABLE aufnahmen ( aufnr int NOT NULL default 0, songnr int NOT NULL default 0, aufntitel varchar(150) NOT NULL default ' ', aufntyp varchar(10) NOT NULL default ' ', duettpartner varchar(20) default NULL, aufndatum datetime default NULL, PRIMARY KEY
(aufnr)
) --- Tabellenstruktur für Tabelle `aufnahmen` -CREATE TABLE songs ( songnr int NOT NULL default '0', songtitel varchar(150) default NULL, autoren varchar(50) default NULL, jahr datetime default NULL, PRIMARY KEY
(songnr)
)
3.3.2 SQL99-Datentypen In der folgenden Aufstellung stellen wir Ihnen die Standard-Datentypen der SQL-Sprache vor. Je nach System, das Sie tatsächlich einsetzen oder das Sie benutzen, kann und wird es Unterschiede geben. Eventuell heißen die Typen anders oder sie haben eine etwas andere Notation, was z.B. Nachkommastellen anbetrifft. In diesem Fall müssen Sie immer die Dokumentation Ihres DBS berücksichtigen. Die folgende Liste folgt allerdings der Spezifikation für die SQL99-Notation. Oft werden logische, boolesche Information wie Ja/Nein bzw. in SQL 1/0 gespeichert. Dies gilt z.B. für den Einsatz von Optionsfeldern der Form Anrede {Herr, Frau}, wenn beide Werte binär mit 1 und 0 kodiert werden. Bit-Ketten speichen feste oder variable Bit-Ketten. ¾ BIT [(länge)] oder BIT VARYING [(länge)]
SQL
55
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
Für längere Bit-Ketten steht dagegen ein anderer Datentyp zur Verfügung. Hier wird z.B. an Bilder gedacht, die typischerweise sehr große Datenmengen enthalten. ¾ BLOB [(länge)] Zeichenketten (Texte) sind eine Folge alphanumerischer Zeichen, wobei zusätzlich eine Längenangabe gemacht werden kann. ¾ CHARACTER [(länge)] oder CHARACTER VARYING [(länge)] ¾ CHAR [(länge)] oder VARCHAR [(länge)] Landesbezogene Zeichenketten verarbeiten zusätzlich auch Sonderzeichen der jeweiligen Landessprache. ¾ NATIONAL CHARACTER [(länge)] ¾ NATIONAL CHARACTER VARYING [(länge)] Exakte numerische Zeichen verarbeiten Zahlen. Sie heißen exakt, weil sie entweder ganze Zahlen sind oder eine feste Anzahl Dezimalstellen (nachkommastellen) aufweisen. ¾ INTEGER [(länge[,nachkommastellen])] ¾ SMALLINT [(länge[,nachkommastellen])] ¾ NUMERIC [(länge[,nachkommastellen])] ¾ DECIMAL [(länge[,nachkommastellen])] Angenährte Zahlen sind Zahlendarstellungen in Exponential-Schreibweise, wobei Basis und Exponent ein Vorzeichen haben können. Die angegebene Länge steht für die Genauigkeit der Basis. ¾ FLOAT [(länge[,nachkommastellen])] ¾ REAL [(länge[,nachkommastellen])] ¾ DOUBLE PRECISION [(länge[,nachkommastellen])] Kalendarische Werte wie Daten oder Zeiten setzen sich aus mehreren Bausteinen zusammen, wobei die einzelnen Felder Jahr-Monat-Tag durch ein Minus als Trennzeichen separiert werden. Diese Funktion übernimmt für Stunde:Minuten:Sekunden der Doppelpunkt. Die Verwendung der Formatierungsvorgabe ist auch sehr unterschiedlich. ¾ DATE mit jjjj-mm-tt ¾ TIME mit stst:mm:seksek ¾ TIMESTAMP mit jjjj-mm-tt stst:mm:seksek Folgender Datentyp soll eine Differenz zwischen zwei Zeiten speichern. ¾ INTERVAL [Intervallart]
3.3.3 Tabelle auf Existenz überprüfen Manchmal möchte man eine neue Tabelle erstellen, wobei man vielleicht wegen der großen Anzahl der bereits vorhandenen Tabellen nicht überblicken kann, ob sie schon existiert. In diesem Fall kann man zunächst die Tabelle bei Existenz löschen, vermeidet dadurch die mögliche Fehlermeldung, die ausgegeben werden könnte, wenn die Tabelle doch schon existieren würde, und legt sie dann erst an.
56
SQL
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
Die Tabellendefinitionen finden Sie in der Datei songs2.sql.
DROP TABLE IF EXISTS datentraeger; CREATE TABLE datentraeger ( datnr int(4) NOT NULL default '0', veroeffnr int(4) NOT NULL default '0', dattitel varchar(150) NOT NULL default '', datart varchar(20) NOT NULL default '', datunterart varchar(20) default NULL, verlagnr varchar(30) NOT NULL default '', packnr varchar(30) default NULL, teil varchar(4) NOT NULL default '', PRIMARY KEY
(datnr)
);
Die Tabellendefinitionen finden Sie in der Datei songs2_MSSQL.sql.
Für den MS SQL Server ergibt sich eine sehr spezielle und eigenwillige Syntax: 1. Mit Hilfe einer if-Klausel testet man zunächst, ob die Tabelle existiert. Dabei greift man auf die Einträge in der Systemtabelle sysobjects zurück, in der die Tabelle gespeichert sein müsste. IF EXISTS(SELECT name FROM sysobjects WHERE
name = 'aufnahmen'
AND type = 'U') 2. Ist das der Fall, fordert man das DBS auf, die Tabelle zu entfernen. Mit dem Befehl GO führt man diese Anweisung aus. DROP TABLE aufnahmen GO 3. Danach erst folgt das Skript, mit dem man die Tabelle wieder oder zum ersten Mal anlegt. CREATE TABLE aufnahmen ( aufnr int NOT NULL default '0', songnr int NOT NULL default '0', aufntitel varchar(150) NOT NULL default '', aufntyp varchar(10) NOT NULL default '', duettpartner varchar(20) default NULL,
SQL
57
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
aufndatum datetime default NULL, PRIMARY KEY
(aufnr)
);
3.3.4 Synonyme Teilweise kann es bei langen Tabellennamen zweckmäßig sein, einen kürzeren Namen als Synonym oder als Alias-Namen vorzugeben. Die hier verwendeten Namen sind alle sehr kurz, sodass nur die Syntax und das Prinzip zählt. Nachdem eine solche Namensänderung definiert wurde, kann in Abfragen oder anderen Transaktionen auf den (kürzeren, einfacheren) Alias-Namen zurückgegriffen werden. Über den DROP – Befehl ist der entsprechende Name wieder zu löschen. Bitte beachten Sie, dass der MS SQL Server Synonyme nicht unterstützt. CREATE {SYNONYM | ALIAS} synonymname FOR tabellenname 1. Richten Sie ein Synonym für die Tabelle datentraeger ein. CREATE SYNONYM videoscdsdvds FOR datentraeger; DROP SYNONYM videocdsdvds; 2. Alternativ kann auch das Schlüsselwort ALIAS verwendet werden: CREATE ALIAS videoscdsdvds FOR datentraeger; DROP ALIAS videocdsdvds;
3.4 Tabellenstruktur ändern Die unterschiedlichen Möglichkeiten, auf die Struktur und die Eigenschaften eine Tabelle Einfluss zu nehmen, fasst folgende Syntaxübersicht zusammen: ALTER TABLE tabellenname {ADD spaltenname datentyp} |{ALTER | CHANGE spaltenname_alt spaltenname_neu datentyp [(laenge)] |{DEFAULT wert | DROP DEFAULT} |{DROP spaltenname {RESTRICT | CASCADE} |{RENAME tabellenname_neu} |{ADD tabelleneinschränkung} |{DROP CONSTRAINT einschränkung {RESTRICT | CASCADE}} Dabei gelten folgende Regeln: ¾ ALTER ist der Befehl, der immer vorgeschaltet werden muss und der den Tabellennamen enthält. ¾ DROP löscht die Spalte, die den nachgesetzten Namen trägt. ¾ RENAME benennt die Tabelle in einen nachgesetzten neuen Namen um. Die Struktur bleibt dabei erhalten.
58
SQL
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
¾ ADD fügt eine neue Spalte mit dem nachgesetzten Namen und Datentyp hinzu. Innerhalb dieser Anweisung kann zusätzlich wie bei der Neudefinition in der CREATE TABLE – Anweisung auch eine DEFAULT – Anweisung stehen. ¾ ALTER bzw. CHANGE erlauben Spaltenänderungen mit Bezug auf den Spaltennamen, den Datentyp nebst Länge oder auch alternativ den Standardwert. Dieser kann wie bei einer Neudefinition erstellt oder komplett mit DROP gelöscht werden. ¾ Die beiden Schlüsselwörter RESTRICT und CASCADE modifizieren die Löschaktion, wenn weitere Objekte wie Sichten (views) und Einschränkungen für Tabellen oder weitere Objekte (assertion) vorhanden sind. In diesen Fällen verhindert RESTRICT das Löschen, um die Funktionsweise der anderen Objekte nicht zu beeinflussen, während CASCADE alle Objekte löscht.
Die Tabellendefinitionen finden Sie in der Datei songs3.sql.
1. Fügen Sie eine neue Spalte namens laenge an. In dieser Spalte soll also die Länge der Aufnahmen eingetragen sein, die natürlich bei Mixen oder LiveAufnahmen stark variieren kann. ALTER TABLE `Songs`.`aufnahmen` ADD `laenge` VARCHAR(5); Um diese Spalte wieder zu löschen bzw. zwei Spalten gleichzeitig zu löschen, verwenden Sie folgende Befehle: ALTER TABLE `aufnahmen`DROP `laenge`; ALTER TABLE `aufnahmen`DROP `aufndatum`,DROP `laenge`; 2. Ändern Sie den Tabellennamen in lieder um. ALTER TABLE `Songs`.`lieder` 3. Ändern Sie den Spaltennamen autoren in textmusik um. Mit dem gleichen Befehl können Sie auch sofort Änderungen am Datentyp oder am Vorgabewert vornehmen. CHANGE `autoren` `textmusik` VARCHAR(50) DEFAULT NULL 4. Ändern Sie den Datentyp für die Spalte laenge zu time mit Vorgabewert Null. ALTER TABLE `Songs`.`aufnahmen` CHANGE `laenge` `laenge` TIME DEFAULT NULL 5. Benennen Sie die Tabelle songs in lieder. ALTER TABLE `songs` RENAME `lieder` 6. Benennen Sie das entstehende Ergebnis der zuvor ausgeführten Änderungsbefehle. # # Tabellenstruktur für Tabelle `aufnahmen`
SQL
59
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
# DROP TABLE IF EXISTS aufnahmen; CREATE TABLE aufnahmen ( aufnr int(4) NOT NULL default '0', songnr int(4) NOT NULL default '0', aufntitel varchar(150) NOT NULL default '', aufntyp varchar(10) NOT NULL default '', duettpartner varchar(20) default NULL, aufndatum year(4) default NULL, laenge time default NULL, PRIMARY KEY
(aufnr)
); # # Tabellenstruktur für Tabelle `lieder` # DROP TABLE IF EXISTS lieder; CREATE TABLE lieder ( songnr int(4) NOT NULL default '0', songtitel varchar(150) default NULL, textmusik varchar(50) default NULL, jahr year(4) default NULL, PRIMARY KEY
(songnr)
);
Die Tabellendefinitionen finden Sie in der Datei songs3_MSSQL.sql.
Für den MS SQL Server muss man zusätzlich noch den genauen Namen des Datenbankobjekts (dbo) angeben und auf die Hochkommata verzichten: ALTER TABLE songs.dbo.aufnahmen ADD laenge VARCHAR(5); ALTER TABLE songs.dbo.aufnahmen DROP column laenge;
3.5 Einschränkungen und Datenüberprüfungen Bereits im letzten Kapitel hatten wir kurz das Thema angeschnitten, wie man prinzipiell verhindert, dass DB-Benutzer falsche Daten oder ungewünschte Informationsstrukturen in die DB eintragen.
60
SQL
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
Diese Überlegungen drehten sich um die Spalte aufntyp in der Tabelle aufnahmen. Sie sollte lediglich die beiden Werte {live, nicht live} enthalten, weil unter diese beide großen Kategorien sowohl Konzert- oder TV-Aufnahmen (live) wie auch Studio-Aufnahmen oder Mixe (nicht live) erfasst werden sollten. Eventuelle Spezialfälle wie vom Zimmermädchen aus dem Tonbandgerät gestohlene Hotelzimmeraufnahmen würden in dieser ersten Variante zunächst einmal brutal nach Belieben unter die Kategorie live fallen, obwohl vielleicht gar kein Publikum anwesend war, aber prinzipiell ist das Ziel dieses Wertebereichs bereits erfüllt, weil zumindest nicht jeder Benutzer seine eigenen Kategorien verwenden kann. Er soll also letztendlich nur eine von beiden Möglichkeiten auswählen bzw. eintragen können und nicht noch selbstständig unterscheiden, ob es ein TV-Auftritt oder ein Konzert war, die diese Aufnahme hervorbrachten. Denn dann stellte sich umgehend das Problem, wie mit einem Konzert zu verfahren sei, das im Fernsehen oder im Radio ausgestrahlt wurde (Amsterdam 1996) und gleichzeitig auf verschiedenen Tonträgern (DVD, Video) veröffentlicht wurde.
Die Tabellendefinitionen finden Sie in der Datei songs4.sql.
3.5.1 Festlegen eines Wertebereichs Für die allgemeine Festlegung eines Wertebereichs, wobei dies nicht zusätzlich in die Tabellendefinition aufgenommen wird, steht die CREATE DOMAIN – Anweisung zur Verfügung, die die folgende allgemeine Syntax besitzt: CREATE DOMAIN domänenname [AS] datentyp [DEFAULT voreinstellung] [[einschränkung]] CHECK (bedingung) [[INITIALLY DEFERRED | INITIALLY IMMEDIATE] [[NOT] DEFERRABLE] ] ] [COLLATE collationname] Wie Sie sehen, kann die vollständige Syntax für die Definition einer Domäne relativ viele andere Einstellungen behalten. Diese einzelnen Möglichkeiten werden im Laufe dieses Kapitels noch vorgestellt und sollten an dieser Stelle wiederum nur als Übersicht über den kompletten Befehl stehen. Im Einzelnen können folgende Befehle verwendet werden: ¾ Für den Wertebereich kann ein Datentyp eingestellt werden, der typischerweise mit dem Datentyp der Spalte, auf die er sich bezieht, übereinstimmen sollte. Dies ist nicht zwangsläufig so, sondern kann anders sein, da Sie ja sehen, dass von einer Spalte in der Syntax nicht die Rede ist. Ein Wertebereich kann also als eigenständiges DB-Objekt angesehen werden, das einfach im DBS existiert und bei Bedarf für eine spezielle Spalte verwendet werden kann. ¾ Für alle Fälle kann eine Voreinstellung über den bereits bekannten DEFAULT – Wert definiert werden.
SQL
61
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
¾ Mit einschränkung ist auch hier wieder eine CONSTRAINT gemeint, auf die wir noch zu sprechen kommen. ¾ Die CHECK - Klausel selbst wiederum ist eine als DB-Regel bezeichnete Bedingung, die für einen in der bedingung angegebenen Zustand prüft, ob der Eintrag überhaupt sinnvoll ist. So kann also ein Mitarbeiter einer Firma dieselbe nicht früher (1989) verlassen, als er in sie eingetreten ist (1990). Zwischen den beiden Spalten eintritt und austritt könnte also eine derartige CHECK – Klausel die Datenintegrität oder Datenplausibilität mit eintritt < austritt berücksichtigen. ¾ Mit COLLATE ist eine spezielle Sortierfunktion gemeint, die über die CREATE COLLATION – Anweisung für unterschiedliche Sprachen eingerichtet werden kann. In einer solchen COLLATION könnt man also bspw. festlegen, dass Groß- vor Kleinbuchstaben sortiert werden sollen: ´A´ < ´B´ <... < ´Z´ < ´a´ < ´b´ < ... < ´z´ oder dass innerhalb eines Buchstabens zunächst die Großschreibung angezeigt werden soll: ´A´ < ´a´.
Im Hintergrund der Überlegungen steht, dass vom Benutzer eine DB-Aktion ausgeführt wird. Dies kann sowohl direkt über eine SQL-Abfrage geschehen, wie wir es hier immer machen, oder aber über eine grafische Oberfläche wie eine Web-Seite oder ein Programm. Eine solche Aktion kann einige Zeit in Anspruch nehmen. Um einen umfangreichen Datensatz mit vielleicht 20 Feldern auszufüllen, wovon einige vom Datentyp text sind, kann es sicherlich einige Minuten dauern. Die aktuellen Informationen könnten also in Zeitpunkt t1 auf dem Benutzerbildschirm ausgegeben worden sein. Innerhalb der Zeit, die dieser Benutzer braucht, um die Daten zu aktualisieren, führt ein anderer Benutzer Änderungen an diesem Datensatz aus. Diese Aktion würde in t2 geschehen. Wenn dann der Benutzer, der die Daten in t1 zur Änderung geladen hat, seine Änderungen in t3 speichern möchte, könnte es sein, dass die Datenstruktur innerhalb der Tabelle eine ganz andere ist oder sogar die Tabelle an sich nicht mehr existiert. Um solche Anomalien zu vermeiden, die wir Ihnen noch später genauer vorstellen werden, kann man mit Hilfe von Transaktionssteuerung die Abarbeitung der einzelnen Prozesse bestimmen. Die Schnittstelle zwischen diesem Thema der Transaktionssteuerung und den Einschränkungen liegt jetzt in der Behandlung der Überprüfung der Einschränkung, ob sie also direkt nach der Änderungsaktion in t3 oder wesentlich später erfolgt, nachdem der Benutzer noch weitere Änderungen vorgenommen hat.
Mit Hilfe einiger Schlüsselwörter, die nicht für diese, aber für alle anderen Einschränkungen gelten, die in diesem Kapitel gesetzt werden, kann man Einschränkungen überprüfen. Steht eine Datenänderung einer Einschränkung im Wege, lehnt das DBS diese Datenänderung mit Hilfe einer Fehlermeldung ab bzw. führt sie dadurch nicht aus. ¾ NOT DEFERRABLE ist eine Einschränkung standardmäßig, sodass dieser Eintrag unterbleiben kann, wenn diese Voreinstellung gewünscht ist. Sie bedeutet, dass bei jeder Transaktion, die Datenänderungen zur Folge hat (Neu-Eintrag, Aktualisierung), die Einschränkung überprüft wird. ¾ DEFERRABLE dagegen berücksichtigt die Einstellung in der evtl. vorhandenen CONSTRAINT – Bedingung. Ist dort IMMEDIATE verwendet worden, findet die Überprüfung unmittelbar nach der Datenänderung statt. Bei DEFERRED dagegen wartet das DBS zunächst die komplette Transaktion ab, die vom Benutzer eingegeben wurde. ¾ Mit dem zusätzlichen Schlüsselwort INITIALLY kann die Voreinstellung der Einschränkung wiederum an dieser Stelle gesetzt werden.
62
SQL
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
Eine Domäne kann wie andere Objekte sehr einfach gelöscht werden, wobei die folgende Syntax benötigt wird: DROP DOMAIN domänenname {CASCADE | RESTRICT} Die beiden Schlüsselwörter CASCADE und RESTRICT beeinflussen das Löschverhalten analog wie oben bereits beschrieben: ¾ RESTRICT unterbindet den Löschvorgang, wenn die Domäne von anderer Seite (z.B. von einem anderen Benutzer) gleichzeitig benutzt wird und der Löschvorgang innerhalb der Transaktion Anomalien hervorrufen könnte. ¾ CASCADE dagegen trägt in eine Spalte, auf die sich die Domäne bezieht, den DEFAULT – Wert in diese Spalte ein, wenn kein solcher in der Spalte vorhanden ist. Zusätzlich kann der Datentyp genau auf den Datentyp der Domäne gesetzt werden, wenn eine solche Spalte einen ähnlichen Datentyp (zumindest gleicher Typ, aber nicht die gleiche Länge) besitzt. Zum Schluss können dadurch noch Einschränkungen auf eine Spalte übertragen werden, wenn der Benutzer, der diese Aktion ausführt, die dafür notwendige Berechtigung besitzt. Im gegenteiligen Fall wird die Domäne dennoch gelöscht. Im folgende Beispiel soll die oben beschriebene Überlegung in einen Wertebereich umgesetzt werden: 1. Benennen Sie die Domäne mit aufnahmetyp, setzen Sie einen Datentyp und geben Sie den Standardwert mit live vor. Vermutlich dürften die meisten Songs in dieser Tabelle LiveAufnahmen zugeordnet werden, sodass dies eine günstige Entscheidung ist. CREATE DOMAIN aufnahmetyp varchar(10) default ´live´, 2. Geben Sie eine CHECK - Bedingung vor, die untersucht, ob die Werte {live, nicht live} vorliegen. CHECK ( VALUE IN (´live´, ´nicht live´));
3.5.2 Verwenden der Einschränkung innerhalb der Tabelle Interessant ist natürlich nicht wirklich, wie ein solcher Wertebereich im luftleeren Raum definiert wird, sondern wie Sie ihn bei der Tabellendefinition einsetzen. In diesem Fall muss nach erfolgter Definition der Domäne die jeweilige Spalte nur noch mit dem Namen der Domäne aufgerufen werden. Möchte man sehr große Datenstrukturen definieren mit teilweise ähnlichen Feldern, die den gleichen Plausibilitätsregeln unterliegen (alle Daten für einen Mitarbeiter können nicht kleiner sein als sein Geburtsjahr), so könnte man dies einfach in eine solche Bedingung auslagern. Für einen reinen Wertebereich könnte ein Anwendungsfall darin liegen, dass bei der Verteilung von Mitarbeitern auf einzelne Betriebsbereiche in der Domäne {Labor, ReWe, Messwarte, Meisterstube, Werk} die gleichen Werte verwendet werden wie bei den Telefonanschlüssen oder in der Tabelle werksbereiche. Sie würden damit alle auf die gleiche Domäne zugreifen, die man auslagern und mehrfach in den Tabellendefinitionen verwenden könnte. Damit hätte man auch gleichzeitig eine DB-übergreifende Plausibilitätsregel aufgestellt. # # Tabelle `aufnahmen` mit Einschränkung bei aufntyp # DROP TABLE IF EXISTS aufnahmen; CREATE TABLE aufnahmen ( aufnr int(4) NOT NULL default '0', songnr int(4) NOT NULL default '0',
SQL
63
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
aufntitel varchar(150) NOT NULL default '', aufntyp aufnahmetyp, duettpartner varchar(20) default NULL, aufndatum year(4) default NULL, PRIMARY KEY
(aufnr)
);
3.5.3 CHECK – Klausel innerhalb der Tabellendefinition Eine weitere Möglichkeit ist es, direkt innerhalb der Tabellendefinition eine Prüfung über die CHECK – Klausel einzubauen. Dabei können einfache Operatoren, Funktionen (wie z.B. die Summenberechnung mit SUM) oder Abfragen verwendet werden. Die letzten beiden Möglichkeiten werden Sie später noch kennen lernen, sodass an dieser Stelle zunächst nur mit Hilfe einfacher Operatoren, die denen der Abfragen entsprechen, zwei Regeln für die Jahreszahlen verwendet werden. 1. Tina Turner ist 1939 geboren, sodass natürlich jede Aufnahme nach diesem Jahr stattfinden muss, wobei die Bedingung jahr > 1939 entsteht, die für die Spalte aufndatum verwendet wird. # # Tabelle `aufnahmen` mit Regel bei aufntyp # DROP TABLE IF EXISTS aufnahmen; CREATE TABLE aufnahmen ( aufnr int(4) NOT NULL default '0', songnr int(4) NOT NULL default '0', aufntitel varchar(150) NOT NULL default '', aufntyp aufnahmetyp, duettpartner varchar(20) default NULL, aufndatum year(4) CHECK (aufndatum > 1939), PRIMARY KEY
(aufnr)
); 2. Eine ähnliche Überlegung gilt für das Erstellungsjahr des Songs. Es werden keine Songs existieren, die vor 1900 und aus heutiger Sicht nach 2020 geschrieben sein können. Dies kann über das Schlüsselwort BETWEEN in eine Bedingung überführt werden. # # Tabelle `songs` mit Regel für jahr # DROP TABLE IF EXISTS songs; CREATE TABLE songs ( songnr int(4) NOT NULL default '0',
64
SQL
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
songtitel varchar(150) default NULL, autoren varchar(50) default NULL, jahr year(4) CHECK (jahr BETWEEN 1900 AND 2020), PRIMARY KEY
(songnr)
);
Änderungen an Tabellen mit ADD und ALTER können auch mit CHECK – Klauseln ausgeführt werden. Die CHECK – Klausel folgt in der Notation einfach dem Spaltennamen und dem Datentyp.
3.5.4 Einschränkungen für Tabellen Der Unterschied zwischen der hier und im nächsten Abschnitt vorgestellten Vorgehensweise besteht darin, dass über den Befehl CONSTRAINT ein eigenes Datenbankobjekt erzeugt wird. Es trägt damit einen eigenen Namen und ist nicht mit der Tabelle verbunden. Daher kann sich die Bedingung im CONSTRAINT im Gegensatz zu einer CHECK - Klausel auch auf mehrere Tabellen beziehen. Eine einfache CHECK – Klausel dagegen ist mit einer Spalte direkt in der Tabellendefinition verbunden. Sie wird hier im Rahmen der Bedingung eingebunden. CONSTRAINT einschränkungsname bedingung [[INITIALLY DEFERRED | INITALLY IMMEDIATE] [NOT] DEFERRABLE] Die gleiche Bedingung wie oben soll also zunächst festgelegt und dann innerhalb der Tabellendefinition aufgerufen werden. Achten Sie dabei darauf, dass die Tabellenspalte über einen Punkt mit dem Tabellennamen verbunden ist, damit auch bei gleichen Spaltennamen eine eindeutige Zuordnung gewährleistet ist. 1. Legen Sie eine Einschränkung für das Aufnahmedatum fest, das immer größer als 1939 sein muss. Gemäß der Schlüsselwörter nach der CHECK – Klausel erfolgt die Überprüfung am Ende der gesamten Transaktion des Benutzers. CONSTRAINT aufnahmedatum CHECK (aufnahmen.aufndatum > 1939), INITIALLY DEFERRED DEFERRABLE 2. Legen Sie eine Einschränkung für das Kompositionsdatum fest, das laut obiger Überlegung zwischen den Jahren 1900 und 2020 liegen muss. Hierbei wird als Variante die Überprüfung immer direkt nach dem Eintrag eines neuen Datensatzes vorgenommen. CONSTRAINT kompositionsdatum CHECK (songs.jahr BETWEEN 1900 AND 2020), NOT DEFERRABLE
SQL
65
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
3. Rufen Sie die Einschränkung in einer Tabellendefinition auf. # # Tabelle `songs` mit Constraint für jahr # DROP TABLE IF EXISTS songs; CREATE TABLE songs ( songnr int(4) NOT NULL default '0', songtitel varchar(150) default NULL, autoren varchar(50) default NULL, jahr year(4) CHECK (jahr between 1900 and 2020), kompositionsdatum, PRIMARY KEY
(songnr)
);
Innerhalb der CHECK – Klausel können Sie auch mit Hilfe einer Abfrage auf andere Tabellen zugreifen, um DB-übergreifende Regeln zu definieren. Dabei wird die Abfrage in runde Klammern gesetzt und am Ende z.B. mit einem Operator mit einem Wert verglichen.
Sie schalten eine Tabellenbeschränkung mit folgendem Befehl aus, wobei nicht wie beim DROP – Befehl die gesamte Einschränkung entfernt wird: ALTER TABLE aufnahmen DISABLE CONSTRAINT aufnahmedatum; Um eine Einschränkung zu löschen, verwenden Sie lediglich: DROP CONSTRAINT einschränkungsname {CASCADE | RESTRICT}
3.6 Tabellen untereinander referenzieren Für die Beziehungen innerhalb der Datenbank bzw. zwischen den einzelnen Tabellen werden Fremdschlüssel verwendet. Dabei werden diese nicht nur in den Tabellen eingetragen, sondern auch mit dem Befehl FOREIGN KEY eigens ausgewiesen und über REFERENCES mit der zugehörigen Tabelle verbunden. Dies funktioniert allerdings weder bei MySQL noch beim MS SQLServer. Eine Datenbank funktioniert dagegen auch ohne die explizite Festsetzung von Fremdschlüsseln, indem einfach die entsprechenden Felder in den einzelnen Tabellen angelegt werden. Die Definition von Fremdschlüsseln in der Datenbank hat darüber hinaus den Vorteil, dass so dem DBS bekannt ist, dass es sich bei einem bestimmten Feld um einen Fremdschlüssel handelt und so selbst die referenzielle Integrität prüfen kann. # # Tabelle `veroeffentlichungen` mit Fremdschlüsseln
66
SQL
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
# DROP TABLE IF EXISTS veroeffentlichungen; CREATE TABLE veroeffentlichungen ( veroeffnr int(4) NOT NULL default '0', aufnr int(4) NOT NULL default '0', datnr int(4) NOT NULL default '0', PRIMARY KEY
(veroeffnr),
FOREIGN KEY
(aufnr) REFERENCES (aufnahmen),
FOREIGN KEY
(datnr) REFERENCES (datentraeger)
);
3.7 Daten strukturieren mit Indizes Ein Index ist weniger wichtig, wenn eine Tabelle erstellt wird, sondern für die späteren Abfragen und für eine spezielle Kontrolle beim Einfügevorgang. Insgesamt stellt ein Indizierung eine Möglichkeit dar, Tabellenzugriffe schneller zu gestalten, weil durch einen Index verhindert wird, dass eine Tabelle Zeile für Zeile (sequentiell) durchsucht wird, um einen bestimmten Eintrag zu finden. Bei einer Tabelle von 20 Zeilen mag das nicht lange dauern, aber wenn Sie bspw. Logfiles mit einer umfangreichen Zugriffserfassung einer gesamten Webpräsenz auslesen und schön formatiert ausgeben wollen, können bei 20 Seitenzugriffen mit 10 weiteren Klicks am Tag 200 Datensätze gespeichert werden. Nach einem Monat oder nach einem halben Jahr kommt eine mehrere 1000 Zeilen lange Tabelle heraus. In diesem Augenblick wäre es schon günstiger, wenn es eine Methode gäbe, die für die Datenbank einen schnelleren Zugriff auf die Datensätze ermöglicht. Ein Index ist letztendlich eine eigene Tabelle innerhalb der Datenbank, in die Spaltenwert und Speicherplätze einer indizierten Tabelle abgelegt werden und daher nach dem Index-Kriterium vorsortiert wurden. Dabei arbeitet das DBS wie ein Leser bei der Verwendung eines Buch-Index. Man sucht ein Stichwort, erhält eine Seitenzahl, springt zu dieser Seite und sucht innerhalb dieser Seite dann nach dem Stichwort bzw. nach den Informationen, die mit diesem Stichwort zusammenhängen. Es ergibt sich schnell, dass diese Vorgehensweise schneller abläuft, als wenn man für den einen Befehl oder die eine Syntaxübersicht das gesamte Buch durchsucht hätte. Gerade wenn die Informationen am Ende der Tabelle bzw. am Ende des Buches zu finden sind, ist ein sequentieller Zugriff im Gegensatz zu einem direkten sehr hilfreich. Drei Effekte machen den Index so interessant für die Beschleunigung der Zugriffsgeschwindigkeit: ¾ Da natürlich nicht alle Datensätze indiziert werden, sondern dieser Vorgang nach einem speziellen Muster abläuft, ist die Index-Tabelle wesentlich kleiner als die Originaltabelle. ¾ Die Organisation innerhalb der Datensätze der Indextabelle ist für die Suche nach einer bestimmten Spalte optimiert. Während bspw. in einer Mitarbeitertabelle in der Spalte bereich Werte aus dem oben genannten Wertebereich {Labor, ReWe, Messwarte, Meisterstube, Werk} für jeden Mitarbeiter gespeichert sind, ist die Reihenfolge dieser Tabelle natürlich nicht optimal, da in einer Firma in beliebiger Reihenfolge Mitarbeiter in Bereiche eingestellt werden und ihre Bereiche irgendwann wieder verlassen. Dadurch werden Suchabfragen wie „Zeige alle Mitarbeiter nach Bereichen an“ oder „Zähle die Mitarbeiter pro Bereich“ erschwert, da im Normalfall die gesamte Tabelle durchsucht werden muss, um die Spalte bereich zu
SQL
67
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
durchforsten. Ist dagegen ein Index über diese Spalte gelegt, ist die Organisation in der IndexTabelle genau für eine derartige Suche optimiert. ¾ Nachdem der Index gelesen wurde, verbleibt für die eigentliche Tabelle nur noch ein einziger Lesevorgang pro Datensatz. Der einzige Nachteil – bei so vielen Vorteilen muss es natürlich irgendwo einen Haken geben – besteht darin, dass bei Änderungen in der Tabelle (Einfüge- und Löschoperationen) zusätzlich auch der Index automatisch geändert werden muss. Dies kann dann ein wenig mehr Zeit in Anspruch nehmen als sonst. Die Erstellung eines Index ist nach diesen ganzen Überlegungen wiederum sehr einfach zu bewerkstelligen. Die verschiedenen Möglichkeiten, die Abfrage zu beschleunigen, laufen typischerweise im DBS selbst ab, sodass man nur über die Auswahl der Index-Spalte Einfluss auf die Optimierung nehmen kann. Das DBS setzt stets automatisch den Index bei einer Abfrage ein. 1. Erstellen Sie einen Index für die Songnummer. Dies ist die einfachste Variante der vier Möglichkeiten. Nach dem Befehl CREATE INDEX folgt ein Name für diesen Index (er ist also auch ein DB-Objekt). Dann wird mit ON die Tabelle aufgerufen, und in runden Klammern folgt die Spalte, für die dieser Index erstellt werden soll. Bei Produktnummern in einfacher Zählweise wie 1, 2, 3 wäre ein solcher Index wenig hilfreich, wenn die Produkte auch in dieser Reihenfolge in die Tabelle eingetragen wurden. Hat man aber komplexe, mehrstellige Nummern wie 98156, 52354, 32145 wird ein solcher Index wieder interessanter. CREATE INDEX songnummer ON songs (songnr); 2. Erstellen Sie einen Index für die Jahreszahl der Lieder. Es ist höchst unwahrscheinlich, dass sich jemand für die Nummern der Songs interessiert. Stattdessen möchte man sicherlich gerne wissen, wie viele Lieder TT überhaupt in einem Jahr aufgenommen hat, wie viele davon LiveAufnahmen und wie viele Studio-Aufnahmen sind. Diese Abfragen führen u.a. immer darauf hinaus, dass die Spalte jahr durchsucht wird. Wenn nach dem ersten Füllen der Datenbank mit dem Bestand der Plattensammlung neue Aufnahmen hinzukommen, dann werden die Jahreszahlen nicht mehr ordentlich untereinander in der Tabelle aufgelistet sein. Vielmehr kann es passieren, dass plötzlich ganz unten noch eine seltene Konzertaufnahme aus dem Jahre 1983 mit vielleicht 15 Titeln folgt. In der Index-Tabelle wäre also wichtig zu wissen, wo neue Jahreszahlen in der Tabelle positioniert sind. Dies könnte man mit einem Index über dieser Spalte erreichen. CREATE INDEX jahr ON songs (jahr); 3. Erstellen Sie einen Index mit dem Attribut UNIQUE. Hier wird lediglich immer ein Jahr bei mehrfachem Auftreten einer Jahreszahl in der Spalte für den Index erfasst. Dies ist sinnvoll, da in einigen Jahren oft mehrere Lieder geschrieben wurden. CREATE UNIQUE INDEX jahr ON songs (jahr); 4. Erstellen Sie einen Index für eine Optimierung der bereits oben angedeuteten Abfrage. Um gleichzeitig herauszufinden, welche Lieder in einem Jahr aufgenommen worden sind, genügen prinzipiell die Spalten songtitel und jahr. Also wäre es zweckmäßig, über beide Spalten einen gemeinsamen Index zu legen. Wird dann tatsächlich nur diese Abfrage ausgeführt, läuft diese in besonders kurzer Zeit ab, da nur die optimierte Index-Tabelle abgerufen wird. CREATE INDEX songundjahr ON songs (songtitel, jahr);
68
SQL
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
3.8 Kommentare für DB-Objekte Nicht immer ist für jede Tabelle, jede gespeicherte Abfrage oder Berechtigung klar, welche Zielsetzung oder Bedeutung sie hat. Hinzukommen Schwierigkeiten, wie sie gerade bei Beziehungstabellen und ihrer Bedeutung für das Datenmodell auftreten. Folgende kurze allgemeine Syntax steht zur Verfügung, um DB-Objekte zu kommentieren: COMMENT ON {[TABLE | COLUMN]} DB-objektname IS kommentar Beachten Sie bei der Kommentierung lediglich die nächsten, kurzen Punkte: ¾ In Standard-SQL stehen Ihnen Möglichkeiten zur Verfügung, Tabellen und einzelne Spalten zu kommentieren. Dies entscheiden Sie entweder durch expliziten Aufruf des Tabellen- oder Spaltennamens oder alternativ durch einen qualifizierten Namen. ¾ Der eigentliche Kommentar folgt in Redezeichen und Fließtext nach dem Schlüsselwort IS. 1. Für eine Tabelle müssen Sie diese lediglich mit ihrem Namen aufrufen und den entsprechenden Kommentar eingeben. COMMENT ON TABLE aufnahmen IS ’Eine Aufnahme ist eine auf einem Song beruhende Klangeinheit’ 2. Für eine Spalte ist zusätzlich auch der Tabellennamen von Bedeutung, um sie eindeutig zu referenzieren. COMMENT ON COLUMN aufnahmen.duettpartner IS ’Wenn möglich, mit Vorname und Nachname’ 3. Für den Abruf eines Kommentars muss man wissen, wie das jeweilige DBMS solche Kommentare verwaltet. Gemäß Standard-SQL und der meisten Implementationen findet man diese Kommentare in einer Systemtabelle. SELECT COMMENT FROM syscols WHERE tblname = ’aufnahmen ’ AND
3.8.1
colname = ’duettpartner’
Zusammenfassung
9 Tabellen, Einschränkungen, Alias-Namen und Indizes werden mit dem Befehl CREATE angelegt und mit dem Befehl DROP gelöscht. 9 Tabellen werden mit dem Befehl ALTER geändert. ADD dagegen fügt neue Spalten hinzu. 9 Bei der Definition von Spalten wird zuerst der Spaltenname genannt, gefolgt vom Datentyp und evtl. dem Standardwert.
SQL
69
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
9 Sinnvolle Eingaben kann man innerhalb der Tabellendefinition mit der CHECK – Klausel überprüfen. Sie fragt innerhalb eines Klammerausdrucks Bedingungen ab, die für die Werte zutreffen müssen. 9 Die Fremdschlüssel werden mit FOREIGN KEY angegeben und über REFERENCES mit der Tabelle verbunden, in der sie den Primärschlüssel stellen. 9 Ein Index dient der Optimierung von DB-Transaktionen, wobei in einer speziellen Tabelle eine optimierte, verkleinerte Version der indizierten Tabelle gespeichert wird. 9 Kommentare für Spalten und Tabellen vergeben Sie mit dem Befehl COMMENT:
3.8.2
Übungen
1. Erstellen Sie die Tabellen für die Vollkornmühle im Sauerland, deren Datenmodell Sie bereits in Aufgabe 8 des letzten Kapitels entwickelt haben. 2. Mit welchem Quelltext können Sie die Tabellen für die Firma SemiTex aus Aufgabe 2 des letzten Kapitels erstellen? Beachten Sie bitte, dass zunächst auf Existenz der Tabelle geprüft und diese Tabelle ggf. gelöscht werden soll. Des Weiteren sollen die Tabellen auch untereinander mit Fremdschlüsseln referenziert werden. Tipp: MySQL stellt als Datentyp zusätzlich text für längere Textpassagen zur Verfügung. Für welche Spalten ist dieser Datentyp geeignet? 3. Wie verwenden Sie den Datentyp date, wenn Sie eine Voreinstellung eingeben wollen? Wie lautet die DEFAULT-Anweisung? Zeigen Sie dies am Beispiel der Spalten Beginn und Ende der SemiTex-DB. 4. Geben Sie die Befehle an, die von der Tabelle datentraeger zur Tabelle datenmaterialien führen. # # Tabellenstruktur für Tabelle `datentraeger` # DROP TABLE IF EXISTS datentraeger; CREATE TABLE datentraeger ( datnr int(4) NOT NULL default '0', veroeffnr int(4) NOT NULL default '0', dattitel varchar(150) NOT NULL default '', datart varchar(20) NOT NULL default '', datunterart varchar(20) default NULL,
70
SQL
DATENBANK
UND
TABELLEN
ANLEGEN UND ÄNDERN
verlagnr varchar(30) NOT NULL default '', packnr varchar(30) default NULL, teil varchar(4) NOT NULL default '', Lernen Sie PRIMARY KEY (datnr) Daten in eine DB einzutragen );
Datensätze zu ändern
#
Daten wieder zu löschen # Tabellenstruktur für Tabelle `materialien` die Eigenschaften-Klausel mit dem # Schlüsselwort WHERE kennen und einfache Bedingungen festzulegen DROP TABLE IF EXISTS materialien; CREATE TABLE materialien ( datnr int(5) NOT NULL default '0', veroeffnr int(4) NOT NULL default '0', dattitel varchar(150) NOT NULL default '', dattyp varchar(20) NOT NULL default '', datsubtyp varchar(20) default NULL, verlagnr varchar(30) NOT NULL default '', packnr varchar(30) default NULL, datlaenge time default NULL, PRIMARY KEY
(datnr)
); 5. Entwickeln Sie eine Domäne datentraegeruntertyp mit den Werten {maxi, single, LP, 5-inch, 3-inch} und dem Datentyp varchar(20). Als Standardwert soll der Begriff maxi benutzt werden. 6. Entwickeln Sie eine Domäne datentraegertyp mit dem Standardwert CD und den Werten {vinyl, CD, DVD, Video, Cassette, MiniDisc, LaserDisc} sowie dem Datentyp varchar(20). 7. Rufen Sie beide Domänen bei der Definition der Tabelle datentraeger auf. 8. Definieren Sie die Fremdschlüssel in den Tabellen datentraeger und aufnahmen sowie die Tabellen, auf die sie sich beziehen. 9. Geben Sie in einem Kommentar eine Definition für die Tabelle datentraeger an. 10.Legen Sie in einem Kommentar für die Spalte autoren der Tabelle songs fest, dass Songautoren nur mit Nachnamen angegeben werden sollen.
SQL
71
DATENBANK
72
UND
TABELLEN
ANLEGEN UND ÄNDERN
SQL
4 Daten einfügen und ändern
SQL
73
DATEN
74
EINFÜGEN UND ÄNDERN
SQL
DATEN
EINFÜGEN UND ÄNDERN
4 Daten einfügen und ändern Nachdem die Datenbank geplant und umgesetzt ist, muss sie natürlich mit Daten gefüllt werden. Sind Daten vorhanden bzw. wurden sie erfolgreich eingefügt, sollen sie ab und an geändert (aktualisiert) oder sogar gelöscht werden. All dies wird über die einfachen Befehle INSERT, UPDATE und DELETE gelöst, die mit Hilfe einer Eigenschaften-Klausel modifiziert werden können.
4.1 Daten in eine DB eintragen Die Grundstruktur des Befehls, um Daten in eine Tabelle einzutragen, ist sehr simpel. Interessant ist vielmehr seine Flexibilität mit Blick auf die Syntaxmöglichkeiten, die zunächst in folgender Syntaxübersicht zusammengestellt werden: INSERT INTO tabellenname [(spalte1 [, spalte2, ...])] {VALUES (1wert1 [, 1wert2, ...)} |{[VALUES] (2wert1 [, 2wert2, ...)} |SELECT-Anweisung Folgende Überlegungen kennzeichnen den Aufbau und den Nutzen, den Sie aus dieser Syntaxübersicht ziehen können: ¾ Je nach Verwendungszweck oder Situation, in der dieser Befehl eingesetzt wird, kann man sich entscheiden, ob man nur eine Zeile oder mehrere gleichzeitig in die Tabelle einfügen möchte. Im Rahmen einer Spielprogrammierung wird es sicherlich für die Erfassung eines Höchstpunktestands so sein, dass nur der aktuelle Spieler sich mit seinem (einem) Datensatz in die Tabelle spieler oder punktstaende einträgt, wobei eine Spalte wie datum seinen Punktestand und Namen einem bestimmten Spiel zuweist. Anders dagegen wird es sich mit der Erfassung evtl. Mit- oder Gegenspieler verhalten, die sich alle gleichzeitig in einem gemeinsamen Formular eintragen können und die dann nachher gleichzeitig in die Tabelle spieler oder punktstaende eingetragen werden sollen. Hier könnte eine Syntax, in der sich lediglich die Werteliste für die einzelnen Tabellen wiederholt (solange man keine entsprechende Schleife verwendet) etwas übersichtlicher im Quelltext aussehen. ¾ Möchte man sämtliche Spalten verwenden, kann man sich die Nennung der Spalten sparen, sodass lediglich nach dem Tabellennamen die Werteliste vorgegeben wird. Hierbei muss man aber die in der Tabelle verwendete Reihenfolge der Spalten auch in der Werteliste verwenden, damit der Vorname nicht im Feld für den Nachnamen eingetragen wird. ¾ Möchte man dagegen nur bestimmte Spalten verwenden und andere nicht, muss man diese Spalten einzeln aufrufen.
SQL
75
DATEN
EINFÜGEN UND ÄNDERN
¾ Über die SELECT – Anweisung können Abfragen realisiert werden. Die Abfrageergebnisse können dann wiederum in diese Tabelle eingefügt werden. Hier muss natürlich der Ergebnisumfang, also die Spaltenzahl, mit der Spaltenanzahl der Tabelle bzw. der ausgewählten Spaltenanzahl übereinstimmen.
Die Reihenfolge der Werte in der Werteliste, die über VALUES aufgerufen wird, ist entscheidend für den Eintrag in der Datenbank. Die Reihenfolge der Spalten in der Tabelle oder in der Spalteliste muss in jedem Fall mit der Reihenfolge der Werte übereinstimmen, um Fehleinträge zu vermeiden.
1. Fügen Sie sämtlichen Spalten der Tabelle unternehmen für das Schulungsunternehmen SemiTex Kundendaten hinzu. Da hier jeweils alle Spalten verwendet werden, reicht die einfache Werteliste, wobei die Reihenfolge der Werte mit der Spaltenreihenfolge kongruent sein muss. Im SQLStandard stehen Zeichenketten bzw. auch längere Texte in Hochkommata, während Zahlen diese nicht benötigen. Insbesondere bei der Verwendung in Programmiertext treten hier in verschiedenen Programmiersprachen Änderungen auf. Redezeichen oder Hochkommata müssen hier typischerweise durch einen Rückstrich entwertet werden: \’Gewerbestraße\’. So wird z.B. verhindert, dass der Parser das Redezeichen für die Beendigung des Befehls oder für den Abschluss des Variablenwerts hält, wenn Sie die gesamte Abfrage in eine Variable wie $abfrage gespeichert haben. Die folgenden Beispiele verwenden die Tabelle unternehmen des Datenmodells für die Firma SemiTex, die in den Übungen von Projekt 1 beschrieben und umgesetzt wurde. Dort und in den Lösungen finden Sie weitere Hinweise. INSERT INTO unternehmen VALUES (1, 'Draht Gründling GmbH', 'Gewerbestraße', '15', '0357-62849-0', 'Metall', 84571, 'Sollbach', '
[email protected]', 'Dieter', 'Grünbein', '0357-62849-15', 'Geschäftsleiter'); INSERT INTO unternehmen VALUES (2, 'Stadt Sollbach', 'Hoffahrt', '19', '0357-63689-0', 'Stadt', 84571, 'Sollbach', '
[email protected]', 'Susanne', 'Korne', '0357-63689-17', 'Innerbetriebliche Weiterbildung'); INSERT INTO unternehmen VALUES (3, 'SAQUA GmbH', 'An der Bergkuppe', '35', '0358-58269-0', 'Getränke', 84571, 'Willingen', '
[email protected]', 'Hedwig', 'Schlimme-Putz', '035858269-6', 'Personalleiter');
76
SQL
DATEN
EINFÜGEN UND ÄNDERN
Die Skripte finden Sie in der Datei tbl_unternehmen1.txt.
2. Kombinieren Sie mehrere Einträge in einem einzigen Befehl. Hierbei müssen lediglich die Wertelisten über Kommata getrennt aneinander angeschlossen werden. Beachten Sie auch hier, dass der gesamte Einfüge-Befehl von einem Semikolon beendet wird. Dies war im vorherigen Fall nach jedem einzelnen Befehl der Fall. INSERT INTO unternehmen VALUES (1, 'Draht Gründling GmbH', 'Gewerbestraße', '15', '0357-62849-0', 'Metall', 84571, 'Sollbach', '
[email protected]', 'Dieter', 'Grünbein', '0357-62849-15', 'Geschäftsleiter'), (2, 'Stadt Sollbach', 'Hoffahrt', '19', '0357-63689-0', 'Stadt', 84571, 'Sollbach', '
[email protected]', 'Susanne', 'Korne', '0357-63689-17', 'Innerbetriebliche Weiterbildung'), (3, 'SAQUA GmbH', 'An der Bergkuppe', '35', '0358-58269-0', 'Getränke', 84571, 'Willingen', '
[email protected]', 'Hedwig', 'Schlimme-Putz', '035858269-6', 'Personalleiter'); 3. Verwenden Sie nur die Spalten für die reinen Unternehmensinformationen. Da eine Verbesserung des Datenmodells ohnehin darauf hinauslaufen würde, die Ansprechpartner in eine eigene Tabelle auszusondern, sieht man jetzt, dass durch das so gewählte Datenmodell viele Spalten leer bleiben, wenn nur Firmeninformationen zu erfassen sind. Die zu verwendenden Spalten werden in einen Klammerausdruck nach dem Tabellennamen aufgezählt. INSERT INTO unternehmen (untnr, untname, untstraße, unthausnr, unttelefon, untbranche, untplz, untstadt) VALUES (1, 'Draht Gründling GmbH', 'Gewerbestraße', '15', '0357-62849-0', 'Metall', 84571, 'Sollbach'), (2, 'Stadt Sollbach', 'Hoffahrt', '19', '0357-63689-0', 'Stadt', 84571, 'Sollbach'), (3, 'SAQUA GmbH', 'An der Bergkuppe', '35', '0358-58269-0', 'Getränke', 84571, 'Willingen'),
4.2 Daten löschen Ähnlich einfach ist der Löschvorgang, wobei hier mit der so genannten WHERE – Bedingung ein Kriterium vorgegeben werden kann, das die zu löschenden Daten herausfischt. In diesem Zusammenhang soll es nur sehr kurz um die Einzelheiten dieses sehr wichtigen Schlüsselworts gehen, da im nächsten Projekt darüber gesprochen wird. All das, was dort zu WHERE und den vielen Möglichkeiten der Kriterienbildung gesagt wird, können Sie natürlich auch hier verwenden. Gleiches gilt für die gesamte SELECT – Abfrage, die ebenfalls für den Löschvorgang eingesetzt werden kann.
SQL
77
DATEN
EINFÜGEN UND ÄNDERN
Folgende Syntax bietet auch für umfangreiche Löschaktionen die Basis: DELETE FROM tabellename |WHERE suchbedingung |WHERE suchbedingung IN SELECT – Anweisung Folgende Punkte gilt es zu beachten: ¾ Die Anweisung kann auch vollkommen alleine stehen, dann wird die Tabelle geleert, d.h. die Anweisung entfernt sämtliche Datensätze aus der Tabelle, ohne die Tabelle selbst zu löschen. In gewissen Fälle wie z.B. bei Oracle kann dies zu einem Überlauf für die Rückgängig-Funktion (Rollback) führen, sodass die Daten nicht komplett gelöscht werden können. ¾ Die einfache WHERE – Bedingung löscht anhand des Suchkriteriums, während über die Variante mit einer eingefügten SELECT – Anweisung auch Bezüge zu anderen Tabellen hergestellt werden können. Wollte man also für die Schulungsdatenbank der Firma SemiTex alle Kurse löschen, für die keine Buchung vorgelegen haben, muss innerhalb der SELECT – Anweisung ein entsprechender Abgleich über das in den Tabellen buchungen und kurse vorhandene Feld kursnr erfolgen.
Die Skripte und insbesondere die Daten für die Tabellen kurse und termine finden Sie in der Datei tbl_kurse1.txt.
Damit Sie einen Anhaltspunkt haben, was in den Tabellen in der Ergebnisdatei in längerer Form steht, folgt jeweils ein kurzer Auszug, wobei noch einmal die beiden Varianten des Dateneintrags gezeigt werden: ¾ Tabelle termine: INSERT INTO termine VALUES (9, '20127', '2002-04-02', '200204-05', 'Bochum'), (8, '20126', '2002-05-06', '200205-08', 'Bochum'), (7, '20121', '2002-06-03', '200206-06', 'Bochum'), (6, '20121', '2002-03-12', '200203-15', 'Bochum'), (5, '20120', '2002-06-10', '200206-13', 'Bochum'), (4, '20120', '2002-03-18', '200203-21', 'Bochum'), (3, '30128', '2002-05-03', '200205-03', 'Bochum'), (2, '20119', '2002-04-08', '200204-10', 'Bochum'), (1, '20117', '2002-03-25', '200203-27', 'Bochum');
78
SQL
DATEN
EINFÜGEN UND ÄNDERN
¾ Tabelle kurse: INSERT INTO kurse (Kursnr, Titel, Bereich, Dauer, Preis, Vorkenntnisse, Themen) VALUES (20117, 'PHP I', 'Programmierung', 3, '920', 'WebGrundkenntnisse, HTML-Kenntnisse, Programmierkenntnisse sind nützlich, aber nicht Pflicht.', 'Antwortformulare auf einer Webseite'); INSERT INTO kurse (Kursnr, Titel, Bereich, Dauer, Preis, Vorkenntnisse, Themen) VALUES (20118, 'JavaScript', 'Programmierung', 3, '870', 'geringe Programmierkenntnisse nützlich aber nicht Pflicht, HTMLGrundkenntnisse', 'Formularverarbeitung'); INSERT INTO kurse (Kursnr, Titel, Bereich, Dauer, Preis, Vorkenntnisse, Themen) VALUES (20119, 'PERL', 'Programmierung', 3, '920', 'HTMLGrundkenntnisse', 'Antwortformulare auf einer Webseite'); INSERT INTO kurse (Kursnr, Titel, Bereich, Dauer, Preis, Vorkenntnisse, Themen) VALUES (20120, 'C++', 'Programmierung', 4, '1175', 'geringe Programmierkenntnisse ', 'Standard Datenverarbeitung'); 1. Um alle Kurse aus dem Bereich Office zu löschen, muss der entsprechende Eintrag in der WHERE – Klausel vorgegeben sein. DELETE FROM kurse WHERE Bereich = 'Office'; 2. Die WHERE – Klausel lässt sich mit vielerlei Operatoren erweitern und wird im nächsten Projekt ausführlich dargestellt. Um alle Kurse mit einem Preis unterhalb von 600 Euro zu löschen, geben Sie diesen Preis mit dem Kleiner-Operator vor. DELETE FROM kurse WHERE Preis < 600; 3. Um mit Hilfe einer Abfrage zu arbeiten, wird diese Abfrage innerhalb eines Klammerausdrucks nach dem Schlüsselwort IN vorgegeben. In diesem Fall existiert eine weitere Tabelle termine, in der u.a. Termine in Dortmund eingetragen sind. Über ihre Kursnummer referenzierte Kurse, die in Dortmund stattfanden, sollen in der Tabelle kurse gelöscht werden. DELETE FROM kurse WHERE Kursnr IN (SELECT Kursnr FROM termine WHERE Ort='Dortmund'); 1. Löschen Sie den gesamten Tabelleninhalt, d.h. nur die Einträge, aber nicht das Schema. DELETE FROM kurse;
SQL
79
DATEN
EINFÜGEN UND ÄNDERN
Nicht alle Datenbanksysteme können solchermaßen verschachtelte Abfragen ausführen. In diesem Fall erhalten Sie eine entsprechende Fehlermeldung. Im Gegensatz zu MySQL können der MS SQL Server und Oracle diese Abfragen abarbeiten.
4.3 Daten aktualisieren und ändern Eine letzte Möglichkeit besteht darin, vorhandene Daten zu ändern, wobei auch hier die Möglichkeiten bzgl. der Vorgaben innerhalb der WHERE – Klausel wesentlich umfangreicher sind als hier dargestellt. Dafür verweisen wir Sie erneut auf das nächste Projekt und die dort vorgestellten Techniken. Die WHERE – Klausel hat in allen Einsatzbereichen die Funktionalität, die Sie dort vorfinden. Der grundlegend technische Unterschied zu den beiden anderen Befehlen besteht darin, dass nicht ein ganzer Datensatz betroffen ist, sondern lediglich eine Spalte. Die allgemeine Syntax für den so genannten UPDATE – Befehl ist folgendermaßen strukturiert: UPDATE tabellenname SET spalte1 = {wert | NULL | DEFAULT} [, spalte2 = {wert | NULL | DEFAULT}...] [WHERE suchbedingung [SELECT-Anweisung] ] Dabei sind folgende Variationen möglich: ¾ Zum einen kann man eine einzelne Spalte ansprechen und einen geänderten Wert vergeben. Zum anderen ist es ebenso möglich, nach der SET – Anweisung durch mehrere Kommata verbundene solcher Anweisungen ausführen zu lassen. ¾ Ist ein Standardwert vergeben, kann auch dieser automatisch geladen werden, ohne dass man ihn extra angeben müsste. ¾ Die eigentliche Änderung stellt entweder den Standard- oder den NULL – Wert dar oder einen ganz neuen Wert dar. Mit „wert“ ist in der allgemeinen Syntax nicht nur ein Eintrag wie eine einfache Zeichenkette oder eine einfache Zahl gemeint. Vielmehr kann man auch mit Hilfe einer mathematischen Berechnung (Erhöhung um 20 %) vorhandene Werte ändern. ¾ Alternativ kann zusätzlich eine WHERE – Bedingung zum Einsatz kommen, wenn nicht alle Datensätze durchlaufen und geändert werden sollen. Dabei kann diese Bedingung die gesamte Funktionalität annehmen und darüber hinaus mit einer verschachtelten SELECT – Bedingung erweitert werden.
Die Skripte und insbesondere die Daten für die Tabellen kurse und termine finden Sie in der Datei tbl_kurse2.txt.
1. Ändern Sie den Ort der Tabelle termine von Bochum zu Düsseldorf.
80
SQL
DATEN
EINFÜGEN UND ÄNDERN
UPDATE termine SET Ort='Düsseldorf'; 2. Ändern Sie Preise und Kursdauer. Innerhalb der neuen Wertzuweisung können komplexe Operationen verwendet werden. Wenn alle Preise um ein Viertel steigen sollen und die Dauer jeweils um einen Tag verlängert wird, dann kann lässt sich das durch Nennen der Spalte und Vorgabe der Rechenvorschrift erreichen. UPDATE kurse SET Preis = Preis*1.25, Dauer= Dauer+1; 3. Verändern Sie ausschließlich den Kurs mit der Kursnummer 10113 so, dass er nun in Dortmund stattfindet. Dabei hängen Sie die WHERE – Klausel mit ihrer Bedingung einfach direkt an die Wertzuweisung. UPDATE termine SET Ort='Dortmund' WHERE kursnr = 10113; 4. Lassen Sie alle Kurse aus dem Bereich Office in Dortmund stattfinden. Dabei müssen Sie eine etwas kompliziertere WHERE – Anweisung mit Hilfe des LIKE – Operators verwenden, der mit Hilfe bestimmter Jokerzeichen alphanumerische Einträge vergleicht. In diesem Fall ist bekannt, dass alle Kurse aus dem Office–Bereich mit einer 4 in der Kursnummer beginnen, sodass mit Hilfe eines Prozentzeichens beliebig viele Zeichen nach der 4 gefunden werden. Das Jokerzeichen besteht dabei aus dem Prozentzeichen, dass beliebig viele Zeichen (Zahlen und Buchstaben) repräsentiert. UPDATE termine SET Ort='Dortmund' WHERE kursnr LIKE '4%'; 5. Erhöhen Sie den Preis für alle Kurse, die in Dortmund stattfinden, um 20 Euro. Dies können Sie mit einer ähnlich gestalteten SELECT – Anweisung erreichen, die Sie bereits oben eingesetzt haben. Erneut wird das Abfrageergebnis durch den IN – Operator (für Zahlen können Sie auch die Vergleichsoperatoren verwenden) innerhalb der WHERE – Klausel abgerufen. UPDATE kurse SET Preis = Preis+20 WHERE Kursnr IN (SELECT Kursnr FROM termine WHERE Ort = 'Dortmund');
SQL
81
DATEN
EINFÜGEN UND ÄNDERN
Abgesehen von der eleganten Aktualisierungsanweisung, kann man hier sehr schön sehen, wie eine einfache Entscheidung ein Datenmodell in einem ganz ungünstigen Licht dastehen lassen kann und es eigentlich unbrauchbar macht. Bis jetzt hingen die Preise vom Kurs(thema) ab. In dem Augenblick, wo aber der Ort oder andere Faktoren ihn beeinflussen, weil z.B. das Essen im Hotel dort teurer ist oder ein eigener Raum gemietet werden muss, ergibt sich das Problem, dass immer nur ein Preis in der Tabelle kurse eingetragen sein kann. Ein Kurs darf jetzt nicht mehr an zwei Orten stattfinden, da er ja nur in Dortmund 20 Euro teurer ist. Um auf diese veränderte Zielsetzung der Datenbank zu reagieren, müsste man entweder eine Tabelle für Gewinnaufschläge einrichten, die pro Ort einen fixen Euro-Betrag als Zuschlag speichern, oder unterschiedliche Kurse mit gleichem Thema, aber unterschiedlichem Service speichern. Dies könnte durch eine Tabelle für die Serviceleistungen noch einmal ausgelagert werden, sodass man die Preise mit Hilfe des Grundpreises (Preis für das Thema) und weiteren Preisen (Servicepreise für Essen, Ort, Literatur oder Übernachtung) jeweils neu berechnen lässt. – Diese Überlegungen haben natürlich nichts mit der oben verwendeten Syntax zu tun, sollten aber noch einmal die Wichtigkeit des Datenmodells und die Verknüpfung zwischen Zielsetzung und dem Datenmodell zeigen.
4.3.1
Zusammenfassung
9 INSERT trägt Daten in der VALUES – Klausel in eine Tabelle ein. Reihenfolge der Spalten und Daten müssen übereinstimmen, um korrekte Einträge zu gewährleisten. 9 DELETE löscht Daten aus einer Tabelle, die mit einer WHERE – Klausel noch näher spezifiziert werden können. Mit dieser Anweisung kann eine Tabelle auch komplett geleert werden, wobei sie selbst aber erhalten bleibt. 9 UPDATE ändert Daten in einer Tabelle, wobei eine WHERE – Klausel eine Datenauswahl treffen kann. 9 Die WHERE – Klausel wird stets für die Beschreibung von Dateneigenschaften verwendet. Sie wird eingesetzt in Abfragen und Datenmodifikationen.
4.3.2
Übungen
1. Fügen Sie gemäß obiger Abbildung die letzten drei Datensätze von Tonalicht GmbH, Druckerei Setzling GmbH und Stadtwerke Willingen in die Tabelle unternehmen ein. Fügen Sie dabei die drei Datensätze gleichzeitig in die Tabelle ein. 2. Wie gehen Sie vor, wenn Sie für die Firma Tonalicht GmbH nur die Firmen-, nicht aber die Ansprechpartnerinformationen erfassen wollen? 3. Laden Sie folgende kommagetrennte Werte in die Tabelle teilnehmer.
82
SQL
DATEN
EINFÜGEN UND ÄNDERN
"1";"1";"Heinrich";"Schmidtler";"Hans-Strenkel-Weg";"11";"84569"; "Willingen";"0356-86259" "2";"1";"Ralf";"Ahrens";"Krogbuschweg";"28";"84570";"Wedelingen";"035762847" "3";"1";"Rainer";"Ahlgrin";"Landstraße";"6";"84571";"Sollbach";"035852688" "4";"1";"Roswita";"Bikelund";"Schwarzenbecker Weg";"27";"84569"; "Willingen";"0356-54317" "5";"1";"Hans-Josef";"Doberens";"Ellerbreite";"2";"84570"; "Wedelingen";"0357-52186" "6";"1";"Martin";"Gendner";"Humperdinckstraße";"30";"84571";"Sollbach";" 0356-86260" "7";"1";"Gabriele";"Gielbelsen";"Gusta-Lunthe-Straße";"1";"84569"; "Willingen";"0357-62848" 4. Löschen Sie die gesamte Tabelle termine. 5. Löschen Sie alle Teilnehmer aus Sollbach. 6. Löschen Sie alle Kurse, die günstiger sind als 250 Euro. 7. Löschen Sie alle Kurse, die laut der Tabelle termine in Düsseldorf stattfinden. 8. Alle Kurse in der Tabelle termine sollen in Düsseldorf stattfinden. 9. Die Kurspreise sollen alle um 30 % erhöht werden, wobei die Dauer um einen Tag verlängert werden soll. 10. Der Kurs mit der Kursnummer 30129 soll in Oberhausen stattfinden. 11. Die Kurse mit einer 2 als erster Ziffer sollen in Gelsenkirchen stattfinden. 12. Alle Kurse in Düsseldorf sollen um 30 Euro teurer werden.
SQL
83
DATEN
84
EINFÜGEN UND ÄNDERN
SQL
5 Grundstrukturen einfacher Abfragen
SQL
85
GRUNDSTRUKTUREN
86
EINFACHER
ABFRAGEN
SQL
GRUNDSTRUKTUREN
5 Grundstrukturen einfacher Abfragen
EINFACHER
ABFRAGEN
Lernen Sie die relationale Algebra kennen und mit ihr Abfragen zu verstehen und zu planen einfache Abfragen zu konstruieren die WHERE – Klausel mit Anweisungen zu füllen
Dies ist das erste von zwei Projekten zum Thema Abfragen. Es dürfte neben den Möglichkeiten, eine Datenbank einzurichten und Daten einzutragen bzw. zu ändern, ein gleichrangig wichtiges Thema sein. Wenn die Datenbank mit allen Tabellen bereits besteht, und man sich ihr aus Benutzer-Sicht nähert, stellen die Abfragen sogar die wichtigste Aufgabe dar. Da hier sehr viele Möglichkeiten existieren, die gefundenen Daten zu ordnen, zu sortieren oder sogar mit verschiedenen Funktionen für spezielle Zwecke aufzubereiten und auszuwerten, scheint es besser, zunächst die Grundstrukturen zu klären und danach weitergehende Anwendungen zu zeigen.
weiche und harte Operatoren einzusetzen gefundene Daten zu sortieren, zugruppieren, alphanumerisch zu ordnen
5.1 Übersicht über die relationale Algebra Zunächst sollten Sie sich mit der Theorie beschäftigen, die die Basis für die Tabellenoperationen bildet, die typischerweise bei der Benutzung mit einem DBMS vollzogen werden. Es handelt sich dabei um grafisch leicht zu interpretierende Grundoperationen, die auf der Mengenlehre beruhen, mit denen Sie (vom Prinzip her) beliebig komplizierte Abfragen (gerade auch über mehrere Tabellen hinweg) planen können. Für viele Abfragen, die nur immer eine einzige Tabelle betreffen oder die lediglich möglichst viele Informationen bzw. Daten mit einem niedrigen Aggregationsgrad ausgeben sollen, werden Sie natürlich nicht alle hier gezeigten acht Basisoperationen der relationalen Algebra nutzen, doch bei größeren Projekten wie z.B. Unternehmungsanwendungen wie ECommerce-Lösungen, die zusätzlich auf Schnelligkeit und leichte Wartbarkeit hin aufgebaut werden, lassen sich mit der Hilfe sämtlicher Basisoperationen leicht alle Abfragenstrukturen planerisch vollziehen. Sie basieren wie das gesamte relationale Datenmodell auf den Arbeiten von E.F. Codd. Sein Ziel war es u.a. ein besonders leicht nachvollziehbares System zu entwickeln, damit möglichst viele Menschen solchermaßen strukturierte Datenbanken nutzen können. ¾ Selektion Die Selektion stellt eine der beiden Grundformen für die häufigste Abfrage bereit, nämlich die horizontale Auswahl von Zeilen einer Tabelle. Wichtig ist hierbei, dass die Anzahl der Spalten des eingehenden Schemas und des ausgehendes Schemas (also der Tabellen) gleich bleibt. Die Auswahl erfolgt dabei über eine Bedingung,
SQL
87
GRUNDSTRUKTUREN
EINFACHER
ABFRAGEN
wie Sie sie bereits im letzten Kapitel in einer WHERE – Klausel vorgegeben haben. Damit stellt also die Selektion eine Untermenge gleichen Grades (gleicher Spaltenanzahl) der Obermenge dar. ¾ Projektion Eine Projektion stellt ebenfalls eine Auswahl aus einer Tabelle dar, dabei liegt die Betrachtung jedoch nicht primär auf den einzelnen Zielen, sondern vielmehr auf den Spalten. Die Kardinalität des Schemas bleibt also nicht erhalten. Die Ergebnisoder die Abfragetabelle wird mindestens eine Spalte weniger als die Original- oder Ursprungstabelle enthalten. Dabei dient als Auswahlkriterium wie immer mindestens eine Kondition, die in einer Spalte abgefragt wird und für die ausgewählten Datensätze zutrifft. ¾ Union (Vereinigung) Die Operation Union stellt eine Vereinigungsmenge aus zwei Relationen / Tabellen her. Dabei gilt, dass die beiden eingehenden Tabellen das gleiche Schema, also die gleiche Spaltenstruktur haben müssen. Ist diese Bedingung erfüllt, verläuft der Vorgang einfach durch ein Anhängen der Datensätze der einen Tabelle an die Datensätze der anderen Tabelle. Es entsteht also eine Tabelle mit den Datensätzen der beiden eingehenden Tabellen. ¾ Differenz (Differenzmenge) Die Differenz stellt das logische Gegenstück zur Vereinigung dar. Wiederum müssen die eingehenden Tabellen die Bedingung erfüllen, dass sie das gleiche Schema besitzen. Die Operation T1 – T2 der Differenzbildung verläuft dann so, dass nur die Datensätze in der Ergebnistabelle übrig bleiben, die zur Tabelle T1, aber nicht zur Tabelle T2 gehören. Pro Datensatz wird also ein Vergleich durchgeführt, wobei die Datensätze in T1 entfallen, die in T2 enthalten sind. Sie werden also abgezogen. Wie bei einer Differenzbildung mit Zahlen ist hier ebenfalls zu beachten, dass im Gegensatz zur Vereinigung die Operation nicht symmetrisch ist. Es ist also ein Unterschied, ob T1 von T2 oder T2 von T1 subtrahiert wird.
88
SQL
GRUNDSTRUKTUREN
EINFACHER
ABFRAGEN
¾ Schnittmenge Die Schnittmenge ist insoweit mit der Differenzmenge verwandt, als dass ebenfalls zwei Tabellen mit gleichem Schema aufgrund ihrer Datensätze miteinander verglichen werden. Dabei bleiben in der Ergebnistabelle die Datensätze übrig, die in beiden Tabellen vorhanden sind. Die Schnittmenge ist nicht wirklich eine Basisoperation, sondern setzt sich zusammen aus zwei Differenzen: T1 ∩ T2 = T1 – (T1 – T2) = T2 – (T2 – T1) ¾ Join (Verbund) Der Join stellt das Hilfsmittel dar, das zum Einsatz kommt, wenn Beziehungen zwischen den Tabellen über Fremdschlüssel bei einer Abfrage genutzt werden. Die Ergebnistabelle ergibt sich aus den beiden eingehenden Tabellen, indem ein Produkt der Felder gebildet wird, die die JoinBedingung erfüllen. In nebenstehendem Beispiel gelangt man zur Ergebnistabelle, indem die Zuordnungen verglichen werden. Da in T1 zum Feld a1 das Feld b1 gehört, gelangt in der Ergebnistabelle aus T2 das Feld c1 in die erste Reihe, da in T2 das Feld b1 (das ja auch in T1 vorhanden ist) zu c1 gehört. Gleich verhält es sich mit der zweiten und dritten Zeile, da hier wiederum eine Verbindung über b1 und über b2 besteht. Die vierte Zeile von T1 dagegen findet keine Entsprechung in T2, da b4 nur in T1 auftritt. Daher wird es nicht Teil der Ergebnistabelle. In dieser Konstruktion würde ein so genannter Natürlicher Join verwendet werden. ¾ Division Die Division stellt eine Operation dar, die auf zwei eingehende Tabellen angewandt werden kann, die einen Teil ihrer Daten gleich haben. Dabei wird eine Ergebnistabelle erzeugt, die Werte von T1 enthält, die nicht zu T2 gehören, aber als zugehörige Werte die von T1 enthalten. In nebenstehendem Beispiel gelangt man zur Ergebnistabelle, indem man in einem Datenvergleich feststellt, dass lediglich a und c von T1 gleichzeitig als zugeordnete Werte x und y aus T2 enthalten. Sie bleiben also übrig. Wie die Differenzmenge ist auch die Divisionsoperation nicht symmetrisch. Das Ergebnis wird sich also ggf. ändern, sobald die beiden Tabellen (Dividend und Divisor) vertauscht werden.
SQL
89
GRUNDSTRUKTUREN
EINFACHER
ABFRAGEN
¾ (Kartesisches) Produkt Ein Produkt aus zwei eingehenden Tabellen stellt die Tabelle dar, die eine Verknüpfung beider Wertemengen enthält, sodass sämtliche Kombinationsmöglichkeiten entstehen. In nebenstehendem Beispiel gelangt man also zur Ergebnistabelle, indem jeder Wert der Tabelle T1 (a, b, c) mit jedem Wert der Tabelle T2 (x, y) als Paar verknüpft wird. Da die Reihenfolge der Spalten im relationalen Datenmodell unerheblich ist, ergeben sich also 3 * 2 = 6 Kombinationsmöglichkeiten. Damit ist das kartesische Produkt eine Unterart des Verbunds, da hier ebenfalls zwei Tabellen miteinander verknüpft werden.
Im weiteren Verlauf des Buchs werden die drei unterschiedlichen Abfragetypen vorgestellt. Sie unterscheiden sich strukturell von den Relationen, die bisher behandelt wurden. Die bisherigen Basisrelationen wurden tatsächlich in der Form von Tabellen in der DB gespeichert. Abfragen stellen jedoch abgeleitete, virtuelle Relationen dar (es entstehen ja ebenfalls Tabellen), die aber nur zeitlich begrenzt (z.B. zur Laufzeit) existieren oder unveränderbar sind. Eine Abfrage stellt dabei eine Ergebnisrelation dar, die zur Laufzeit eines Programms oder eines Website-Besuchs erstellt und danach wieder gelöscht wird. Eine Sicht dagegen stellt eine abgespeicherte Abfrage dar, die beliebig oft und zu beliebigen Zeitpunkten aufgerufen werden kann. Dabei stellt diese Sichtrelation lediglich eine gespeicherte Folge von Datenbankoperationen dar, die ausgeführt eine Ergebnistabelle erzeugen. Mit Snapshot (Kurzaufnahme) bezeichnet man ganz bildlich eine einmalige Abfrage, die einmal aufgrund von Basisrelationen erstellt, abgespeichert und danach nie wieder geändert wird. Ein typisches Beispiel könnte die Erstellung einer Jahresbilanz sein, die aus rechtlichen Gründen natürlich nachträglich nicht geändert werden darf.
5.2 Grundstruktur der Abfrage Bereits die einfachste Abfragesyntax enthält verschiedene Optionen für Datensortierung und eine spezielle Datenausgabe. Folgende Syntaxübersicht soll dabei zunächst genügen: SELECT [ALL | DISTINCT] * | {spalte1 [, spalte2, ...]} FROM tabellennamen [WHERE suchbedingung] [ORDER BY [spalte1 [, spalte2, ...]] [ASC | DESC]]
90
SQL
GRUNDSTRUKTUREN
EINFACHER
ABFRAGEN
[GROUP BY [spalte1 [, spalte2, ...]] [ASC | DESC]] [HAVING gruppensuchbedingung] Folgende Abfragemöglichkeiten werden anhand dieser Syntax bereits deutlich: ¾ Eine Abfrage beginnt stets mit dem Befehl SELECT, gefolgt von einem der beiden Schlüsselwörter ALL oder DISTINCT, wobei ALL in den meisten DBS weggelassen werden kann, da es die Voreinstellung bedeutet. ALL liefert auch doppelte Einträge, während DISTINCT diese nicht anzeigt. Doppelte Einträge bedeutet hierbei nicht, dass in der Basisrelation doppelte Datensätze enthalten sind, sondern dass diese in der Abfrage auftreten können. ¾ Mit einem Asteriskus (*) oder einer Liste der benötigten Spaltennamen kann man entweder alle Spalten einer Tabelle oder eine bestimmte Auswahl in die Abfrage aufnehmen. ¾ Mit dem Schlüsselwort FROM wird dann bestimmt, welche Tabellen für die Abfrage benötigt werden. Da es hier zunächst nur um die Abfragen mit einer Tabelle gehen soll, beschränkt sich diese Liste auf einen einzigen Tabellennamen. ¾ Die WHERE – Klausel beschreibt nun mit verschiedenen Parametern die Kriterien, die für die Daten erfüllt sein müssen, damit sie in die Ergebnisrelation aufgenommen werden. ¾ Mit ORDER BY und GROUP BY kann man anhand einer oder mehrere Spalten eine alphanumerisch aufsteigende (ASC bzw. Standardeinstellung) oder absteigende (DESC) Sortierung vornehmen. ¾ Mit HAVING kann man weitere Bedingungen vorgeben, die allerdings nicht für die Zeilen, sondern für die Gruppen gelten, die in der GROUP BY – Klausel gebildet wurden. 1. Fragen Sie alle Daten einer Tabelle ab. Dabei verwenden Sie die Grundform aller Abfragen mit Hilfe des Asteriskus und der Nennung der Tabelle ohne eine weiter einschränkende WHERE – Klausel. Ein ALL ist hierbei nicht notwendig, da die meisten DBMS es als Standardwert verwenden. SELECT * FROM kurse SELECT ALL * FROM kurse 2. Suchen Sie alle Themen und Preise heraus. Hier benennen Sie ausdrücklich die benötigten Spalten in der Reihenfolge, in der die Ausgabe erfolgen soll. Wenn der Preis in der ersten Spalte hätte erscheinen sollen, wäre die Reihenfolge preis, titel notwendig gewesen. SELECT titel, preis FROM kurse SELECT preis, titel FROM kurse 3. Geben Sie nun innerhalb der WHERE – Klausel eine Bedingung vor, die prüft, ob der Preis größer als 500 Euro beträgt. Nur diese Kurse sollen ausgegeben werden.
SQL
91
GRUNDSTRUKTUREN
EINFACHER
ABFRAGEN
SELECT titel, preis FROM kurse WHERE preis > 500
Die Abfragenergebnisse werden nicht immer mit einer Grafik dargestellt, sondern nur, soweit nicht unnötig Platz verbraucht wird. Wir haben sie alle in einer Web-Seite mit Hilfe eines kleinen PHP-Programms automatisch ausgeben und formatieren lassen. Sie selbst können die Abfragen mit MySQL direkt in MySQL Front, mit dem MS SQL Server im Query Analyzer oder in Oracle im SQL*Plus Worksheet eingeben. Insbesondere die komplexen Abfragen können Sie nur mit den beiden zuletzt genannten Testumgebungen ausführen.
4. Die Besonderheit der Unterscheidung zwischen ALL und DISTINCT liegt also darin, dass DISTINCT doppelte Datensätze in der Ergebnisrelation ausblendet. Doppelte Datensätze können vor allen Dingen dann eintreten, wenn in einer oder mehreren Spalten gleiche Werte auftreten. Um also eine Übersicht über alle Kursbereiche zu erhalten, benötigt man lediglich eine Ausgabe der überhaupt in der Tabelle vorliegenden Bereiche und nicht zusätzlich die Information, wie viele Kurse zu jedem Bereich vorliegen. Das wäre – nebenbei gesagt – eine andere Abfrage. SELECT DISTINCT bereich FROM kurse
Die Abfragen dieses Abschnitts finden Sie in der Datei kurse_abfragen.sql.
5. Verwenden Sie nun als Gruppierungsbedingung die ORDER BY – Klausel. Im Ergebnis werden die Datensätze - nach Bereichen gruppiert - in der Reihenfolge ausgegeben, wie sie in der Tabelle vorhanden sind. Automatisch wird dabei der Bereichsname alphabetisch aufsteigend sortiert. SELECT titel, bereich FROM kurse ORDER BY bereich 6. Wenn Sie zusätzlich die Titel alphabetisch aufsteigend sortieren wollen, hängen Sie diese neue Sortierungsoption hinten an die Abfrage an. Dies betrifft die Spalte titel mit der Option ASC.
92
SQL
GRUNDSTRUKTUREN
EINFACHER
ABFRAGEN
SELECT titel, bereich FROM kurse ORDER BY bereich, titel ASC 7. Vergleichen Sie nun die Auswirkungen der GROUP BY – Klausel. Sie zeigt jeweils nur den ersten Datensatz, für den ein Bereich in der Tabelle erscheint. Da dieser Befehl nur mit Unterabfragen wirklich Sinn macht und dort sehr schöne Ergebnisse erzielt, wird er im nächsten Projekt detailliert dargestellt. Beim MS SQL Server muss titel ebenfalls in der Gruppierung angegeben werden. SELECT titel, bereich FROM kurse GROUP BY bereich
5.3 Operatoren der WHERE – Klausel Bis jetzt waren die Abfragen bzw. die Bedingungen innerhalb der WHERE – Klausel ganz intuitiv immer auf die Gleichheit von Vorgabenwert und Feldwert ausgerichtet. Stattdessen gibt es eine ganze Reihe von Operatoren, die für die Verkettung einzelner WHERE – Klauseln gelten, und andere, die innerhalb der Klausel die Datenabfragen steuern. Dabei ergeben sich im einfachen Gleichheitsfall WHERE = 25102 folgende Wahrheitswerte: ¾ TRUE, wenn die Bedingung erfüllt ist ¾ FALSE, wenn die Bedingung nicht erfüllt ist ¾ UNKNOWN, wenn die Spalte den Wert NULL enthält
5.3.1 Boolesche Funktionen und logische Operatoren Mit Hilfe der booleschen Funktionen AND (logisches UND, Konjunktion), OR (logisches ODER, Disjunktion) und der Negation (NOT) können WHERE – Klauseln miteinander verbunden werden, sodass z.B. ein Datensatz in die Ergebnistabelle eingetragen wird, wenn (wie bei OR) eine von beiden Bedingungen erfüllt ist. Zusätzlich ist es möglich, mit Hilfe dieser Schlüsselwörter Bedingungen innerhalb einer WHERE – Klausel miteinander zu verknüpfen, sodass auch hier mehr Spielraum möglich wird.
SQL
93
GRUNDSTRUKTUREN
EINFACHER
ABFRAGEN
1. Zwei Bedingungen in einer WHERE – Klausel werden durch das Wort AND verbunden. Dabei ist die Bedingung genau dann erfüllt, wenn beide einzelnen Bedingungen zutreffen. SELECT titel, preis, dauer FROM kurse WHERE
dauer > 2
AND preis < 800 2. Das Gegenteil ergibt das Wort OR. Hier reicht es, wenn eine von beiden Bedingungen zutrifft. Daher ist bei der gleich strukturierten Abfrage die Liste wesentlich länger. SELECT titel, preis, dauer FROM kurse WHERE OR
dauer > 2 preis < 800
3. Mit NOT schließen Sie diejenigen Datensätze aus, die gerade nicht die Bedingung der NOT – Funktion erfüllen. SELECT titel, preis, dauer FROM kurse WHERE
NOT dauer = 2
4. Eine weitere Möglichkeit ergibt sich, wenn innerhalb der WHERE – Klausel mehrere Bedingungen durch diese booleschen Funktionen verknüpft werden. SELECT titel, preis, dauer FROM kurse WHERE (dauer > 2 AND dauer <4)
Die Abarbeitung der drei Funktionen bzw. der Test auf ihre Bedingungen hin verläuft in der Reihenfolge NOT, AND und OR. Das bedeutet, dass in einem Fall, wo alle drei Ausdrücke existieren, in dieser Reihenfolge die einzelnen Tests durchgeführt und die Ergebnisrelation zusammengesetzt wird. Möchte man hingegen eine andere Reihenfolge einrichten, fasst man zusammengehörige Bereiche durch runde Klammern zusammen.
Zum Abschluss zeigen wir Ihnen noch die Wahrheitstabellen für die in diesem Abschnitt präsentierten Operatoren. Sie verdeutlichen das gemeinsame bzw. das gesamte Ergebnis im Vergleichsfall. ¾ Wahrheitstabelle für AND
94
SQL
GRUNDSTRUKTUREN
EINFACHER
ABFRAGEN
Die drei Grundfälle von AND bestimmen sich so: TRUE wird zurückgeliefert, wenn beide Operanden TRUE zurückliefern. FALSE wird zurückgeliefert, wenn einer von beiden Operanden den Wert FALSE zurückliefert. UNKNOWN wird zurückgeliefert, wenn einer von beiden Operanden UNKNOWN zurückliefert. Das erste gemeinsame Ergebnis im Fall TRUE/TRUE bestimmt sich mit folgender Überlegung: Eine Abfrage mit zwei gleichzeitig zutreffenden Suchkriterien ist nur dann wahr und liefert auch nur dann ein Tupel in die Ergebnisrelation, wenn beide Einzelbedingungen zutreffen. Daher ist das gemeinsame Ergebnis TRUE. AND
TRUE
FALSE
UNKNOWN
TRUE
TRUE
FALSE
UNKNOWN
FALSE
FALSE
FALSE
FALSE
UNKNOWN UNKNOWN FALSE
UNKNOWN
Tab.1: Wahrheitstabelle für AND ¾ Wahrheitstabelle für OR Die drei Grundfälle von OR bestimmen sich so: TRUE wird zurückgeliefert, wenn einer von beiden Operanden TRUE zurückliefert. FALSE wird zurückgeliefert, wenn beide Operanden FALSE zurückliefern. UNKNOWN wird zurückgeliefert, wenn einer von beiden Operanden UNKNOWN zurückliefert. Für OR reicht es, wenn eines von beiden Suchkriterien zutrifft, damit ein Tupel in die Ergebnisrelation übernommen wird oder das gemeinsame Ergebnis TRUE ist. Der erste Fall mit TRUE/TRUE entspricht also dem ersten Fall für AND. Interessant ist dagegen der zweite Fall für TRUE/FALSE, da hier für AND der Wert FALSE zurückgeliefert wird, aber im Fall von OR dagegen TRUE. Um TRUE zu erzeugen, genügt es für OR, wenn eines von beiden Suchkriterien erfüllt wird. Dies ist bei TRUE/FALSE eindeutig der Fall. AND hat eine höhere Wertigkeit als OR, sodass folgende beide Ausdrücke äquivalent sind: a OR b AND c ⇔ a OR (b AND c) OR
TRUE
FALSE
UNKNOWN
TRUE
TRUE
TRUE
TRUE
FALSE
TRUE
FALSE
UNKNOWN
UNKNOWN TRUE
UNKNOWN UNKNOWN
Tab.2: Wahrheitstabelle für OR ¾ Wahrheitstabelle für NOT Im Fall von NOT kehrt sich das Ergebnis immer um, da gerade der Fall des Zutreffens nicht gesucht wird. Wird also TRUE zurückgeliefert, so ist die Negation richtig bzw. alles falsch. NOT TRUE
FALSE
FALSE
TRUE
UNKNOWN
UNKNOWN
SQL
95
GRUNDSTRUKTUREN
EINFACHER
ABFRAGEN
Tab.3: Wahrheitstabelle für NOT
5.3.2 Vergleichsoperatoren Bis jetzt haben Sie bereits auf Gleichheit und Ungleichheit geprüft, ohne dass es einer speziellen Erklärung bedurft hätte. Daher beschränken wir uns im Folgenden auf eine knappe Vorstellung der restlichen Möglichkeiten, Vergleiche von Werten durchzuführen. ¾ Prüfung auf Gleichheit: SELECT titel, preis FROM kurse WHERE preis = 1000 SELECT titel, preis FROM kurse WHERE titel= "SQL" ¾ Prüfung „kleiner als“: SELECT titel, preis FROM kurse WHERE preis < 1000 ¾ Prüfung „größer als“: SELECT titel, preis FROM kurse WHERE preis > 1000 ¾ Prüfung „größer gleich“: SELECT titel, preis FROM kurse WHERE preis >= 1000 ¾ Prüfung „kleiner gleich:“ SELECT titel, preis FROM kurse WHERE preis <= 1000 ¾ Prüfung „ungleich“: SELECT titel, preis FROM kurse WHERE preis <> 920 Neben den Zahlen lassen sich auch andere Datentypen auf (Un-)Gleichheit überprüfen. Bei Buchstaben werden die Werte der ASCII-Tabelle genommen, sodass also ein „kleinerer“ Buchstabe einen kleineren Wert in der ASCII-Tabelle besitzt. Für Daten gilt, dass ein Datum kleiner als ein anderes ist, wenn es älter ist, das Ereignis also länger zurückliegt.
96
SQL
GRUNDSTRUKTUREN
EINFACHER
ABFRAGEN
Der MS SQL Server lässt darüber hinaus auch Abfragen mit !< („nicht kleiner“) und !> („nicht größer“) zu.
Abgesehen von diesen intuitiv zu benutzenden Operatoren, die in Programmiersprachen auch immer eingesetzt werden, gibt es einige SQL-spezifische Operatoren, die ebenfalls für den Vergleich zum Einsatz kommen. Mit Hilfe der Operatoren BETWEEN und IN kann man sehr differenzierte Vergleiche ausführen, die spezielle Mengen- und Zeichenvergleiche ausführen. Dabei prüft BETWEEN, ob Werte in einem vorgegebenen Bereich (Preis zwischen 800 und 1000) liegt, während IN prüft, ob Werte in einer bestimmten Werteliste (Titel wie PHP, SQL oder Java) vorliegen. Zusätzlich dient er als Schlüsselwort für den Einsatz von Unterabfragen. 1. Geben Sie die beiden Grenzen des abzufragenden Bereichs direkt nach dem Vergleichsoperator vor und verbinden Sie sie durch AND. Wie Sie in nebenstehender Abbildung erkennen, werden bei der Prüfung die beiden Grenzen eingeschlossen, tauchen also als Ergebnis auf. SELECT titel, preis FROM kurse WHERE preis BETWEEN 600 AND 800 2. Fragen Sie dagegen einen festen Wertebereich ab, indem Sie die Werte (bei Zeichenketten mit Redezeichen) in eine Klammer nach dem Vergleichsoperator schreiben. SELECT titel, preis FROM kurse WHERE titel IN ("SQL", "PHP", "Java") 3. Diese Operatoren können natürlich auch mit den anderen Vergleichsoperatoren kombiniert werden, sodass man nur die Kurse abfragen könnte, die entweder nicht SQL, PHP oder Java als Thema haben oder (wahlweise) einen Preis zwischen 600 und 800 Euro haben sollen. Die Ergebnisrelation soll dann zusätzlich alphabetisch nach dem Titel und innerhalb des Titels (es gibt ja mehrere Kursstufen pro Thema) nach dem Preis sortiert werden. SELECT titel, preis FROM kurse WHERE titel NOT IN ("SQL", "PHP", "Java") OR preis BETWEEN 600 AND 800 ORDER BY titel ASC, preis DESC Um etwas weitergehend in die Datensatzprüfung einzusteigen, kann man mit Hilfe des LIKE – Operators, der bereits im vorherigen Kapitel für das Beispiel einer Unterabfrage aufgetreten ist, die Zeichenketten des vorgegebenen Feldes untersuchen. Dabei vollzieht LIKE einen Mustervergleich anhand der Syntax für reguläre Ausdrücke, die in Programmiersprachen allgemein üblich ist. Für den Einsatz auf den unterschiedlichen DBMS kann es also neben den hier vorgestellten Möglichkeiten immer auch von Erfolg gekrönt sein, komplizierteste reguläre Ausdrücke für einen Testlauf einzusetzen, da gerade textbasierte Datenbanken mit solchen Ausdrücken natürlich wesentlich besser oder überhaupt erst durchsucht werden können als mit {<,>,<=, ...}.
SQL
97
GRUNDSTRUKTUREN
EINFACHER
ABFRAGEN
Die Grundstruktur der Abfrage besteht dabei aus folgenden Bestandteilen: WHERE spaltenname [NOT] LIKE ’muster’ Die Unterstützung von regulären Ausdrücken ist unterschiedlich geregelt, sodass die folgende Tabelle nicht immer umgesetzt werden kann. Zeichen
Bedeutung
Beispiel
Ergebnis
%
ersetzt beliebig vie- P% le Zeichen
findet PHP, Python, Perl
_
ersetzt genau ein PH_ Zeichen
findet PHP
[ ]
ersetzt ein Zeichen S[Q-U]% aus dem Bereich
findet SQL, Suchmaschinenoptimierung, aber nicht Server
^
negiert die Aus- ^P% wahl, kehrt die Auswahl um
findet Java, C++, aber nicht PHP, Python oder Perl
Tab.1: Reguläre Ausdrücke, die von einigen DBMS unterstützt werden Ein Spezialfall der Abfrage ergibt sich natürlich sofort, wenn die Platzhalter selbst ein Teil des Musters darstellen wie z.B. bei Prozentzahlen oder Bezeichnungen (von Dateien, Variablen usw.) mit Unterstrichen. In diesem Fall erweitert sich die allgemeine Syntax auf die folgende Form: WHERE spaltenname [NOT] LIKE ’muster’ ESCAPE zeichen 1. Um also Kurse abzufragen, deren Titel mit einem „S“ als erstem Buchstaben beginnen, benötigt man "S%". Dabei steht das Prozentzeichen für alle anderen, beliebig vielen Zeichen, die dem S folgen. Im Ergebnis findet man die beiden Kurse „SQL“ und „Suchmaschinenoptimierung“. SELECT titel, preis FROM kurse WHERE titel LIKE "S%"
98
SQL
GRUNDSTRUKTUREN
EINFACHER
ABFRAGEN
2. Die Anzahl der Buchstaben bleibt dabei beliebig. Es wird immer ein Vergleich mit dem vorgegebenen Muster durchgeführt. SELECT titel, preis FROM kurse WHERE titel LIKE "Jav%" 3. Der Unterstrich dagegen ersetzt nur genau ein alphanumerisches Zeichen. Daher wird bei einer Abfrage wie "Jav_" nur der Kurs Java gefunden, während bei "Jav%" alle möglichen Kurse im Ergebnis erscheinen, die die Zeichenkette Jav am Anfang im Titel tragen. SELECT titel, preis FROM kurse WHERE titel LIKE "Jav_" 4. Wenn die folgende Suche auch für dieses Datenmodell wenig Sinn macht, für eine linguistische Forschungsarbeit über typische E-Mail-Adressen könnte sie nützlich sein: E-Mail-Adressen haben oftmals Unterstriche, sodass man alle E-Mail-Adressen der Firmenansprechpartner zählen lassen könnte, die einen solchen Unterstrich besitzen. Das Zeichen für die Auskommentierung soll in diesem Fall ein Schrägstrich sein, der dann genau vor das zu auskommentierende Zeichen gesetzt wird. SELECT COUNT(anspremail) FROM unternehmen WHERE anspremail LIKE '%/_%' ESCAPE '/' Folgende Beispiele sollen die Grundstruktur des Mustervergleichs noch einmal verdeutlichen, wobei das Ergebnis als Wahrheitswert ausgegeben wird. Beispiel
Muster
Ergebnis
xyz
_y_
TRUE
xyz
_y
FALSE
xyz
%y%
TRUE
xy
%y
TRUE
xy
xy_
FALSE
xy
y%
TRUE
xyz
x%_
TRUE
xy
x%_
TRUE
SQL
99
GRUNDSTRUKTUREN
EINFACHER
ABFRAGEN
Tab.2: Beispiele für Vergleiche
5.3.3 Berechnungen mit numerischen Operatoren und Vorzeichen Werte können wie beim Aktualisierungsvorgang auch mit mathematischen Operationen verknüpft werden, indem Addition, Subtraktion, Multiplikation und die Division über die Zeichen +, -, * und / in der WHERE – Klausel vorgegeben wird. Dabei ändern sich natürlich die Werte in der Basisrelation selbst nicht, sondern werden lediglich anhand des errechneten Werts in die Ergebnisrelation eingetragen. Die Berechnung dient also wie sonst auch dem Prüfkriterium, ob ein Datensatz in die Ergebnisrelation gerät oder nicht. 1. Um also zu überprüfen, welche Kurse mehr als 1000 Dollar kosten, wenn der Kurs für einen Euro bei 0,92 Dollar liegt, muss diese Umrechnung innerhalb der WHERE – Klausel mit preis*0.92 erfolgen. Wie sonst auch, folgt danach das eigentliche Vergleichskriterium. SELECT titel, preis FROM kurse WHERE preis*0.92 > 1000 2. Die Berechnung kann auf beiden Seiten des Vergleichs erfolgen. Um herauszufinden, welche Kurse mit einem Rabattprogramm von 25 % bei 3 Teilnehmern von einer Firma günstiger sind, als wenn pauschal 800 Euro abgezogen werden, berechnet sich, indem beide Varianten vor und nach dem Vergleichsoperator eingetragen werden. Das Ergebnis entspricht dem der vorherigen Abfrage. Darüber hinaus erkennt man an diesem Beispiel, dass Punkt- vor Strichrechung abgearbeitet wird und daher keine Klammern im zweiten Term notwendig sind. SELECT titel, preis, dauer FROM kurse WHERE preis*3*0.75 < preis*3-800 3. Obwohl es das Abfrageergebnis nicht beeinflusst, müssen bei der Berechnung der DollarPreise Klammern gesetzt werden, da sonst natürlich Fehler auftreten: SELECT titel, preis, dauer FROM kurse WHERE (preis*3*0.75)*0.92 < (preis*3-800)*0.92
100
SQL
GRUNDSTRUKTUREN
EINFACHER
ABFRAGEN
5.4Abfrage des Werts NULL Eine Besonderheit stellt die Abfrage nach NullWerten dar, für die spezielle Operatoren existieren. Eine Abfrage mit den zuvor vorgestellten Operatoren ist daher nicht erfolgreich, sondern kann nur mit IS [NOT] NULL oder MATCH erfolgen. Dabei prüft IS [NOT] NULL genau auf die Existenz eines Null-Wertes, während MATCH dagegen einerseits die Abfrage mit IN ersetzt, andererseits jedoch die Möglichkeit eröffnet, ebenfalls auf NULL zu überprüfen. Dabei gibt es unterschiedliche Parameter, die diese Überprüfung zusätzlich flexibel gestalten. Da MATCH zusammen mit Unterabfragen eingesetzt wird, folgt die Darstellung im nächsten Projekt.
Die Tabellendefinitionen und die Aktualisierung finden Sie in der Datei tbl_kurse.sql.
Sollten Sie die hier gezeigten Befehle an einer realen Datenbank nachvollziehen, können Sie sich die leeren Zeilen in der Tabelle kurse durch den Befehl UPDATE kurse SET vorkenntnisse = NULL WHERE vorkenntnisse IN ("Grundlagen in Windows", "keine", "Grundlagen Windows") erzeugen. Es müssten dann insgesamt 12 Zeilen gelöscht werden. An diesem Beispiel sollen zusätzlich sehen, dass die in diesem Kapitel vorgestellten Konzepte nicht nur für die SELECT – Anweisung reserviert sind, sondern vielmehr für die WHERE – Klausel bestimmt sind. Diese taucht natürlich auch bei Aktualisierungen und Löschungen auf.
Im SQL-Standard werden die hier dargestellten Operatoren BETWEEN, EXISTS, IS NULL, LIKE, MATCH, OVERLAPS und UNIQUE als Prädikate behandelt und bezeichnet. Sie prüfen in Wirklichkeit (also laut Standard) nur, ob die in den Prädikaten getroffenen Aussagen wahr, falsch oder unbekannt (true, false, unknown) sind und liefern keine Ergebnisrelationen. In DBMS dagegen werden sie für die Verfeinerung der WHERE – Klausel benutzt und werden im Fall von SELECT auch ausgegeben.
SQL
101
Die Funktion IS [NOT] NULL prüft – wie der Name schon vermuten lässt – ausschließlich auf die Existenz oder Nicht-Existenz eines Nullwertes innerhalb eines Datensatzes. 1. Verwenden Sie diese Funktion in ihrer Grundform einfach in der WHERE – Klausel wie die anderen Operatoren. Tatsächlich werden genau die 12 Datensätze gefunden, aus denen wie in der Einleitung die belanglosen Vorkenntnis-Informationen gelöscht wurden. SELECT titel, preis FROM kurse WHERE vorkenntnisse IS NULL 2. Im gegenteiligen Fall werden alle anderen Kurse gefunden. SELECT titel, preis FROM kurse WHERE vorkenntnisse IS NOT NULL
5.5 Abfragen miteinander verknüpfen Die ganz zu Anfang dieses Projekts beschriebenen Verfahren der relationalen Algebra haben sich in den Mengenoperatoren niedergeschlagen, die mehrere, unabhängige Abfragen miteinander verknüpfen. Dabei müssen jeweils unterschiedliche Voraussetzungen für die eingehenden Tabellen erfüllt sein, damit die Abfrage keine Fehlermeldung hervorruft. A propos Fehlermeldung: Wie Sie gleich sehen werden, können viele Abfragen auch mit anderen Mitteln gebildet werden, sodass viele Datenbanksysteme die Mengen-Operatoren noch nicht implementiert haben.
5.5.1 Vereinigungsmenge von Tabellen Zwei Abfragen können mit dem Operator UNION so verknüpft werden, dass die jeweils entstehenden Ergebnisrelationen in einer gemeinsamen Tabelle ausgegeben werden. Dabei müssen beide Abfragen das gleiche Schema (Spaltenstruktur) aufweisen, damit die beiden Tabellen tatsächlich so miteinander verbunden werden, dass die Ergebnisse der zweiten Abfrage direkt an die Ergebnisse der ersten angeschlossen werden. Beachten Sie folgende Regeln für den Umgang mit diesem Befehl und den anderen: ¾ übereinstimmende Spaltenanzahl in den SELECT – Klauseln
102
SQL
¾ Sortierung mit ORDER BY muss für die letzte Abfrage spezifiziert werden und wirkt sich auf die gesamte Ergebnisrelation aus ¾ DISTINCT darf nicht eingesetzt werden, da Duplikate ohnehin automatisch entfernt werden; dies gilt auch für den Wert NULL, der für Mengen-Operatoren als ein spezieller Wert gilt ¾ nur UNION ALL belässt Duplikate im gesamten Abfrageergebnis 1. Alle Kurse mit einer Dauer von mehr als oder gleich drei Tagen und alle Kurse mit einer Dauer von weniger als zwei Tagen sollen zusammengefasst werden. SELECT titel, preis, dauer FROM kurse WHERE dauer>=3 UNION SELECT titel, preis, dauer FROM kurse WHERE dauer<2 2. In diesem Fall besteht die Möglichkeit, die Vereinigung beider Ergebnisrelationen durch den OR-Operator direkt in der ersten Abfrage zu erzeugen. SELECT titel, preis, dauer FROM kurse WHERE dauer>=3 OR dauer<2 3. Um sich tatsächlich alle Datensätze inklusive Duplikate anzuschauen, muss man den Operator UNION ALL einsetzen, der die standardmäßige Ausblendung wieder aufhebt. SELECT teilnnr FROM buchungen WHERE teilnnr<5 UNION ALL SELECT teilnnr FROM teilnehmer WHERE teilnnr<5
5.5.2 Schnittmenge Die mit INTERSECT gebildete Schnittmenge erzeugt aus zwei Abfrageergebnissen eine Ergebnisrelation, welche genau die Datensätze enthält, welche in beiden einzelnen Abfragen vorhanden sind. Dabei fallen Duplikat ebenfalls aus der Betrachtung heraus, so lange man nicht INTERSECT ALL einsetzt.
SQL
103
1. In einer ersten Abfrage fragt man nur Teilnehmer mit einer Teilnehmernummer kleiner als 15 ab, während eine zweite Abfrage diejenigen aus Sollbach ermittelt. Beide Abfragen zusammen ergeben dann eine Schnittmenge, wenn sie Teilnehmer enthält, auf die beide Merkmale zutreffen. SELECT teilnnr, teinnachname, teilnstadt FROM teilnehmer WHERE teilnnr<15 INTERSECT SELECT teilnnr, teilnnachname, teilnstadt FROM teilnehmer WHERE teilnstadt="Sollbach" 2. Diese Abfrage ist äquivalent zu einer Abfrage, welche die zweite Bedingung mit Hilfe des AND – Operators in die WHERE – Klausel integriert. SELECT teilnnr, teilnnachname, teilnstadt FROM teilnehmer WHERE teilnstadt="Sollbach" AND teilnnr<15 3. Doppelte Datensätze blendet der UNION – Operator aus, sodass UNION ALL benutzen muss, um die Duplikate ebenfalls zu sehen. SELECT untnr, teilnstadt FROM teilnehmer WHERE teilnnr<15 INTERSECT ALL SELECT untnr,teilnstadt FROM teilnehmer WHERE teilnstadt="Sollbach"
5.5.3 Differenzen zwischen Tabellen Aus der mathematischen Mengentheorie wissen Sie vielleicht, dass die Reihenfolge der Tabellen, die Vereinigungsmenge und die Schnittmenge bilden, uninteressant für das Ergebnis ist. Es gilt in diesen beiden Fällen das Kommutativgesetz (Vertauschungsgesetz). Die Menge der resultierenden Datensätze ist stets die gleiche, unabhängig davon, ob erst die Dauer größer gleich drei Tagen oder erst die Dauer kleiner zwei Tagen abgefragt wird. Daher konnte man diese beiden speziellen Abfragen, die sich auch auf die gleiche Tabelle bezogen, mit anderen Operatoren umschreiben. Die Differenzmenge, die über den Operator EXCEPT erzeug t wird, verhält sich in Bezug auf Vertauschungen innerhalb der Reihenfolge dagegen anders. Eine Differenzmenge ist die Menge der Tupel, die in Tabelle A gemäß dem Suchkriterium erscheinen, welche aber gleichzeitig nicht in Tabelle B erscheinen. Dabei werden auch hier eventuelle Duplikate entfernt. Man kann sie nur im Fall der Verwendung von EXCEPT ALL sehen.
104
SQL
Die Entwicklung einer Differenzmenge soll im folgenden Beispiel auch mit den eingehenden Ergebnistabellen betracht werden. 1. Gesucht werden zunächst alle Teilnehmer, die in Unternehmen mit der Unternehmensnummer 2 arbeiten. Die simple Abfrage erzeugt die untenstehende Tabelle mit Mitarbeitern dieses Unternehmens und verschiedenen Wohnstätten. SELECT teilnnr, untnr, teilnnachname, teilnstadt FROM teilnehmer WHERE untnr=2 2. Genau die Wohnstätte sollen nun weiter ausgefiltert werden. Man möchte also alle Mitarbeiter abziehen, die nicht in Sollbach wohnen. Dieses Mal entsteht eine Tabelle mit wesentlich mehr Datensätzen, da ja keine Einschränkungen bei den Unternehmen getroffen wurde. Direkt nach den Datensätzen für die Unternehmensnummer 1 folgen die Datensätze für die Unternehmensnummer 2, die bei teilnstadt nicht den Inhalt Sollbach besitzen. Für eine Analyse der Funktionsweise der Differenzmenge vergleichen Sie besonders, was z.B. mit Herrn oder Frau Kahsen aus Willingen geschieht. Er arbeitet im oben gesuchten Unternehmen und wohnt in Willingen. [EXCEPT] SELECT teilnnr, untnr, teilnnachname, teilnstadt FROM teilnehmer WHERE teilnstadt<>"Sollbach" 3. Wird die Abfrage komplett ausgeführt oder in der unten angegebenen Alternative verwendet, verschwindet Herr oder Frau Kahsen aus Willingen aus der endgültigen Ergebnistabelle. Übrig bleibt also in der Tat und gemäß Definition exakt die Datensätze aus Tabelle A, die nicht in Tabelle B waren. SELECT teilnnr, untnr, teilnnachname, teilnstadt FROM teilnehmer WHERE untnr=2 AND NOT(teilnstadt<>"Sollbach") Kombinationen von Mengen-Operatoren sind ebenfalls möglich. Standardmäßig werden auch bei mehreren miteinander verbundenen Abfragen die einzelnen Abschnitte sukzessive von oben nach
SQL
105
unten abgearbeitet. Möchte man jedoch die Reihenfolge beeinflussen und insbesondere spezielle Kombinationen einrichten, so muss man die zusammengehörigen Abfragen durch runde Klammern zusammenfassen. Dann geht das Ergebnis des geklammerten Blocks in die nächsthöhere Ebene der Abfrage ein.
5.5.4
Zusammenfassung
9 Abfragen können mit Hilfe der relationalen Algebra (grafisch) veranschaulicht werden. Die Befehle von SQL bilden dabei indirekt die Konzepte der relationalen Algebra ab. 9 Der grundlegende Befehl für alle Abfragen ist SELECT. Danach werden die benötigten Spalten der Spalten der Tabelle aufgerufen oder über das Sternchen (*) alle ausgewählt. 9 Mit Hilfe von FROM ruft man die Tabelle auf, aus der die Spalten benutzt werden sollen. 9 Wie in allen anderen Fällen, in denen Bedingungen oder Suchkriterien in Spalten vorgegeben werden sollen, bestimmt man diese Suchkriterien in der WHERE – Klausel. Sie ist damit das zentrale Element für die Vorgabe von Kriterien wie z.B. auch dem Löschen oder Aktualisieren. 9 Innerhalb der WHERE – Klausel helfen verschiedene Operatoren für Vergleiche oder mathematische Berechnungen bei der Konstruktion der Bedingung. Neben den Vergleichsoperatoren gibt es noch weitere Operatoren wie z.B. IN und BETWEEN, wobei IN auf eine Werteliste hin prüft und BETWEEN ein Intervall vorgibt. 9 Für die Überprüfung auf den Wert NULL gibt es eine spezielle Funktion: IS [NOT] NULL.
5.5.5
Übungen
1. Geben Sie für sämtliche Datensätze die Spalten titel, preis und vorkenntnisse aus. 2. Geben Sie nur die Datensätze mit den genannten Spalten aus, die länger als drei Tage dauern. 3. Welche Kurspreise liegen zwischen 300 und 600 Euro? Geben Sie die Spalten titel und preis aus. 4. Geben Sie die Informationen zu den Kursen Flash, XML und SQL aus, wobei Sie mindestens zwei Varianten für diese Abfrage finden sollten.
106
SQL
5. Welche Kurse haben eine Mehrwertsteuer von über 250 Euro? Die Daten in der Tabelle stellen Preise ohne MwSt. dar. Geben Sie die Spalten titel und preis aus. 6. Finden Sie die Kurse mit den Spalten titel, preis und dauer heraus, die nach einer 30prozentigen Preiserhöhung inkl. Mehrwertsteuer mehr als 1000 Euro kosten. 7. Welche Kurse sind länger als drei Tage, wenn alle Kurse um einen Tag erhöht werden? 8. Welche Kurse sind Teil III einer Kursfolge? 9. Welche Kurse haben als zweiten und dritten Buchstaben die Zeichenfolge „av“? 10. Welche Kurstitel fangen mit einem Großbuchstaben an?
SQL
107
108
SQL
6 Komplexe Abfragen, Unterabfragen und Funktionen
SQL
109
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
110
UND
FUNKTIONEN
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
6 Komplexe Abfragen, Unterabfragen und Funktionen Während die Grundstruktur der im vorherigen Projekt gezeigten Syntax nur für eine Tabelle nützlich ist, kann man sie mit einfachen Mitteln erweitern, um mehrere Tabellen in eine Abfrage zu übernehmen oder Unterabfragen zu gestalten. Dies kann dann noch zusätzlich mit verschiedenen statistischen Funktionen kombiniert werden, die in unterschiedlichen DBMS unterschiedlich umfangreich gestaltet sind.
UND
FUNKTIONEN
Lernen Sie: mehrere Tabelle gleichzeitig abzufragen mehrere Tabellen über ihre (Fremd-) Schlüssel zu verbinden Aggregatfunktionen für kleine statistische Analysen des Ergebnisses zu verwenden Unterabfragen in Abfragen zu verwenden und mit speziellen Operatoren diese Unterabfragen zusätzlich abzufragen Unterabfragen als skalare Ausdrücke einzusetzen
6.1 Mehrere Tabellen abfragen Im relationalen Datenmodell befinden sich die Daten in mehreren Tabellen, die wiederum teilweise über Primärschlüssel-Fremdschlüssel-Beziehungen verbunden sind. Dies zwingt dazu, bei Informationen, die sich auf mehrere Tabelle verteilen, genau diese Tabellen miteinander für eine Abfrage zu verknüpfen. Die folgenden Abschnitte zeigen das Grundprinzip wie die tatsächliche Anwendung auf.
6.1.1 Grundprinzip und Bedeutung der Fremdschlüssel Die Technik, mit der mehrere Tabellen abgefragt werden können, fußt auf den Bedingungen, die das relationale Datenmodell durch die Verteilung von Daten in mehreren Tabellen aufstellt. Da die Entwicklung des Datenmodells für die Firma SemiTex schon einige Seiten her ist, finden Sie es in rechts stehender Abbildung noch einmal. Jetzt soll es nicht noch einmal um eine Analyse gehen, sondern lediglich das Augenmerk auf die Gestaltung von Abfragen gerichtet werden. Dies soll dann nachher helfen, die einzelnen Abfragen zu verstehen. Zusätzlich werden in den nächsten Abbildungen die einzelnen Tabellen mit ihren bisherigen Inhalten gezeigt.
SQL
111
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
Die Inhalte der Tabellen buchungen und teilnehmer dieses Abschnitts finden Sie in der Datei tbl_buchungen.sql und tbl_teilnehmer.sql.
Bis jetzt drehten sich alle Abfragen immer um die Tabelle kurse. Neben den Informationen, die für einen Teilnehmer besonders wichtig sind, wie der Preis oder die Dauer, gibt es eine bisher nicht abgefragte Spalte für die Kursnummer. Laut dem obigen Datenmodell ist sie nicht nur der Primärschlüssel in dieser Tabelle, sondern stellt auch den Fremdschlüssel in der Tabelle buchungen. Sie verbindet als Beziehungstabelle die Tabellen kurse und teilnehmer. Das bedeutet schon einmal vorab, dass Abfragen, die z.B. in den Themenkreis Buchungen fallen, irgendwie diese Tabelle abfragen bzw. mit einbeziehen müssen. Schaut man ganz genau in den Inhalt dieser Beziehungstabelle, kann man bereits einige weitere Informationen anhand der Daten erkennen. Die ersten Datensätze bspw. stellen einen Kurs über den MS SQL Server dar, da die Kursnummer hier für die Buchungen 1 bis 11 gleich ist. Da für den Kurs über PHP ebenfalls ähnliche Teilnehmernummern existieren, müssen es wohl die gleichen Leute gewesen sein, die sowohl den einen wie den anderen Kurs besucht haben. Diese Informationen findet man ausschließlich durch Zahlenvergleich in den anderen Tabellen heraus. Natürlich ist dieser Vergleich auch mit entsprechenden Abfragen möglich. Genau dieses Ergebnis sehen Sie in der folgenden Abbildung, in der die Tabelle der vorherigen Abbildung eine weitere Spalte für den Titel des gebuchten Kurses aufweist. Ähnlich könnte man nun auch die Namen und Adressen der Kursteilnehmer oder – soweit es die Kurse betrifft – die Preise oder Dauer ausgeben. Würde man zusätzlich noch eine Tabelle für die Termine und die Dozenten haben, so könnte man für jeden Termin (stattgefundener Kurs) den entsprechenden Dozenten finden. Im Endeffekt laufen derartige Abfragen, die wir hier zu den komplexen zählen, darauf hinaus, dass man den Prozess der Normalisierung, wie wir ihn im ersten Projekt durchlaufen haben, rückgängig macht. Wenn also zu guter Letzt nach allen Verknüpfungsvorgängen eine große Tabelle mit sämtlichen Daten und ent-
112
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
sprechend vielen Redundanzen die Universal Relation erhält. Für genau dieses Beispiel soll nun die benötigte Abfrage schrittweise hergeleitet werden. 1. Zunächst müssen Sie nach der SELECT – Klausel die benötigten Spalten aufrufen, die aus den Tabellen in die Abfrage hineingenommen werden sollen. Da hier Spalten auftreten, die mit gleichem Namen in mehreren Tabellen erscheinen, müssen sie „qualifiziert“ werden, d.h. man stellt ihnen den Namen der Tabelle voran und verbindet beide durch einen Punkt. Dies muss zwangsweise nur bei Spalten geschehen, die tatsächlich in mindestens zwei Tabellen auftreten. Konkret wäre dies lediglich die Spalte kursnr, während die anderen Spalten nicht qualifiziert werden müssten. In den Abfragen dieses Buches wollen wir allerdings bei komplexen Abfragen jede Spalte auch mit ihren zugehörigen Tabellennamen verwenden, damit die Quelltext insgesamt ordentlicher und übersichtlicher aussehen. Aus gleichen Gründen ist dies auch für eigene Projekte nützlich, gerade auch dann, wenn umfangreiche Abfragen später noch verstanden werden sollen. SELECT buchungen.buchungsnr, buchungen.kursnr, buchungen.teilnnr, kurse.titel 2. Strukturell geschieht in der FROM – Klausel insoweit nichts, als dass wie sonst auch die benötigte Tabelle aufgerufen wird – allerdings sind es dieses Mal zwei Tabellen. FROM buchungen, kurse 3. In der WHERE – Klausel müssen Sie nun die Verknüpfung, die dieser Abfrage zu Grunde liegt, eindeutig benennen. In diesem Fall ist es gerade die Primärschlüssel-FremdschlüsselBeziehung der beiden Spalten kursnr. Die eigentliche Bedingung, die die so erzeugte Verknüpfung untersuchen soll, wird dann z.B. durch einen geeigneten Operator angeschlossen. In diesem einfachen Fall geschieht das durch AND, wobei lediglich die beiden gefundenen Kursnummern innerhalb einer IN – Klausel vorgegeben werden. Würde man darauf verzichten, so erhielte man die oben angesprochene Tabelle, in deren letzter Spalte jeweils der Kurstitel für jede Buchung angezeigt würde. Wir haben es hier lediglich aus drucktechnischen Gründen so gelöst, damit in der Abbildung wie immer auch der Abfragetext ausgegeben wird. WHERE buchungen.kursnr=kurse.kursnr AND buchungen.kursnr IN (50232, 20117) Noch einige Worte zur Handhabung dieser Technik: Teilweise stellt die geeignete Verknüpfung das eigentliche Problem der Abfrage dar und nicht etwa die Auswahl der weiteren Bedingungen in der WHERE – Klausel, da man ja zunächst die entsprechende verknüpfte Tabelle einrichten muss, ehe die anderen Bedingungen interessant werden. Mit Blick auf die relationale Algebra stellt die Verknüpfung einen Join aus mehreren Tabellen dar, wobei auf diese Ergebnisrelation weitere Filterungen angewandt werden. Im obigen Beispiel wird nach Einrichtung der (verknüpften) Ergebnisrelation durch die Selektion der Datensätze, die als kursnr die Nummern aus der Werteliste aufweisen, die zweite und endgültige Ergebnisrelation eingerichtet.
6.1.2 Möglichkeiten der Verknüpfung Neben der vorher gezeigten Standardanwendung gibt es unterschiedliche Möglichkeiten, Tabellen miteinander zu verknüpfen. Hierbei ist weniger die spätere Abfrage wichtig, sondern lediglich, wie die erste Ergebnisrelation eingerichtet wird, auf die man später mit weiteren Bedingungen zugreift. Daher soll es in diesem Abschnitt nur um die Möglichkeiten der Verknüpfung und gerade nicht um die weitere Einschränkung des Ergebnisses gehen. Achten Sie also lediglich darauf, wie das DBMS die erste Ergebnisrelation einrichtet. Prinzipiell können Sie dann immer weitere Einschränkungen mit der üblichen WHERE – Klausel anschließen. In den Übungen werden Sie dann konkrete
SQL
113
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
Fragen beantworten müssen und damit auch ganz konkret wie sonst auch die WHERE – Klausel mit Einschränkungen füllen, die sich auf diese erste Ergebnisrelation, die wir in den folgenden Punkten jeweils herleiten, bezieht und aus ihr die zweite, endgültige Ergebnisrelation macht. ¾ CROSS JOIN richtet das kartesische Produkt der beiden eingehenden Tabellen ein. Da beide Tabellen sehr viele Datensätze enthalten, können Sie sich mit Blick auf das Beispiel im vorherigen Kapitel ausmalen, dass die entstehende Tabelle mehr als lang sein dürfte. Tatsächlich ist sie sogar ohne die Gruppierungsanweisung genau 9550 Zeilen lang und stellt sicherlich Ihr DBMS auf die Probe. Die Tabelle buchungen enthält insgesamt 191 Zeilen, die Tabelle kurse 50. Gemäß der Formel bzgl. der Anzahl der Kombinationen (wie wir sie auch anhand des Beispiels „nachgewiesen“ haben) ergibt sich die Zahl der Kombinationsmöglichkeiten als Produkt der beiden Zeilenzahlen. Die (hier etwas sinnentfremdet) angewandte Gruppierung liefert dagegen wieder 50 Zeilen, nämlich genau die 50 Zeilen, die in der Tabelle kurse vorliegen. Da alle anderen Spalten gleich bleiben, kann man daraus schließen, dass sie der Reihe nach mit jeder einzelnen Titelzeile verknüpft werden. SELECT buchungen.buchungsnr, buchungen.kursnr, buchungen.teilnnr, kurse.titel FROM buchungen CROSS JOIN kurse GROUP BY titel Da alle Zeilen ausgefüllt sind und daher keinen Wert NULL enthalten, entspricht diese Abfrage ohne Gruppierung auch der Form: SELECT buchungen.buchungsnr, buchungen.kursnr, buchungen.teilnnr, kurse.titel FROM buchungen JOIN kurse ¾ NATURAL JOIN verknüpft eingehende Tabellenspalten aufgrund ihres Namens, d.h. gleichartige Namen werden miteinander verknüpft. Für das Einführungsbeispiel ergibt sich dabei folgender Quelltext: SELECT buchungen.buchungsnr, buchungen.kursnr, buchungen.teilnnr, kurse.titel FROM buchungen NATURAL JOIN kurse WHERE buchungen.kursnr IN (50232, 20117) Wichtig ist hier, wie schon in der Definition erwähnt, die Namensgleichheit der über Schlüssel verbundenen Spalten. Dies sollte in den meisten kleineren Datenbanken auch der Fall sein. Probleme können im allgemeinen Fall auftreten, sobald ähnliche Spalten für unterschiedliche Inhalte belegt werden., d.h., wenn eine Kursnummer in der einen Tabelle nicht die gleiche
114
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
Kursnummer in der anderen Spalte ist, aber dennoch so heißt. In diesem Fall macht es natürlich keinen Sinn, verschiedene Kursnummersysteme zu vergleichen und jedes Mal festzustellen, dass sie nicht zusammenpassen und daher keine Buchungen für einen bestimmten Kurs erfolgt sind, aber dennoch Teilnehmer im Seminarraum gesichtet wurden. ¾ INNER JOIN bezieht nur solche Zeilen in die erste Ergebnisrelation ein, die als Wert kein NULL enthalten. 1. Benennen Sie zuerst standardmäßig die benötigten Spalten in der SELECT – Anweisung. Da es auch hier lediglich um die Struktur geht, bleibt es bei den bisher üblichen Spalten. SELECT buchungen.buchungsnr, buchungen.kursnr, buchungen.teilnnr, kurse.titel 2. Dann folgt die Verknüpfungsart in der FROM – Klausel, indem Sie neben dem Tabellenaufruf zusätzlich die Bedingung für den Join benennen. Es muss also nicht zwangsläufig die Gleichheit sein, auf die man prüfen möchte. FROM kurse INNER JOIN buchungen ON buchungen.kursnr = kurse.kursnr 3. Im Ergebnis stellen Sie fest, dass Sie die bereits eingerichtete Tabelle erhalten, da ja keine Nullwerte zu verzeichnen sind. Anders stellt es sich dar, wenn Sie Nullwerte hätten, die in dieser ersten Ergebnisrelation nicht auftauchen würden. ¾ LEFT OUTER JOIN verknüpft die Zeilen der ersten Tabelle mit den zugehörigen Werten der zweiten Tabelle, wobei evtl. nicht vorhandene Werte in der zweiten Tabelle NULL gesetzt werden. Hintergrund soll die Wertedominanz der ersten Tabelle sein. Ihre Werte sollen auch dann erhalten bleiben, wenn sie kein entsprechendes Gegenüber in der zweiten Tabelle finden. In diesem Zusammenhang bedeutet das Seitenverhältnis die Reihenfolge innerhalb der WHERE – Klausel. Die erste Tabelle, die genannt wird, wird in dieser Konstruktion zur ersten Tabelle, also zur Tabelle mit Wertedominanz. Die folgende Abfrage zeigt sehr eindrucksvoll die Bedeutung der Wertedominanz einer Tabelle. In diesem Fall geht es um die Dominanz der Tabelle kurse, da sie zuerst in die Abfrage eingeht. In dieser Tabelle befinden sich alle Kurse, d.h. insbesondere auch Kurse, die nie gebucht worden sind. Daher müssen bei der Verknüpfung sehr viele Zeilen erzeugt werden, die keine Buchungsnummer haben. Sinn macht eine solche Abfrage z.B. für den Fall, dass man herausfinden möchte, welche Kurse gerade nicht gebucht worden sind bzw. noch nie gebucht wurden. SELECT buchungen.buchungsnr, buchungen.kursnr,
SQL
115
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
buchungen.teilnnr, kurse.titel FROM kurse LEFT OUTER JOIN buchungen ON buchungen.kursnr = kurse.kursnr WHERE kursnr > 20117 WHERE buchungen.kursnr > 20117 ¾ RIGHT OUTER JOIN entspricht von der Funktionsweise dem LEFT OUTER JOIN. Hierbei liegt jedoch die Wertedominanz bei der eingehenden zweiten Tabelle, sodass bei einem fehlschlagenden Vergleich in der ersten Tabelle in dieser Tabelle der Wert NULL ergänzt wird. So bleiben zumindest die Werte der zweiten Tabelle komplett erhalten. Genau andersherum als im vorherigen Beispiel verhält es sich, wenn die Wertedominanz bei der zweiten eingehenden Tabelle angesiedelt ist. Da in der Tabelle buchungen weniger Kursnummern vorhanden sind als in der Tabelle kurse, entsteht genau das andere Phänomen: Alle Zeilen werden ausgefüllt, wobei weniger Kurse angezeigt werden, als insgesamt buchbar wären. SELECT buchungen.buchungsnr, buchungen.kursnr, buchungen.teilnnr, kurse.titel FROM kurse RIGHT OUTER JOIN buchungen ON buchungen.kursnr = kurse.kursnr WHERE kurse.kursnr > 20117 Die oberen Abfragen beschränkten sich alle auf Kurse oberhalb der Nummer 20117, da es in der ersten Abfrage dieses Typs wegen der Tabellenausgabe (Felder mit Nullwert) drucktechnisch besser war. Kehrt man diese Bedingung allerdings so um, dass nicht die Kursnummer der Tabelle kurse verwendet wird, sondern der Tabelle buchungen, wird durch die Wertedominanz ersichtlich, dass die Nummer 20239 in dieser Tabelle gar keinen passenden Treffer findet, weil er nicht gebucht ist. Nur die gewählte Verknüpfungsart kann diesen Fehler anzeigen, weil ja auch Treffer, die auf kein passendes Gegenstück treffen, mit den Wert NULL angezeigt werden. SELECT buchungen.buchungsnr, buchungen.kursnr, buchungen.teilnnr, kurse.titel FROM kurse RIGHT OUTER JOIN buchungen ON buchungen.kursnr = kurse.kursnr WHERE buchungen.kursnr > 20117
116
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
¾ FULL OUTER JOIN kombiniert beide vorher beschriebenen Verknüpfungsarten. Hierbei bleiben sämtliche Einzelwerte in den Spalten erhalten, wobei ein fehlender Wert in der anderen Tabelle durch NULL ersetzt wird. In diesem Fall werden sämtliche Verknüpfungsmöglichkeiten in einer Tabelle ausgegeben, wobei allerdings die jeweiligen Werte, die keinen Geschwisterwert in der anderen Tabelle finden, mit dem Wert NULL als Geschwisterwert dargestellt werden. SELECT buchungen.buchungsnr, buchungen.kursnr, buchungen.teilnnr, kurse.titel FROM kurse FULL OUTER JOIN buchungen ON buchungen.kursnr = kurse.kursnr ¾ UNION JOIN bildet eine Differenz zwischen FULL OUTER JOIN und INNER JOIN. In die endgültige Ergebnisrelation werden die Datensätze / Zeilen übernommen, die links einen Wert der ersten Tabelle aufweisen und mit NULL ergänzt wurden, und die rechts einen Wert der zweiten Tabelle aufweisen und mit NULL ergänzt wurden.
Es ist ebenfalls möglich, über den Asteristikus sämtliche Spalten einer Tabelle auszuwählen, wenn Tabellen miteinander verknüpft werden sollen: kurse.* ist dann die richtige Syntax.
6.1.3 Tabelle mit sich selbst verknüpfen Ab und an kann es notwendig werden, eine Tabelle mit sich selbst zu verknüpfen, um innerhalb dieser Tabelle Vergleiche der Datensätze anzustellen. In diesem Fall müssen der Tabelle zwei Aliasnamen gegeben werden, damit strukturell sozusagen zwei Tabellen miteinander verknüpft werden. 1. Im vorliegenden Fall sollen die beiden Aliasnamen für die Tabelle kurse die Buchstaben a und b sein. Sie werden bereits beim Aufruf der benötigten Spalten wie sonst auch mit einem Punkt vor die Spaltennamen gesetzt. SELECT a.kursnr, a.titel, b.kursnr, b.titel 2. Die eigentliche Definition dieser Synonyme geschieht in der FROM – Klausel, indem jeweils der originale Tabellenname, gefolgt von seinem Synonym, aufgelistet wird. FROM kurse a, kurse b 3. Wie sonst auch folgen die mindestens zwei Bedingungen einmal für die Verknüpfung selbst und einmal für das inhaltlich bedeutsame Filterkriterium. In diesem Fall soll ein kurzer Test stattfinden, ob evtl. Kursnummern und Titel nicht optimal (sprich fehlerhaft) vergeben sind. Dies ist dummerweise tatsächlich der Fall, und das genau bei unserem Buch-Thema. Es gibt zwei verschiedene Kurstitel für die Kursnummer 20136, die Ihnen vielleicht bereits aufgefallen sind und genau an dieser Stelle Sinn machen.
SQL
117
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
WHERE a.kursnr = b.kursnr AND a.titel <> b.titel
6.1.4 Mehr als zwei Tabellen verknüpfen Bis jetzt war die Anzahl der Tabellen, welche in den Join eintreten, übersichtlich gering. Entweder waren es zwei oder auch nur eine, wenn sie – wie im letzten Abschnitt - mit sich selbst verknüpft wurde. Im vorliegenden Datenmodell jedoch benötigt man eindeutig eine weitere Tabelle, um die Tabelle buchungen vollständig nutzen zu können. Während die obigen Abfragen über die Kursnummern Informationen zu den Kursen lieferten, benötigt man die Tabelle teilnehmer, um zusätzlich Informationen über die Teilnehmer eines Kurses herauszufinden. Ganz konkret geht es um die Frage, welcher Kurs mit welchen Teilnehmern stattgefunden hat. Eine andere Frage entsteht, wie man von den Teilnehmern wiederum zu den Unternehmen findet. In der Tabelle teilnehmer befindet sich eine Spalte für die Unternehmensnummer, die sie einem Unternehmen aus der Liste der Unternehmen zuordnet. Hier müsste man also diese Tabelle ebenfalls in die Abfrage aufnehmen, um die Unternehmen den Teilnehmern zuzuordnen. Das wäre z.B. auch bei einer Abfrage wichtig, die angeben soll, welches Unternehmen welchen Kurs gebucht hat. In diesem Zusammenhang sei noch einmal auf die Wichtigkeit hingewiesen, dass das Datenmodell von vornherein (also bevor Programmtext mit SQL-Abfragen vermengt wird) feststeht. Man erspart sich dann bei Änderungen, auch solche komplexen Abfragen erneut zu ändern. 1. Nennen Sie wie immer die benötigten Spalten. In diesem Fall reichen die allernötigsten, um die Funktionsweise dieser großen Verknüpfung zu testen. SELECT buchungen.buchungsnr, teilnehmer.teilnvorname, teilnehmer.teilnnachname, kurse.titel 2. Nennen Sie dann die benötigten Tabellen. FROM buchungen, teilnehmer, kurse 3. Nennen Sie dann die Bedingungen, mit denen Sie die Tabellen verknüpfen. Auf weitere Bedingungen wie eine Auswahl bestimmter Kurse oder eine Begrenzung auf eine bestimmte Heimatstadt der Teilnehmer wird verzichtet. WHERE buchungen.kursnr=kurse.kursnr
118
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
AND buchungen.teilnnr=teilnehmer.teilnnr ORDER BY kurse.titel DESC, teilnehmer.teilnnachname ASC Bedeutsam an diesem Vorgehen ist, dass beide Vergleiche immer von der Beziehungstabelle buchungen aus zu den anderen Tabellen zeigen. Hierbei ist die Reihenfolge, in der die Tabellen für den Vergleich genannt werden, nicht weiter relevant, hilft aber, um die Struktur der Verknüpfung zu erkennen: In der Tabelle buchungen müssen also beide Spalten vorhanden sein, sodass sie die eigentliche Beziehung zwischen den beiden Tabellen herstellt. Im nächsten Beispiel wird es sich genau anders verhalten, da hier die weitere Tabelle nur deswegen hinzugezogen wird, weil in der Beziehungstabelle buchungen nicht die benötigte Primärschlüssel-FremdschlüsselBeziehung besteht. Die Struktur der Abfrage bleibt dieselbe. Neu ist nur, dass eine weitere Bedingung in der WHERE – Klausel angehängt wird, um die neu hinzugekommene Verknüpfung zwischen den Tabellen teilnehmer und unternehmen zu beschreiben. Hier wird bereits in den Tabellennamen im Vergleich zu den beiden oberen Bedingungen deutlich, dass hier eine Beziehung außerhalb der Beziehungstabelle aufgebaut wird, also sozusagen eine weitere Tabelle hinzukommt, die in der Beziehungstabelle buchungen nicht bereits impliziert ist. SELECT buchungen.buchungsnr, unternehmen.untname, teilnehmer.teilnvorname, teilnehmer.teilnnachname, kurse.titel FROM buchungen, teilnehmer, kurse, unternehmen WHERE buchungen.kursnr=kurse.kursnr AND buchungen.teilnnr=teilnehmer.teilnnr AND teilnehmer.untnr=unternehmen.untnr ORDER BY kurse.titel DESC, teilnehmer.teilnnachname ASC Damit nach diesen vielen Abfragen nicht der Eindruck bleibt, man müsste stets qualifizierte Tabellennamen verwenden, möchten wir noch einmal an den Hinweis erinnern, den wir gegeben haben, als wir die qualifizierten Tabellennamen eingeführt haben. Man muss wirklich lediglich die Spalten mit ihren Tabellennamen verbinden, wenn die Zuordnung nicht eindeutig ausfallen könnte. Dies ist insbesondere beim Aufruf, der WHERE – Klausel und bei Sortierungen der Fall. Bei steigender Komplexität könnte die Vereinfachungsregel, die die Quelltexte bisher aufwiesen, nämlich einfach immer qualifizierte Namen zu verwenden, lästig werden. Je nachdem, wie gut sie Ihr Datenmodell kennen und Sie wissen, welche Spalten in welchen Tabellen erscheinen (spätestens bei der Verknüpfung müssen Sie es wissen), können Sie die Skripte wieder auf ein Minimum reduzieren. Das hat dann auch den Vorteil, dass die verknüpften Spalten besonders deutlich auffallen. Eine andere Möglichkeit zur Vereinfachung bieten Aliasnamen. Kurz und gut, das vorherige Beispiel ließe sich auch so schreiben:
SQL
119
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
SELECT buchungen.buchungsnr, untname, teilnvorname, teilnnachname, kurse.titel FROM buchungen, teilnehmer, kurse, unternehmen WHERE buchungen.kursnr=kurse.kursnr AND buchungen.teilnnr=teilnehmer.teilnnr AND teilnehmer.untnr=unternehmen.untnr ORDER BY kurse.titel DESC, teilnnachname ASC
Die Anzahl der Tabellen, die miteinander verknüpft werden, hängt jeweils vom DBS ab. Normalerweise sollte man sich also bereits bei der Gestaltung des Datenmodells Gedanken machen, wie viele Verknüpfungen notwendig sind, um alle Tabellen miteinander in Beziehung zu setzen. Das wäre ja der umfangreichste Verknüpfungsfall. Ob er eintritt oder nicht, er wird in jedem Fall von den technischen Bedingungen beschränkt.
6.2 Aggregatfunktionen einsetzen Zu Anfang des Projekts sprachen wir etwas großspurig von statistischen Funktionen, die zeitgleich mit der Abfrage wie die mathematischen Berechnungen verwendet werden können. Da nun schon der Vergleich mit diesen mathematischen Funktionen gezogen wurde, kann man daraus schließen, dass es mit den statistischen Funktionen wohl auch nicht viel her sein kann. Tatsächlich finden Sie ja in der Überschrift bereits den offiziellen Begriff der Aggregatfunktionen. Mit ihnen ist es zusammenfassend möglich, Mittelwertsbildungen vorzunehmen, größte und kleinste Werte auszuwählen, sowie Summen berechnen zu lassen und Datensätze zu zählen. Interessant ist, wie diese speziellen Abfragen vom DBMS verarbeitet und zurückgegeben werden. Dies kann bei den einzelnen Funktionen und DBMS ein wenig variieren, aber typischerweise wird der Vorgang so wie folgt ablaufen. In nebenstehender Abbildung sehen Sie wie sonst auch das Ergebnis folgender Abfrage: SELECT COUNT(buchungsnr) FROM buchungen Sollte Ihnen wider Erwarten trotz ihrer wunderbaren Funktionalität der Funktionsaufruf im Spaltenkopf nicht zusagen, können Sie wie stets einen Aliasnamen über das Schlüsselwort AS verwenden. Er folgt direkt der Funktion. SELECT COUNT(buchungsnr) AS AnzahlDerBuchungen
120
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
FROM buchungen Im für die Abfrage verantwortlichen PHP-Programm wird die Abfrage gesendet und so verarbeitet, dass die eintreffende Ergebnistabelle auf Feldnamen und Datenzeilen hin untersucht und der Reihe nach in HTML ausgegeben wird. Dabei fällt auf, dass das DBS eine 1x1-Tabelle zurücksendet, in der die einzige zu zählende Spalte mit Ergebnis im Datenbereich und mit dem Funktionsaufruf oder dem eigens vorgegebenen Namen als Spaltenkopf enthalten ist. Je nach Funktionsverwendung können natürlich dementsprechend viele Spalten auftreten, doch diese Grundstruktur bleibt immer erhalten. Es wäre also, falsch anzunehmen, es träfe nur eine einzige Ergebniszahl ein, die als Variablenwert sofort weiterverarbeitet werden kann. Hier werden Sie den falschen Datentyp im Programm einsetzen. Wenn Sie eine Abfrage also nicht anhand Ihrer verwendeten Programmiersprache verarbeiten (zähle Datenreihen, zähle Felder, rufe Feldnamen ab usw.), sondern mit SQL bereits die benötigten Informationen beschaffen, müssen Sie diese Hinweise beachten. ¾ Kleinsten und größten Wert finden Die erste Funktion wählt aus Spalten, die den Datentyp Zahl oder Zeichenkette (!) haben, den Datensatz mit dem kleinsten oder größten Wert aus. SELECT MIN(teilnhausnr) AS KleinsteHausnummer FROM teilnehmer Innerhalb der SELECT – Anweisung dürfen keine weiteren Spalten vorgegeben werden. Daher kann nur über eine Unterabfrage – wie sie in der nächsten Lektion behandelt wird – auch z.B. der Besitzer der kleinsten Hausnummer ausfindig gemacht werden. SELECT teilnvorname, teilnnachname FROM teilnehmer WHERE teilnhausnr = (SELECT MIN(teilnhausnr) FROM teilnehmer) Für die größte Hausnummer gibt es eine analoge Funktion, die MAX heißt. Sollten Sie sie bereits getestet haben, werden Sie festgestellt haben, dass statt der 40 die 9 in der Ausgabe erscheint. Dies ist darauf zurückzuführen, dass der Datentyp der Hausnummer in Wirklichkeit gar keine Zahl wie INTEGER ist, sondern vielmehr ein Zeichenkettentyp wie VARCHAR ist. Zeichenketten können anhand dieser Funktionen auch analysiert werden, wobei ihre binären Werte verwendet werden. Die 1 hat dabei den niedrigsten und die 9 den höchsten binären Wert, da ja alle anderen Zahlen mathematische Zusammensetzungen dieser Zahlen sind. Sie müssten also zunächst den Datentyp ändern: ALTER TABLE teilnehmer CHANGE teilnhausnr teilnhausnr INT(10) DEFAULT '0' NOT NULL
SQL
121
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
Danach kann die Abfrage analog zur ersten gestellt werden und liefert auch ein mathematisch korrektes Ergebnis, nämlich die Hausnummer 40. SELECT MAX(teilnhausnr) AS GrößteHausnummer FROM teilnehmer ¾ Mittelwert berechnen lassen Über die Funktion AVG kann man sich den Durchschnitt einer Spalte berechnen und ausgeben lassen. In den folgenden Beispielen wird zum einen der Durchschnittspreis, zum anderen die Durchschnittsdauer und dann eine Kennzahl für den durchschnittlichen Preis pro Tag berechnet und ausgegeben. SELECT AVG(preis) FROM kurse SELECT AVG(dauer) FROM kurse Interessant an dieser Kennzahl ist, dass es also auch möglich ist, mit den so berechneten Werten weitere Berechnungen über die bekannten mathematischen Operatoren ausführen zu lassen. SELECT AVG(preis)/AVG(dauer) FROM kurse ¾ Summen erzeugen Als Einzelabfrage, also ohne eine weitere Unterabfrage, ist die Summenbildung in diesem Datenmodell nicht gerade sinnvoll, sodass uns nur übrig bleibt, die Gesamtsumme alle Kurspreise zu bestimmen, um uns an der hohen Zahl zu berauschen. Dafür wird die Funktion SUM verwendet, die ausschließlich für Zahlen eingesetzt werden kann. SELECT SUM(preis) FROM kurse ¾ Automatisch Zeilen in Spalten zählen lassen Eine überaus wichtige Funktion – daher auch als glänzender Höhepunkt am Schluss – stellt die Funktion COUNT dar, mit der man Werte in Spalten zählen lassen kann. Mit ihr lassen sich alle Fragen beantworten, die für weitere statistische Auswertungen mit geeigneten (selbst geschriebenen) Programmen notwendig sind. Diese Funktion hat verschiedene Anwendungsfälle, die wir in den nächsten Beispielen wieder etwas ausführlicher als die Summenbildung vorstellen wollen.
122
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
1. Die Grundform besteht darin, dass Sie wie immer eine Spalte innerhalb der Funktion aufrufen, die in diesem Fall ganz simpel durchgezählt wird. Um also die Anzahl der Buchungen zu bestimmen, die in der Tabelle buchungen gespeichert sind, führen Sie folgende Abfrage durch. Sie erhalten insgesamt 191 Buchungsfälle. SELECT COUNT(buchungsnr) AS GesamtBuchungen FROM buchungen 2. Eine Alternative zu dieser Vorgehensweise stellt die Verwendung des Asteristikus dar, weil ja bei der einfachen Zählung ohnehin nur die Länge der gesamten Tabelle ermittelt werden soll. SELECT COUNT(*) FROM buchungen 3. Wenn man dagegen die Berücksichtigung der Null-Werte ausschließen möchte, verwendet man wieder die Option DISTINCT innerhalb der COUNT – Anweisung. In diesem Fall wären es ebenfalls 191 Buchungsfälle, da natürlich keine Luftbuchungen erfasst werden. SELECT COUNT(DISTINCT buchungsnr) AS AnzahlBuchungen FROM buchungen 4. Um dann allerdings festzustellen, wie viele einzelne Teilnehmer als Personen anwesend waren, weil ja vermutlich auch einige der 191 Buchungen Mehrfachbuchungen für verschiedene Kurse waren, muss die Spalte durchsucht werden, die Duplikate enthalten kann. Dies trifft auf die Spalten kursnr und teilnnr zu, wobei für die Teilnehmer natürlich teilnnr interessant ist. Hier sollen also Duplikate ausgeschlossen werden, sodass ebenfalls DISTINCT verwendet werden muss. SELECT COUNT(DISTINCT teilnnr) AS TeilnehmerAlsPersonen FROM buchungen Neben diesen eigentlich trivialen Einsatzfällen bietet diese Funktion dagegen auch reichlich raffiniertere Anwendungen, die mit den anderen in diesem Projekt gezeigten Techniken tatsächlich ein wenig das Prädikat einer statistischen Funktion verdient. Hierbei handelt es sich als Beispiel um die Frage, welcher Teilnehmer wie viele Kurse gebucht hat. Man weiß zwar aus der vorherigen Abfrage, dass sich auf insgesamt nur 63 einzelne Personen 191 Buchungen für Kurse verteilen, doch ist noch nicht geklärt, wer nun letztendlich welchen Kurs gebucht hat.
SQL
123
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
Die Tabelle buchungen würde zwar über die Teilnehmernummer Auskunft geben können, aber interessanter wäre auch die Information, wer sich ganz konkret hinter diesen Zahlen verbirgt. In einem weiteren Schritt könnte man dann die Top-Buchungsunternehmen herausfinden, um den Geschäftspartner mit den meisten Firmenschulungen herauszufiltern. Dabei nützt die Eigenschaft der COUNT – Funktion, auch andere Spalten in die SELECT – Anweisung hineinnehmen zu können, sodass die durch die Zählung erzeugte Spalte nur eine Ergebnisspalte ist. Daher ist es auch möglich, die Namen der Teilnehmer auszugeben, die über die Verknüpfung mit der Tabelle teilnehmer in die Abfrage gezogen werden. SELECT buchungen.teilnnr, teilnvorname, teilnnachname, COUNT(buchungen.teilnnr) AS Kursbesuche FROM buchungen NATURAL JOIN teilnehmer GROUP BY teilnnr
6.3 Unterabfragen und ihre Operatoren Bisher war es nicht immer zu vermeiden, dass hier und da bereits eine Unterabfrage auftauchte, sodass das Prinzip vermutlich schon klar ist. Innerhalb einer Abfrage wird auf das Ergebnis einer anderen Abfrage zugegriffen. Inhaltlich bedeutet dies lediglich, dass man das Pferd sozusagen vom Schwanz her aufzäumt und zunächst die Unterabfrage erstellt, um dann mit weiteren Einschränkungen darauf zuzugreifen. Wichtig ist daher immer für die Konstruktion, sich über denr Inhalt der ersten Ergebnisrelation (also der Unterabfrage) im Klaren zu sein.
6.3.1 Grundprinzip einer Unterabfrage Besonders eindrucksvoll lässt sich die Funktionsweise einer Unterabfrage an den Spaltenfunktionen festmachen, die ja bis auf die Summenfunktion nicht ganz so beeindruckend wirkten, da sie nicht immer sehr praxistauglich schienen. Wenn Sie jedoch in eine Unterabfrage eingebunden werden, die dann ihren ermittelten Wert als Vergleichsmaßstab für die eigentliche Abfrage zur Verfügung stellt, ändert sich die Situation. Vorhin hatten wir den Durchschnittswert ermittelt, wie teuer ein Kurs pro Tag ist. Dies ist ein Wert, mit dem man überhaupt das Preisniveau von Schulungsfirmen vergleichen kann, da ja nicht alle Kurse gleich lang sind und daher ein zweitägiger, billigerer Kurs im Vergleich zu einem viertägigen, etwas teueren Kurs dann plötzlich nicht mehr interessant sein kann. 1. Dieser einzelne Wert über die gesamte Tabelle wurde mit folgender Abfrage ermittelt: SELECT AVG(preis)/AVG(dauer) FROM kurse 2. Um nun herauszufinden, welche Kurse einen höheren Tagespreis als der Durchschnitt des gesamten Kursangebots aufweisen, kann man die oben ermittelte Zahl als Vergleichsmaßstab in die WHERE – Klausel einsetzen.
124
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
SELECT titel, dauer, preis, preis/dauer FROM kurse WHERE preis/dauer > 292.463768 3. Die Unterabfrage-Technik bietet nun die Möglichkeit, die beiden ersten Schritte in einem einzigen zu verarbeiten, indem die oben gestellte Abfrage zur Ermittlung des durchschnittlichen Tagespreises in die WHERE – Klausel eingetragen wird. Dabei steht genau der gleiche Wert zur Verfügung, als würde man den mit der Unterabfrage ermittelten Wert von ca. 292 direkt wie oben gezeigt verwenden. SELECT titel, dauer, preis, preis/dauer FROM kurse WHERE preis/dauer > (SELECT AVG(preis)/AVG(dauer) FROM kurse)
Beachten Sie zusätzlich die raffinierte Verwendung einer Berechnung innerhalb der Spaltenauswahl in der SELECT – Anweisung mit preis/dauer. Es ist also mit Hilfe der mathematischen Operatoren ebenfalls möglich, eine noch gar nicht vorhandene Spalte durch eine solche Berechnungsvorschrift neu zu generieren.
6.3.2 Verwendung von Vergleichsoperatoren Die Unterabfrage wird mit den bereits beschriebenen Vergleichsoperatoren oder logischen Funktionen innerhalb der WHERE – Klausel eingebunden. Dies hatten Sie bereits im letzten Beispiel gesehen. Das gleiche Beispiel funktioniert wunderbar mit anderen Vergleichsoperatoren als „größer“, sodass wir auf eine genaue Erläuterung aufgrund Trivialität verzichten. Ebenso funktionstüchtig bleiben AND, OR und NOT, da ihre Funktionsfähigkeit primär von der umgebenden WHERE – Klausel abhängig ist und nicht etwa vom Inhalt des Vergleichs (NULL ausgenommen). Lediglich einen Operator wollen wir gezielt herausgreifen, weil er sehr schön den Vergleich der beiden Relationen veranschaulicht und dazu dient, darauf zu testen, ob übereinstimmende Werte (beliebig viele) zwischen äußerer und innerer Ergebnisrelation vorliegen. 1. In einer ersten Abfrage wird gezählt, mit wie vielen Teilnehmern die einzelnen Kurse stattgefunden haben. Daraus ergibt sich eine Aufstellung mit den 10 beliebtesten Kursen, die nachher dazu benutzt werden soll, um die zugehörigen Kursorte für diese Kurse herauszufiltern. Dabei ist es vermutlich am einfachsten, wenn man diese erste Abfrage in eine Unterabfrage platziert, weil so eine gewisse Übersichtlichkeit erhalten bleibt.
SQL
125
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
SELECT buchungen.kursnr, kurse.titel, COUNT(buchungen.kursnr) FROM buchungen NATURAL JOIN kurse GROUP BY buchungen.kursnr 2. Die eigentlich geplante Abfrage, die nachher die soeben erstellte als Unterabfrage aufnehmen soll, sollte bzgl. der herausgefundenen Kursnummern die zugehörigen Orte aus dem Terminkalender filtern. Inhaltlich ergibt sich also, dass die beiden Tabellen kurse und termine verknüpft werden müssen und die Überprüfung in der WHERE – Klausel die einzelnen Werte aus der gerade erstellten Abfrage testet. Da die Termine mehrmals im Kalender mit den gleichen Orten stattfinden, sollen die Duplikate durch DISTINCT gelöscht werden. SELECT DISTINCT kurse.kursnr, kurse.titel, termine.ort FROM kurse NATURAL JOIN termine WHERE kurse.kursnr IN (10111, 20117, 20134, 20136, 20142, 30129, 30136, 30329, 40314) 3. In der zusammengesetzten Abfrage ersetzt die zuerst erstellte Abfrage der Tabelle buchungen die Werteliste der im letzten Schritt konstruierten Abfrage komplett. An ihrer Stelle tritt also ebenfalls mit dem IN – Operator die obige Abfrage. Es entsteht eine Tabelle, die Kursnummer, Titel und Ort nennt, an dem die stattgefundenen Seminare verzeichnet werden. Strukturell kann hier also der praktische IN – Operator erhalten bleiben. SELECT DISTINCT kurse.kursnr, kurse.titel, termine.ort FROM kurse NATURAL JOIN termine WHERE kurse.kursnr IN (SELECT buchungen.kursnr, kurse.titel, COUNT(buchungen.kursnr) FROM buchungen NATURAL JOIN kurse GROUP BY buchungen.kursnr)
126
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
Zum Schluss geben wir Ihnen noch das endgültige, amtliche Endergebnis mit auf den Weg, das selbst um Duplikate bereinigt ist und in das auch auf keiner Ebene der Abfrage Duplikate eingeflossen sind. UNIQUE stellt dabei eine Möglichkeit dar, zusätzlich – wenn Duplikate prinzipiell in einer Unterabfrage zugelassen werden – auf die Existenz solcher Duplikate zu prüfen. Sie werden dabei allerdings nicht automatisch entfernt.
Wie schon bei den Verknüpfungen ist die Anzahl der ineinander verschachtelten Abfragen lediglich durch das DBS technisch begrenzt. Prinzipiell können also dementsprechend viele Unterabfragen ineinander jedes Mal über die WHERE – Klausel verschachtelt werden. Die Abarbeitung erfolgt immer von der innersten zur äußersten Abfrage.
6.3.3 Prädikate bei Unterabfragen Die Ergebnismenge der Unterabfrage prüfen verschiedene quantifizierte Prädikate, wie es schon im letzten Projekt kurz im Rahmen der Vorstellung von MATCH erwähnt würde. Nun folgen weitere Hinweise zu diesen Prädikaten. Dabei ist die allgemeine Syntax folgendermaßen aufgebaut: WHERE ... vergleichsoperator [ANY | ALL | SOME] unterabfrage Die einzelnen Prädikate können also fakultativ direkt vor die Unterabfrage bzw. direkt nach dem Vergleichsoperator der WHERE – Klausel gesetzt werden. Ihre Bedeutung im Einzelnen: ¾ ANY und SOME haben die gleiche Bedeutung und werten die Bedingung als wahr, wenn wenigstens eine Reihe der Unterabfrage dem Vergleich entspricht. Stimmen alle Reihen mit dem Vergleich überein, ist das Ergebnis ebenfalls wahr. Sind dagegen alle Reihen falsch, so ist das gesamte Ergebnis falsch. Da ANY sprachlich nicht eindeutig ist, soll SOME der Vorzug gegeben werden. ¾ ALL dagegen wertet die Bedingung nur dann als wahr, wenn wirklich alle Reihen der Unterabfrage dem Vergleich entsprechen. Ein falsches Ergebnis bzw. eine nicht zutreffende Reihe lässt also das gesamte Ergebnis falsch werden. Ein anderes Prädikat ist UNIQUE mit der allgemeinen Syntax: WHERE ... vergleichsoperator [UNIQUE] unterabfrage Dieses Prädikat überprüft das Ergebnis einer Unterabfrage darauf, ob es Duplikatzeilen gibt. Sollten insgesamt keine solchen Doppelgänger existieren, ist das Ergebnis wahr. Ansonsten ist es bereits bei einem einzigen doppelten Datensatz falsch. Eine Besonderheit stellt der Wert NULL dar. Existieren zwei Datensätze, die sowohl in ihren anderen Werten als auch im Null-Wert übereinstimmen, so gelten diese beiden Tupel als verschieden. Zum Schluss gibt es mit [NOT] EXISTS noch die Möglichkeit, die Existenz der Unterabfrage, also ob überhaupt ein Ergebnis existiert, zu überprüfen. Dabei wird als Wert einer leeren Unterabfrage nicht NULL, sondern stattdessen der Wert UNKNOWN erwartet. Auf den Null-Wert kann also zusätzlich mit IS NULL geprüft werden, wenn dies ausdrücklich berücksichtigt werden soll. Die allgemeine Syntax hat dabei folgende Form:
SQL
127
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
WHERE ... vergleichsoperator [[NOT] EXISTS] unterabfrage ¾ EXISTS prüft darauf, ob eine gebundene Abfrage überhaupt Werte enthält. Sollte die Unterabfrage leer sein, stimmt der Test. Im Gegenfall wird die Bedingung als falsch bewertet. ¾ NOT EXISTS prüft dagegen genau auf das Gegenteil, nämlich darauf, ob eine Unterabfrage keinen Wert enthält. Ist dies der Fall, wird die Bedingung als wahr bewertet. Enthält die Unterabfrage dagegen Werte, so liefert der Vergleich ein falsches Ergebnis zurück. Diese einzelnen Prädikate sollen anhand einer einfachen Unterabfrage analysiert werden, die für jedes Prädikat gleich ist, damit die Unterschiede besser deutlich werden. Sie werden alle direkt nach dem Vergleichsoperator in die komplette Abfrage eingebettet, wie es oben in der allgemeinen Syntax beschrieben wurde. SELECT untnr, teilnnr, teilnstadt FROM teilnehmer WHERE = [ANY | SOME | ALL | UNIQUE | [NOT] EXISTS] (SELECT unternehmen.untnr, teilnnr, teilnehmer.teilnstadt FROM unternehmen NATURAL JOIN teilnehmer WHERE untstadt=teilnstadt) Die Abfrage soll darauf testen, ob bzw. in welchem Maße es Teilnehmer gibt, die in der gleichen Stadt wohnen, in der das Unternehmen liegt, für das sie arbeiten. Dies fordert zunächst innerhalb der Unterabfrage eine Ergebnisrelation, die wir in der Abbildung komplett ausgeben, damit die Überlegung etwas einfacher wird. Zunächst wird also eine Verknüpfung zwischen den beiden Tabellen unternehmen und teilnehmer eingerichtet, aus der wiederum nur die Teilnehmer benötigt werden, die – wie oben gesagt – als Stadt die Stadt aufweisen, in der sich das Unternehmen befindet. Die umschließende Abfrage wird bis zum Datensatz 22 ebenfalls in nebenstehender Abbildung ausgegeben. Es handelt sich um die fast schon klassische Ausgabe eines Teils der Tabelle teilnehmer. Mit Hilfe der Unterabfrage soll nun (in Maßen) ein quantitativer Vergleich beider Tabellen stattfinden. Als Beispiel genügt zum einen der Teilnehmer Nr. 3. Wir wissen (wegen der fehlenden Spalten) nicht, wie er oder wie sein Unternehmen heißt, aber er arbeitet in Unternehmen Nr. 1, und er taucht an erster Stelle in der Ergebnistabelle der Unterabfrage auf. Die Unterabfrage stellt also gerade eine Untermenge der hier ausgegebenen Tabelle teilnehmer dar, wobei die gefundenen Datensätze die oben beschriebene Eigenschaft besitzen.
128
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
Sobald Sie dieses Beispiel für trivial halten, weil man ja das Ergebnis anhand der ersten Abbildung bereits sehen kann, so muss noch einmal gesagt werden, dass es gerade nicht darum geht, welche Datensätze genau die geforderte Eigenschaft erfüllen, sondern es vielmehr darum geht, mit Hilfe der kompletten Abfrage herauszufinden, in welchem Maß – soweit es die Prädikate messen können – die Eigenschaft erfüllt ist. Dazu gehen wir die einzelnen Prädikate durch: ¾ Sobald die Abfrage mit ANY oder SOME ausgeführt wird und genau die oben abgebildete Ergebnisrelation in der Unterabfrage erscheint, wird der Wert WAHR zurückgeliefert, da in der Ergebnisrelation der Unterabfrage mindestens ein Datensatz erscheint. Dies bedeutet, dass in der Tabelle teilnehmer wenigstens ein einziger Datensatz die geforderte Eigenschaft besitzt bzw. ein Teilnehmer die gleiche Heimatstadt besitzt wie sein Unternehmen. ¾ Wird dagegen mit ALL getestet, wird der Wert FALSCH zurückgeliefert, denn die oben ausgegebene Tabelle ist eine echte Teilmenge der Ergebnisrelation der Abfrage. Unecht wäre die Teilmenge dann, wenn tatsächlich alle Teilnehmer die Bedingung erfüllen würden, dass sie in der gleichen Stadt wohnen, wo ihr Unternehmen seinen Sitz hat. Dann wiesen die Tabellen von Unterabfrage und Abfrage die gleiche Menge an Datensätzen auf und wären inhaltlich identisch. Nur in diesem Fall würde der Wert WAHR zurückgeliefert. ¾ Wird diese Abfrage nur oder auch zusätzlich mit UNIQUE durchgeführt, so kann bei dieser Spaltenprojektion niemals der Wert FALSCH erscheinen, da jeder Teilnehmer mit seiner einzigartigen Nummer ausgegeben wird und ein Teilnehmer nicht in zwei Städten wohnen kann. Würde man dagegen die Spalte teilnnr weglassen, würde es natürlich dann doppelte Datensätze geben, sobald mehrere Teilnehmer in der Stadt wohnen, in der ihr Unternehmen seinen Sitz hat. ¾ EXISTS würde in diesem konkreten Fall den Wert WAHR liefern, da ja tatsächlich in der Ergebnisrelation der Unterabfrage Datensätze enthalten sind. Es wird also nicht etwa der Wert UNKNOWN zurückgeliefert, sondern die oben gezeigte Menge an Datensätzen. ¾ NOT EXISTS liefert hier den Wert FALSCH. Nur bei einer leeren Ergebnisrelation würde der Wert WAHR zurückgeliefert werden.
Hinsichtlich der Unterstützung der einzelnen Prädikate lässt sich nur sagen, dass nicht alle DBS alle Prädikate gleichermaßen unterstützen. Einige werden sogar nur SOME und ALL unterstützen.
SQL
129
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
6.3.4 NULL und MATCH Wir hatten bereits im letzten Kapitel auf die besondere Verwendung von MATCH hingewiesen, um innerhalb einer Unterabfrage den Null-Wert zu suchen. MATCH ist kein Prädikat, um explizit oder ausnahmslos diesen Test durchzuführen, sondern verarbeitet NULL lediglich als einen eigenständigen Wert. MATCH besitzt darüber hinaus die fantastische Eigenschaft, einen so genannten Zeilenkonstruktor anzugeben, der dann mit verschiedenen Operatoren auf seine Existenz in der Unterabfrage geprüft wird. Mit unterschiedlichen Schlüsselwörtern kann man zudem das Suchverhalten dieser Funktion weiter quantitativ beeinflussen. Ein Zeilenkonstruktor ist in diesem Zusammenhang mit einem beispielhaften Datensatz zu vergleichen. Er weist also genau die Form einer einzelnen Tabellenzeile auf. Eigentlich bzw. in korrekter Sprache ausgedrückt, handelt es sich um eine Folge von skalaren Ausdrücken, die Sie im nächsten Projekt näher kennen lernen werden. Es handelt sich dabei letztendlich um das, was Sie bereits mehrfach in den Abfragen konkret verwendet haben, um ein Suchkriterium vorzugeben. In der hier gezeigten Anwendung begegnet Ihnen der Zeilenkonstruktor nur als eine einzige Zeile, aber er ist vielmehr als Folge solcher Zeilen definiert. Beide Varianten sind möglich, wobei ein einzeiliger Ausdruck keine Klammern benötigt, mehrere aber durch Klammern und Kommata getrennt werden. Alternativ kann er auch durch eine Unterabfrage entstehen. Dies schließt jetzt auch den Kreis zum eigentlichen Thema dieser Lektion und zur Funktion MATCH, weil sie ja genau auf Zeilenkonstruktoren bzw. Unterabfragen reagiert. ¾ Die allgemeine Syntax hat dabei die folgende Form: skalarer ausdruck1 |(skalarer ausdruck1 [, skalarer ausdruck2 [, ...]]) | unterabfrage ¾ Als Beispiel gilt die folgende Abfrage, wobei innerhalb der Unterabfrage ein Zeilenkonstruktor erzeugt wird: SELECT untnr, teilnnr, teilnstadt FROM teilnehmer WHERE = (SELECT unternehmen.untnr, teilnnr, teilnehmer.teilnstadt FROM unternehmen NATURAL JOIN teilnehmer WHERE untstadt=teilnstadt) Als Zeilenkonstruktoren würde dies für die ersten drei Zeilen der Unterabfrage folgendermaßen aussehen: (1, 3, „Sollbach“), (1, 6, „Sollbach“), (1, 9, „Sollbach“) Ein Zeilenkonstruktor der Form (1, 3, „Sollbach“)stellt also einfach den Inhalt des Datensatzes in der Form dar, wie ihn die Unterabfrage vorgibt. Die Funktion MATCH wiederum prüft anhand verschiedener Kriterien, ob dieser Datensatz überall in der Ergebnisrelation (also in allen Zeilen) oder nur teilweise (also in mindestens einer Zeile) vorliegt. Damit ergibt sich die allgemeine Syntax in folgender Form: zeilenkonstruktor MATCH [UNIQUE] | [PARTIAL | FULL] unterabfrage ¾ Wenn PARTIAL eingesetzt wird, ergeben sich unterschiedliche Konstellationen: Werden im Zeilenkonstruktor nur Null-Werte wie (NULL, NULL) vorgegeben, wird der Wert WAHR zurückgegeben. Ist UNIQUE vorgegeben, wird nur dann der Wert WAHR zurückgeliefert, wenn die Übereinstimmung mit dem Zeilenkonstruktor nicht nur in den Null-Werten erfolgt. Fehlt dagegen UNIQUE, wird auch bei bloßer Übereinstimmung mit dem Null-Wert der Wert WAHR zurückgeliefert.
130
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
¾ Wenn FULL verwendet wird, ergeben sich folgende Konstellationen: Ein Zeilenkonstruktor aus reinen Null-Werten liefert das Ergebnis WAHR. Ein gemischter Zeilenkonstruktor mit mindestens einem anderen Wert, liefert das Ergebnis FALSCH, wenn in der Unterabfrage dieser andere Wert nicht ebenfalls gegeben ist. Bei Einsatz von UNIQUE wird der Wert WAHR nur zurückgeliefert, wenn nur eine Zeile der Unterabfrage mit dem Zeilenkonstruktor übereinstimmt. Fehlt UNIQUE dagegen, wird das Ergebnis WAHR zurückgeliefert, wenn mindestens eine Zeile mit dem Zeilenkonstruktor übereinstimmt. In diesem Fall können also auch gleiche Zeilen erscheinen. ¾ Ist weder PARTIAL noch FULL angegeben, ergeben sich folgende Konstellationen: Wenn der Zeilenkonstruktor mindestens einen Null-Wert enthält, wird der Wert WAHR zurückgeliefert. Wenn UNIQUE verwendet wird und nur eine Zeile der Unterabfrage mit dem Zeilenkonstruktor übereinstimmt, wird der Wert WAHR zurückgeliefert. Fehlt dagegen UNIQUE, so wird der Wert WAHR auch dann zurückgeliefert, wenn mehrere Zeilen der Unterabfrage mit dem Zeilenkonstruktor übereinstimmen.
6.3.5 Duplikate in Unterabfragen Das Schlüsselwort UNIQUE hat neben dem Einsatz zur weiteren Qualifizierung der MATCH – Funktion auch noch die Fähigkeit, eine gesamte Unterabfrage darauf zu überprüfen, ob Duplikatzeilen entstanden sind. Auch wenn in der abgefragten Tabelle keine solchen Duplikate enthalten sind, kann es bei sehr ähnlichen Datensätzen geschehen, dass durch eine ungünstige Spaltenauswahl (z.B. durch fehlende Übernahme des Primärschlüsselfeldes, wenn nur dort die Einzigartigkeit des Datensatzes enthalten ist) Duplikate innerhalb einer Unterabfrage entstehen. Anhand der folgenden Abfrage soll das Grundproblem der Duplikatzeilen noch einmal ausführlich diskutiert werden. An einer Stelle wollten wir in jedem Fall auf dieses Grundproblem hinweisen, und diese Stelle scheint hier abschließend günstig. Das Konzept von UNIQUE ist dann verhältnismäßig trivial, da UNIQUE ja nur eine Unterabfrage testet, ob Duplikatzeilen enthalten sind. Sollte dies nicht der Fall sein, wird der Wert WAHR zurückgeliefert. Sind dagegen Duplikate vorhanden, entsteht der Wert FALSCH. Dabei wird der Null-Wert in zwei ansonsten gleichen Ergebniszeilen als nicht gleicher Wert interpretiert. Die hier diskutierte Abfrage hat folgende Form, wobei die unterschiedlichen Einstellungen, die auf die Duplikate Rücksicht nehmen, in eckigen Klammern angegeben sind. Sie soll die Frage beantworten, welche von den Kursen im Terminkalender überhaupt stattgefunden haben, also in irgendeiner Weise gebucht wurden. Man kann sie gleichzeitig oder in gemischter Form verwenden. Die einzelnen Varianten können Sie dann für ein noch besseres Verständnis selbst durchspielen. SELECT [DISTINCT] kurse.kursnr, kurse.titel, termine.ort FROM kurse NATURAL JOIN termine WHERE kurse.kursnr IN [UNIQUE] (SELECT buchungen.kursnr, kurse.titel FROM buchungen NATURAL JOIN kurse [GROUP BY buchungen.kursnr])
SQL
131
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
¾ Die Unterabfrage fragt rein inhaltlich die gesamte Tabelle buchungen ab, wobei allerdings die Kursnummer nicht reicht, sondern auch der Titel benötigt wird. Dieser wird dann über die Verknüpfung mit der Tabelle kurse ermittelt. In nebenstehender Abbildung sehen Sie das Abfrageergebnis ohne die Gruppierung. Die vielen Duplikatzeilen hängen mit der Tabellenstruktur zusammen, die ja jeden Teilnehmer einzeln speichert. Der in der Mitte angegebene Dreamweaver I – Kurs wurde also so oft (nicht unbedingt an einem einzigen Termin) durchgeführt, wie er ausgegeben wird. Das ist natürlich nicht unbedingt die Antwort auf die Frage, welche Kurse überhaupt stattgefunden haben. Sie lässt sich ausschließlich durch eine Gruppierung ermitteln. Das gruppierte Ergebnis verhindert die Duplikatzeilen und beantwortet exakt die oben gestellte Frage nach den Kursen, die überhaupt stattgefunden haben. ¾ Wird die nicht gruppierte Abfrage mit UNIQUE kombiniert, wird der Wert FALSCH zurückgeliefert. Es liegen ja schließlich besonders viele Duplikate vor. Bei der gruppierten Abfrage sieht es dagegen genau anders aus, weil die Gruppierung die Duplikate eliminiert. In diesem Fall wird der Wert WAHR zurückgeliefert. SELECT buchungen.kursnr, kurse.titel FROM buchungen NATURAL JOIN kurse [GROUP BY buchungen.kursnr] ¾ Die eigentliche Abfrage führt strukturell die gleiche Informationsbeschaffung wie die Unterabfrage durch, indem nämlich die Tabelle termine mit der Tabelle kurse abgeglichen wird. Der einzige Unterschied zur vorherigen Ergebnisrelation liegt darin, dass noch eine Spalte für den Ort, an dem der Kurs stattfinden sollte, entsteht. Da relativ viele Kurse mit verschiedenen Terminen angeboten werden, sind die Duplikate nicht so zahlreich, aber dennoch existent. (Nebenbei gesagt, ist deswegen auch die gesamte Abfrage interessant, da ein großer Unterschied zwischen stattgefundenen und angebotenen Kursen besteht.) In nebenstehender Abbildung sind die Duplikate nicht unterdrückt.
132
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
Möglichkeiten zur Unterdrückung dieser Duplikatzeilen, die sich nur deswegen ergeben, weil der gleiche Kurs an mehreren Terminen am gleichen Ort stattfindet und die Termine selbst gar nicht abgefragt werden, sind DISTINCT oder eine Gruppierung. In nebenstehender Abbildung sehen Sie das Ergebnis mit der Unterdrückung durch DISTINCT, in dem bspw. der XMLKurs nicht mehr doppelt auftritt. Da die Gruppierung allerdings nicht nur die Duplikate entfernt, sondern auch von zwei ähnlichen Datensätzen, die sich nur im Ort unterscheiden, lediglich den ersten Datensatz anzeigt, ist sie für diese Abfrage ungeeignet. SELECT [DISTINCT] kurse.kursnr, kurse.titel, termine.ort FROM kurse NATURAL JOIN termine WHERE kurse.kursnr IN [UNIQUE] unterabfrage
Mit dem Konzept der skalaren Unterabfragen hat man die Möglichkeit, überall dort eine (Unter-)Abfrage einzusetzen, wo genau ein Ausdruck erwartet wird. Diese Voraussetzung bedeutet, dass nur eine Unterabfrage mit genau einer Ergebnisreihe und einem Ergebnisfeld für die Weiterverarbeitung in der Abfrage gültig ist. Alle anderen Ergebnisse führen zu einer Fehlermeldung. Sie können auch im Spaltenaufruf in der SELECT – Klausel wie auch in der FROM – Klausel eingesetzt werden.
6.4 Sortierungen und Gruppierungen An dieser Stelle sollen noch einmal die verschiedenen Optionen, die SQL dem Programmierer für die Sortierung und Gruppierung in die Hand gibt, im Zusammenhang beschrieben werden. Insbesondere die Sortierungen von gruppierten Daten stellen ein noch nicht behandeltes Thema dar. Grundsätzlich verläuft die Sortierung in der Sortierungsliste so, dass die Spalten von links nach rechts, sodass also die erste genannte Spalte in der Liste auch die erste Spalte ist, die sortiert wird. Dies entspricht strukturell auch der Ausgabebehandlung, die ja durch die SELECT – Anweisung und ihre Spaltenliste erfolgt. Duplikate innerhalb der ersten sortierten Spalte werden vorrangig nach der zweiten Spalte sortiert. Null-Werte tauchen ganz oben in der Ausgabe auf und genießen damit einen Vorrang vor allen anderen Werten. Mit DESC kann man sie alle an das Ende der Ausgabe platzieren.
SQL
133
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
1. Die erste Möglichkeit, eine Spalte festzulegen, die für die Sortierung verwendet werden soll, ist ihr Aufruf über den Spaltennamen. Dies ist die Standardvariante, die Sie bisher auch immer gesehen haben. SELECT titel, preis, dauer FROM kurse WHERE preis BETWEEN 900 AND 1000 ORDER BY titel, preis 2. Die zweite Möglichkeit ist ihr Aufruf über die Spaltennummer in der Spaltenliste in der SELECT – Klausel. Dies ist natürlich auch prompt die unsicherste Variante. Eine Änderung in der Ausgabereihenfolge, die ja genau durch die Spaltenliste festgelegt wird, führt dazu, dass man ebenfalls die Nummerierung ändern muss, damit die Ausgabe und die Sortierung wieder ins Lot kommt. SELECT titel, preis, dauer FROM kurse WHERE preis BETWEEN 900 AND 1000 ORDER BY 1 3. Die dritte Variante besteht in einer Kombination aus beiden Möglichkeiten, wobei man also Spaltenname und Spaltennummern mischt. SELECT titel, preis, dauer FROM kurse WHERE preis BETWEEN 900 AND 1000 ORDER BY titel, 2 DESC Über die bisher nur sporadisch eingesetzte HAVING – Klausel besteht die Möglichkeit, durch GROUP BY gruppierte Daten und durch Aggregatfunktionen berechnete Daten erneut mit einem Suchkriterium zu belegen. Anders ist es nicht möglich, ein Suchkriterium auf eine Spalte anzuwenden, die durch eine Aggregatfunktion erzeugt wird. Wenn man also die nach Kursnummern gruppierte Analyse der Teilnehmerzahlen pro Kurs daraufhin untersuchen möchte, welche Kurse mit mehr als 20 Teilnehmern stattfanden, benötigt man genau ein solches Suchkriterium für die durch die Funktion COUNT erzeugte Spalte. SELECT buchungen.kursnr, kurse.titel, COUNT(buchungen.kursnr) AS Buchungen
134
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
FROM buchungen NATURAL JOIN kurse GROUP BY buchungen.kursnr HAVING Buchungen > 20
6.5 Werte in der WHERE – Klausel In die WHERE – Klausel sowie an anderen Stellen innerhalb einer Suchanfrage können höchst unterschiedliche Konstruktionen eingesetzt werden, um Werte vorzugeben. In dieser Lektion sollen noch einmal abschließend alle Möglichkeiten zusammengestellt werden. Tatsächlich gibt es nämlich noch weitere Hilfsmittel für die Abfragesteuerung, wobei hier die Implementation natürlich stets die erste Kontrollfrage sein muss, wenn man eine solche Konstruktion benutzen möchte.
6.5.1 Text und Zahlenwerte ¾ Zeichenketten Zeichenketten werden mit Hochkommata zusammengefasst und in die Abfrage aufgenommen. SELECT titel, preis, dauer FROM kurse WHERE
titel = ’PHP II (MySQL Programmbeispiele)’
¾ Numerische Werte Alle Zahlenwerte kann man mit einem Punkt als Komma und einem E als Exponentsymbol in der allgemeinen Form [zzz][[.]zzz][E[+|-]zzz] eingeben. Dabei erkennt SQL bzw. das Datenbanksystem automatisch Zahlen ohne Komma als zum Datentyp Integer gehörig, Zahlen mit Komma und ohne Exponent als Decimal und Zahlen mit Exponent als Float. SELECT titel, preis, dauer FROM kurse WHERE
preis = 920
¾ Daten Daten können Sie normalerweise in der praktischen Anwendung in der Form verwenden, wie sie in der Datenbank gespeichert sind. In Standard SQL allerdings gibt es einige Schlüsselwörter, die die folgende Zeichenkette als zu diesem Datentyp zugehörig klassifizieren. SELECT titel, beginn, ort FROM kurse WHERE
beginn = DATE 2002-06-15
¾ Datum -- DATE 'yyyy-mm-dd' ¾ Zeit -- TIME 'hh:mm:ss[.fff]' ¾ Zeitstempel -- TIMESTAMP 'yyyy-mm-dd hh:mm:ss[.fff]' ¾ Intervall -- INTERVAL [+|-] Zeichenkette. Die Zeichenkettenstruktur hängt vom Intervalltyp ab wie z.B. [dd[-dd] (Jahr-Monat) oder [dd ]dd[:dd[:dd]][.fff] (Tag-Zeit).
SQL
135
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
6.5.2 System-Variablen Zu erwarten, dass exakt die von SQL propagierten System-Variablen auch in einem DBS umgesetzt sind, empfiehlt sich sicherlich nicht. Tatsächlich aber hat jedes System ähnliche Konzepte entwickelt, die teilweise auch den Standard-Namen entsprechen. Dabei unterscheidet sich allerdings sehr deutlich die Anzahl der verfügbaren System-Variablen. Sie speichern Werte über den Benutzer, die Länge der Arbeitszeit mit der Datenbank, die aktuelle Systemzeit, die Anzahl der ausgeführten Befehle und viele andere Informationen mehr. Diese Variablen speichern also in einem bestimmten Format einen Wert, der ebenso in Abfragen eingesetzt werden kann. ¾ USER – liefert eine Zeichenkette mit der vom System vergebenen Autorisation zurück. ¾ CURRENT_USER -- entspricht USER. ¾ SESSION_USER – liefert eine Zeichenkette mit der SQL-Session-Autorisation zurück. ¾ SYSTEM_USER – liefert eine Zeichenkette mit der Betriebssystem-Autorisation zurück. ¾ CURRENT_DATE – liefert eine Zeichenkette mit dem aktuellen System-Datum zurück. ¾ CURRENT_TIME – liefert eine Zeichenkette mit der aktuellen System-Uhrzeit zurück. ¾ CURRENT_TIMESTAMP – liefert eine Zeichenkette mit dem aktuellen Zeitstempel zurück. Die Anwendung erfolgt so, als ob der in den System-Variablen gespeicherte Wert direkt zur Verfügung steht. Dies bedeutet, man ruft einfach die Variable innerhalb der WHERE – Klausel auf: SELECT titel, beginn, ort FROM kurse WHERE
beginn >= CURRENT_DATE
6.5.3 Skalare Funktionen Im nächsten Projekt werden Sie unterschiedliche Funktionen kennen lernen, mit denen man Daten aggregieren und somit z.B. Summen bilden oder Durchschnitte berechnen kann. Diese Funktionen beziehen sich auf die gesamte Spalte, während mit den in diesem Abschnitt beschriebenen skalaren Funktionen Werte innerhalb eines Feldes verarbeitet werden. Nachdem eine solche Funktion einen Wert verarbeitet hat, kann er wieder an die Abfrage zurückgegeben und in ihr weiterverwendet werden. Wir möchten Ihnen diese Funktionen ganz besonders für die Verwendung im Rahmen von Programmen empfehlen, da man sich mit ihnen viele Scherereien oder Umstände erspart, wenn man bestimmte Anforderungen an die Ergebnistabelle hat. Neben der Verwendung in Abfragen ist es nämlich mit diesen Funktionen insbesondere möglich, Zeichenkettenfunktionen in der jeweiligen Programmiersprache für einige Standardanwendungen komplett zu vermeiden. Insbesondere das Beispiel zur Extraktion des Datumsformats könnte Ihnen zeigen, wie elegant eine solche SQL-Abfrage im Gegensatz zu einer selbst geschriebenen Umwandlungsfunktion ist. Daher haben wir versucht, die Beispiele weitestgehend aus diesem Bereich zu nehmen. Folgende Funktionen existieren: ¾ SUBSTRING(zk FROM beginn [FOR länge]) – Diese Funktion extrahiert aus einer Zeichenkette zk vom Punkt beginn (als Zahlenwert) an einen Teil der Länge von länge (ebenfalls als Zahl). Die Längenangabe ist optional, sodass der komplette Rest der Zeichenkette in das Ergebnis einfließt, wenn sie fehlt. Nach der Extraktion liefert die Funktion den ermittelten Teil der Zeichenkette zurück. Diese Funktion eignet sich bspw. für Situationen, in denen man am Ende eine Spalte mit Abkürzungen benötigt. So könnte man
136
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
aus Gründen der Übersichtlichkeit die Städtenamen im Terminkalender auf drei Buchstaben zusammenstreichen. SELECT titel, beginn, SUBSTRING(ort FROM 1 FOR 3) FROM kurse NATURAL JOIN termine WHERE kurse.kursnr = 40314 SELECT titel, beginn, SUBSTRING(ort FROM 1 FOR 3) FROM kurse NATURAL JOIN termine ¾ UPPER(zk) – Diese Funktion wandelt eine Zeichenkette zk zu Großbuchstaben um und liefert diese umgewandelte Zeichenkette zurück. Für eine Teilnehmerliste könnte man sich ein Ausgabeformat wünschen, in dem die Nachnamen automatisch alle in Großbuchstaben erscheinen. Natürlich möchten Sie diese nicht vorher schon so eingegeben haben. Daher bietet sich die Verwendung dieser Funktion an, die alle Nachnamen wunschgemäß umsetzt.
SELECT buchungen.teilnnr, UPPER(teilnnachname), teilnvorname FROM buchungen NATURAL JOIN teilnehmer WHERE buchungen.kursnr = 40314 ¾ LOWER(zk) - Diese Funktion wandelt eine Zeichenkette zk zu Kleinbuchstaben um und liefert diese umgewandelte Zeichenkette zurück. Genau das Gegenteil wie im vorigen Beispiel erreicht man mit dieser Funktion, die die Städtenamen alle in Kleinbuchstaben ausgibt. SELECT titel, beginn, LOWER(ort) FROM kurse NATURAL JOIN termine WHERE kurse.kursnr = 40314 In diesem Anwendungsfall macht es vielleicht keinen richtigen Sinn, aber in Kombination mit einer verkürzten Ausgabe des Städtenamens in der obigen Drei-Buchstaben-Form könnte es tatsächlich die Lesbarkeit stark erhöhen. Dabei kombiniert man beide Funktionen so miteinander, dass die verkürzte Zeichenkette verkleinert wird, indem LOWER auf SUBSTRING angewandt wird. SELECT titel, beginn, LOWER(SUBSTRING(ort FROM 1 FOR 3)) FROM kurse NATURAL JOIN termine
SQL
137
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
WHERE kurse.kursnr = 40314 Auf einer Webseite könnte man dann eine kleine Legende anbringen, welche Stadt mit welcher Abkürzung gemeint ist. Diese Legende erzeugt man natürlich ebenfalls nicht mit geschickter Programmierung und verschiedenen Funktionen, sondern mit einer geschickten Abfrage, damit die Legende durch die Abfrage immer aktuell ist. SELECT LOWER(SUBSTRING(ort FROM 1 FOR 3)) AS Abkürzung, ort AS Veranstaltungsort FROM termine GROUP BY Veranstaltungsort ¾ TRIM([LEADING|TRAILING|BOTH] [FROM] zk) | TRIM([LEADING|TRAILING|BOTH] zk2 FROM zk1) – Diese Funktion entfernt führende (leading), folgende (trailing) Leerzeichen oder beides (both) aus einer Zeichenkette zk1. Wenn zk2 angegeben ist, gilt dies als Zeichen, das entfernt werden soll. Der Standardwert ist both. Nach der Verarbeitung liefert sie die gekürzte Zeichenkette zurück. ¾ POSITION(zk1 IN zk2) – Diese Funktion sucht eine Zeichenkette zk1 in einer anderen Zeichenkette zk2. Sie liefert eine Ganzzahl mit der Position zurück, an der die gesuchte Zeichenkette beginnt. Bleibt die Suche erfolglos, übermittelt die Funktion eine 0. Ist eine der beiden Zeichenketten NULL, so wird auch NULL zurückgegeben, während eine 1 zurückgeliefert wird, wenn zk1 nur NULL ist. ¾ CHAR_LENGTH(zk1) | CHARACTER_LENGTH(zk1) – Diese Funktion liefert eine Ganzzahl zurück, die die Anzahl der Zeichen in zk1 enthält. Ist zk1 NULL, so ist auch das Ergebnis NULL, während eine leere Zeichenkette den Wert 0 zurück übermittelt. Zeichenkettenlängen erscheinen evt. zunächst nicht allzu wichtig, doch kann man sie als Kontrollwerkzeug für Felder einsetzen. Wenn man z.B. herausfinden möchte, wie viel Text in der Datenbank gespeichert ist, wenn es gerade nicht um solche Felder wie Nachnamen oder – noch langweiliger Postleitzahlen geht, kann man diese Funktion einsetzen. SELECT CHAR_LENGTH(titel) FROM kurse SELECT titel, CHAR_LENGTH(themen) FROM kurse
138
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
Mit dieser Technik könnte man in einer ersten, einfachen Auswertung festlegen, dass die Themenliste höchstens 300 Zeichen umfassen soll. Um den freien Platz zu bestimmen, subtrahiert man von diesem maximalen Platz den belegten und erhält ein interessantes Ergebnis: Für XML wurden noch gar keine Themen vergeben (NULL wird oben ausgegeben und entspricht nicht 0), während bei MS Exchange leider 8 Zeichen zuviel (errechneter Wert ist –8) eingetragen sind. SELECT titel, 300-CHAR_LENGTH(themen) AS FreierPlatz FROM kurse ORDER BY FreierPlatz ASC ¾ OCTET_LENGTH(zk1) – Diese Funktion liefert die Anzahl der Bytes (8-Bit-Tupel) zurück, die die Zeichenkette zk1 als Speicherplatz benötigt. Ist zk1 NULL, so ist auch das Ergebnis NULL, während eine leere Zeichenkette den Wert 0 zurück übermittelt. Das oben im Anriss demonstrierte DBControlling-Tool lässt sich durch die hier vorgestellte Funktion ebenso in belegten Speicherplatz umwandeln. Durch geeignete Umrechnungen kann man dabei sogar in der Ausgabe von Bytes nach KB oder MB wechseln, wenn dies als Vergleichsmaßstab eingängiger erscheint. Folgende Abfrage ermittelt daher den belegten Speicherplatz in Bytes der Spalte themen für jeden einzelnen Kurs. SELECT titel, OCTET_LENGTH(themen) FROM kurse ¾ EXTRACT(feld FROM zk1) – Diese Funktion gibt aus einem Zeit- oder Datumswert den numerischen Betrag des Bereichs feld zurück. Dabei ist feld: YEAR, QUARTER, MONTH, DAY, HOUR, MINUTE, SECOND, TIMEZONE_HOUR oder TIMEZONE_MINUTE. Als glänzender Abschluss der skalaren Funktionen soll die folgende Abfrage gelten, die eine Tabelle mit den Kursen im Juni und dabei zusätzlich den Kursbeginn nur mit dem Tagesdatum ausgibt. Dabei verwendet man sowohl im Spaltenaufruf als auch in der Suchbedingung die Funktion EXTRACT, wobei beim ersten Mal nur das Tagesdatum und beim zweiten Mal nur die Monatsnummer 6 ausgewählt wird. An welcher Stelle die Werte stehen, ist dabei egal, da dies im Datenformat des DBS gespeichert ist. SELECT titel, EXTRACT(DAY FROM beginn), ort FROM kurse NATURAL JOIN termine
SQL
139
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
WHERE EXTRACT(MONTH FROM beginn)=6
6.5.4 Ausdrucks-Operatoren Bis auf die sehr nützliche Verknüpfung der Spalten innerhalb der Ergebnistabelle sind die verschiedenen Operatoren, die einzelne Ausdrücke miteinander verknüpfen und dadurch z.B. auch Berechnungen ermöglichen, ein wenig in den Beispielen untergegangen. Wir werden sie hier nicht noch einmal mit Beispielen darstellen, sondern nur kurz zusammenfassen. ¾ Numerische Operatoren Sie ermöglichen die Berechnung von Werten innerhalb des Spaltenaufrufs in der SELECT – or der WHERE – Klausel, wobei der berechnete Wert in die Abfrage eingeht. Folgende Möglichkeiten stehen zur Verfügung, wobei die Beispiele aus den bereits an anderer Stelle gezeigten Abfragen stammen. Berechnung
Operator
Beispiel
Summe
+
dauer+1
Differenz
-
dauer-1
Produkt
*
preis*1.25
Division
/
dauer/preis
Tab.1: Numerische Operatoren Die numerischen Operatoren können auf die verschiedenen Zahlendatentypen angewandt werden, wobei eine automatische Typumwandlung durchgeführt wird. So ist z.B. bei der Erhöhung des Preises um 25 % das Ergebnis des eingehenden Integer-Wertes der Spalte preis keine Ganzzahl mehr, sondern automatisch vom Typ FLOAT. In Grenzen und je nach Datenbanksystem kann man numerische Operatoren auch auf Zeitdatentypen anwenden. Bei der Differenz entsteht dann der Datentyp INTERVAL. ¾ Zeichenketten-Operatoren Mit Hilfe des Operators || können Werte von Zeichenkettendatentypen so miteinander verknüpft werden, dass atomisierte Attribute wieder in einer einzigen Spalte ausgegeben werden. In nebenstehender Abbildung sehen Sie das Ergebnis für eine Teilnehmerliste, die zwar die wichtigsten Teilnehmerinformationen ausgibt, dabei allerdings nur drei Spalten benötigt. Wichtig ist dabei, bereits in der Abfrage zu berücksichtigen, wie das spätere Format in der Ergebnistabelle eigentlich aussehen soll. Im konkreten Fall einer Adressenliste muss man bspw. an die einzelnen Leerzeichen zwischen zwei Wörtern denken und an das Wort Nr. für die Hausnummer. SELECT (teilnvorname || " " || teilnnachname) AS Name, (teilnstrasse || " Nr. " || teilnhausnr) AS Adresse, (teilnrplz || " " || teilnstadt) AS Stadt FROM teilnehmer
140
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
Im Fall von MySQL funktioniert dieser Operator nicht für die Zeichenkettenverknüpfung, sodass man sich der speziellen Funktion CONCAT bedienen muss. Eventuell müssen Sie dies auch für Ihre Testumgebung nachprüfen. SELECT CONCAT(teilnvorname," ",teilnnachname) AS Name, CONCAT(teilnstrasse," Nr. ",teilnhausnr) AS Adresse, CONCAT(teilnrplz, " ",teilnstadt) AS Stadt FROM teilnehmer
6.5.5 Bedingungen mit CASE Mit CASE kann ebenfalls ein Ausdruck erzeugt werden, wobei hier die Möglichkeit besteht, Änderungen in der Ausgabe anhand von unterschiedlichen Fällen vorzugeben. Die allgemeine Syntax lautet: CASE WHEN bedingung1 THEN ergebnis1 WHEN bedingung2 THEN ergebnis2 [ELSE ergebnis3] END Als Beispiel könnte man sich überlegen, die einzelnen Kurse der Tabelle kurse einer Preiskategorie zuzuordnen: SELECT titel AS Titel, CASE WHEN preis <=500 THEN 1 WHEN preis >500 AND <=800 THEN 2 WHEN preis >800 THEN 3 ELSE 4 END Preiskategorie FROM kurse
6.5.6
Zusammenfassung
9 Informationen, die sich nur aus der Verknüpfung mehrerer Tabellen ergeben, werden erzeugt, indem die benötigten Tabellen über ihre Primärschlüssel-Fremdschlüssel-Beziehung verbunden werden. 9 Die Verknüpfungsmöglichkeiten von Tabellen beruhen auf der relationalen Algebra, die mit einfachen Basisoperationen die Vorgänge und Voraussetzungen für die Verknüpfungen beschreibt.
SQL
141
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
9 Spaltennamen, die in mehreren Tabellen erscheinen, müssen qualifiziert werden, indem vor diese mit einem Punkt der Name der Tabelle gesetzt wird. Es müssen nur die uneindeutigen Spalten qualifiziert werden, sodass gemischte Namensgebung erlaubt ist. 9 Verschiedene Spaltenfunktionen für Summen- und Mittelwertsbildung sowie für Vergleiche des größten oder kleinsten Wertes sowie für Reihenzählungen können an verschiedenen Stellen der Abfrage platziert werden. Sie liefern in ihrer Grundform einen einfachen Wert – das Ergebnis – als Ergebnistabelle zurück. 9 Eine Unterabfrage stellt eine Abfrage dar, deren Ergebnis wiederum für eine andere Abfrage als Vergleich bzw. als Kriterium innerhalb der WHERE – Klausel notwendig ist. Dabei wird sie mit den Operatoren, die typischerweise in der WHERE – Klausel verwendet werden, an die Abfrage angeschlossen. 9 Unterabfragen können mit Prädikaten kombiniert werden, die einen quantitativen Vergleich oder eine Existenzüberprüfung der Ergebnisrelation der Unterabfrage durchführen.
6.5.7
Übungen
1. Geben Sie die Buchungsnummern, Kursnummern, Teilnehmernachnamen und den Kurstitel für die gebuchten PHP-Kurse aus. Es sollen dabei alle PHP-Kurse gefunden werden. 2. Finden Sie alle gebuchten PHP I – oder SQL-Kurse und geben Sie dafür die Buchungsnummer, die Kursnummer, die Teilnehmernummer und den genauen Kurstitel aus. 3. Führen Sie eine Deklination (wie bei unregelmäßigen Verben!) durch die einzelnen JoinArten für die Tabelle unternehmen und teilnehmer durch. Das Feld untnr dient dabei der Beziehung. CROSS JOIN und INNER JOIN sollen ohne weitere Einschränkung durchgeführt werden, aber für LEFT OUTER JOIN und INNER OUTER JOIN sollen nur Nachname mit einem „A“ als erstem Buchstaben ausgegeben werden. 4. Warum sind die Ergebnisse der letzten beiden Verknüpfungen der vorherigen Aufgabe gleich? Erklären Sie dies mit den Eigenschaften der Join-Arten und den Strukturen der Tabellen. 5. Wie könnten Sie die beiden Abfragen und ihr Verhalten bzgl. Null-Werten leicht testen? Führen Sie dann diese beiden Abfragen durch und kommentieren Sie das Ergebnis. 6. Welche Teilnehmer haben die gleiche Hausnummer? Geben Sie das Ergebnis so aus, dass nur Teilnehmer mit ihrem Nachnamen und ihrer gleichen Hausnummer untereinander stehen. Vermeiden Sie Duplikate und schließen Sie aus, dass gleiche Teilnehmer gefunden werden. Fällt Ihnen bei der Sortierung der Hausnummernspalte eine Besonderheit auf? 7. Zählen Sie die Anzahl der Teilnehmer in der Tabelle teilnehmer. Belassen Sie einmal den Spaltennamen des Ergebnisses und nennen Sie ihn einmal AnzahlDerTeilnehmer.
142
SQL
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
UND
FUNKTIONEN
8. Welche Kurse dauern länger als die durchschnittliche Kursdauer? Geben Sie sowohl die komplette Abfrage als auch die Unterabfrage und die Abfrage einzeln an. 9. Wie viele Teilnehmer schickte welches Unternehmen in welchen Kurs? Sortieren Sie anhand der Teilnehmerzahlen, sodass der erfolgreichste Kurs an der ersten Stelle erscheint. 10. Welche Kurse wurden noch nie gebucht? Vergleichen Sie dabei nicht die überhaupt vorhandenen Kurse in der Tabelle kurse, sondern vielmehr die Kurse in der Tabelle termine, die nicht genutzt wurden. Geben Sie auch wiederum die komplexe Abfrage und die einzelnen Abfragen aus.
SQL
143
KOMPLEXE ABFRAGEN, UNTERABFRAGEN
144
UND
FUNKTIONEN
SQL
7 Abfragen in virtuellen Tabellen speichern
SQL
145
ABFRAGEN
146
IN VIRTUELLEN
TABELLEN
SPEICHERN
SQL
ABFRAGEN
IN VIRTUELLEN
7 Abfragen in virtuellen Tabellen speichern Dieses Projekt soll nun das Schlusslicht, allerdings im Vergleich zum letzten Projekt sicherlich nicht das Sternenlicht zum Themenkreis der Abfragen bilden. Mit dem Prinzip der virtuellen Tabellen, die sich in die Sichten (Views) und die Kurzaufnahmen (Snapshots) unterteilen lassen, werden die zuvor erlernten Techniken so mit neuen Befehlen kombiniert, dass die Ergebnisse einer Abfrage schneller vom DBMS ausgegeben werden können als sonst. Nicht nur im Controlling, sondern auch bei der Webprogrammierung stellt sich dabei regelmäßig der Wunsch, häufige Abfragen dem Benutzer optimal zur Verfügung zu stellen.
TABELLEN
SPEICHERN
Lernen Sie die einzelnen Tabellentypen und ihre Charakteristiken kennen den Unterschied zwischen Sichten und Kurzaufnahmen kennen Abfragen als typische Kandidaten für virtuelle Tabellen zu identifizieren Sichten anzulegen Änderungen über Sichten durchzuführen Kurzaufnahmen anzulegen
7.1 Grundprinzip der virtuellen Tabelle Bis jetzt haben wir unser Augenmerk noch nicht auf die Tabelle selbst, sondern nur auf ihre Inhalte gelenkt. Tatsächlich jedoch kann man die Tabelle als solche in vier unterschiedliche Kategorien differenzieren, von denen Sie bisher schon die realen Tabellen und die Ergebnistabelle kennen gelernt haben. Alternative Ausdrücke waren hier auch Basisrelation und Ergebnisrelation. Insgesamt kann man aber noch weitere Tabellentypen unterscheiden, die für das Verständnis der beiden neuen Konzepte in diesem Projekte von Bedeutung sind. Sie werden wie folgt charakterisiert: ¾ Reale Tabelle: Für die reale Tabelle speichert die Datenbank sowohl ihre Struktur als auch die Daten physisch auf dem verwendeten Datenträger. ¾ Ergebnistabelle: Sie zählt zu den temporären Tabellen. Durch eine Abfrage gibt die Datenbank ein Ergebnis in Form einer weiteren Tabelle aus, die nur so lange vorhanden ist, wie die Abfrage selbst verwendet. Im Fall einer Webseite entspricht dies der Übermittlung an das Programm, das mit seiner Abarbeitung die HTML-Tabelle erzeugt. Als Struktur kann man den Abfragebefehl bezeichnen, der eine spezielle Form von Spalten und – gemäß der Treffer – eine bestimmte Anzahl an Zeilen erzeugt.
SQL
147
ABFRAGEN
IN VIRTUELLEN
TABELLEN
SPEICHERN
¾ Temporäre Tabelle: Zu den temporären Tabellen zählen sowohl die Ergebnistabelle als auch die Sicht. Nach Sitzungsende oder nach Übermittlung der Ergebnistabelle werden Struktur und Daten gelöscht. ¾ Virtuelle Tabelle: Für eine solche Tabelle existiert nur die Strukturbeschreibung z.B. mit Hilfe eines Abfragebefehls. Beim Aufruf einer solchen Strukturbeschreibung wird der ihr zu Grunde liegende Abfrage-Befehl ausgeführt, sodass aus den realen Tabellen die Ergebnistabelle erzeugt wird. Dies ist der typische Fall für Sichten.
7.1.1 Funktionsweise von virtuellen Tabellen Die Prinzipien für Sichten (Views) und Kurzaufnahmen (Snapshots) ähneln sich in einigen Punkten, während sie in ihren Unterschieden sogar besonders weit auseinander liegen. Eine Sicht speichert einen Abfrage-Befehl so, dass er über das Aufrufen des Datenbankobjekts ausgeführt wird. Dabei kann man sich diesen Vorgang so illustrieren, wie es die nebenstehende Abbildung versucht. Die Abfrage der virtuellen Tabelle schwebt sozusagen über der Struktur der realen Tabelle und schlägt dann quasi aus dem Hinterhalt zu, wenn ein Benutzer diese Sicht abruft. Die Tabelle in der Abbildung wird also von zwei Sichten scharf beobachtet, von denen die eine sämtliche Tupel der zweiten und dritten Spalte auswählt, während die andere sich ausschließlich um die beiden vorletzten Datensätze sorgt. Die Besonderheit für die Sichten liegt dabei in diesem Beobachtungsstatus, der Änderungen innerhalb des Datenbestandes berücksichtigt. Wenn also für die zweite Abfrage die Kriterien innerhalb der WHERE – Klausel nicht mehr vom vorletzten Datensatz erfüllt werden, verschwindet der Datensatz auch aus der Sicht bzw. aus ihrer Anzeige. Innerhalb einer Sicht werden die Daten selbst also nicht physisch gespeichert, sondern es liegen lediglich die Abfrageoperationen gespeichert vor, die auf reale Tabellen angewandt werden. Im Vergleich zu den Sichten ergibt sich bei den Kurzaufnahmen (Snapshots), dass sie eine einmal durchgeführte Abfrage darstellen, also insoweit wiederum die Abfragestruktur speichern und sie als Definition des Objekts benötigen, dass sie des Weiteren jedoch keine Änderungen an den Daten mehr zulassen. Ist die Kurzaufnahme durchgeführt, kann sie zwar immer wieder mit den in der logischen Sekunde der Erstellung gefundenen Daten aufgerufen werden, aber diese Daten bleiben statisch. Damit stellen sie also ganz sinnbildlich tatsächlich den Zustand der Datensätze dar, die zu einem bestimmten Zeitpunkt die Suchbedingungen der Abfrage erfüllten.
7.1.2 Überlegungen zu Einsatzbereichen Einige allgemeine Vorteile zur Bildung von virtuellen Tabellen zur Generierung automatischer Abfragen, die bereits durch den DB-Administrator formuliert und daher von der Ergebnisstruktur bekannt sind, lassen sich auf unterschiedlichen Ebenen finden: ¾ Abfragen werden stark vereinfacht. Sie haben bereits selbst gesehen, dass Abfragen mit nur drei Tabellen sehr umfangreich werden können. In einer wirklich realistischen Kontaktverwaltung wie z.B. MS Outlook kann man sicherlich für einen einzigen Datensatz mehr als 50 verschiedene Attribute zählen. Wenn man dann für die Abfrage, wer zu welchem Termin eingeladen ist, drei Tabellen und insgesamt vielleicht 30 Spaltennamen aufrufen muss, entstehen voll-
148
SQL
ABFRAGEN
IN VIRTUELLEN
TABELLEN
SPEICHERN
kommen unübersichtliche Quelltexte. Bei einer Sicht entstehen sie dagegen nur ein einziges Mal. Danach werden sie leicht über den Namen der Sicht aufgerufen. ¾ Man besitzt eine mehr auf Datenbankseite liegende Möglichkeit der Entkoppelung, um z.B. in Programmiertext den Datenbankbefehl kurz und einfach zu halten. Wenn für die häufige Verwendung einer Abfrage eine Sicht eingesetzt wird, kann man die Sicht auf DB-Ebene ändern, ohne dass man extra den Programmiertext z.B. für eine dynamische Webanwendung ebenfalls ändern müsste. Man kann über den Einsatz von Sichten einen weiteren Teil des Quelltextes auslagern. Mit Blick auf den DB-Benutzer ergibt sich hier eine Möglichkeit, Fehlerquellen an der Schnittstelle zur DB, die über die Abfragen geleistet wird, stark zu reduzieren und die Arbeit mit der DB insgesamt zu stabilisieren. ¾ Wenn auch Zugriffsschutz und Berechtigungen noch ein eigenes SQL-Thema darstellen werden und natürlich über Login-Programmierungen und Authentifizierungen mit weiteren Hilfsmitteln und in mehreren Ebenen (Berechtigungsstufen) gelöst werden kann, so stellen die Sichten eine weitere Methode für den Zugriffsschutz dar. Der DB-Administrator kann durch die Gestaltung von standardisierten Abfragen in Sichten, die allein aufgerufen werden können, dem Benutzer die Möglichkeit nehmen, selber mit beliebigen Abfragen im Datenbestand zu forschen. ¾ Wenn sämtliche Abfragen vom DB-Administrator zentral in Sichten gespeichert werden, erlaubt das ihm auf sehr elegante Weise, Änderungen an der Daten- und DB-Struktur vorzunehmen, ohne dass es dem Benutzer direkt auffällt. Gleichzeitig mit dem Ändern der Datenstruktur ändert er die Sichten, sodass sich für den Benutzer – sofern die Sichten nicht gesperrt oder sonstwie obsolet werden – nichts ändert. Schwierigkeiten treten dagegen sofort auf, wenn man Benutzern die Möglichkeit gibt, selbstständig Module für Abfragen zu erstellen, da ihnen dann Änderungen in der Datenstruktur zur Aktualisierung mitgeteilt werden müssen. Je nach Komplexität der Modifikationen können dabei auch falsche Resultate entstehen, die nicht sofort als solche identifizierbar sind.
Die virtuellen Tabellen stellen damit im zu Anfang beschriebenen 3-Schichten-Modell eine gültige externe Sichtweise der Datenbank dar. Genauso sollte man sie auch in der DBProgrammierung anwenden, um größtmöglichen Nutzen aus ihnen zu ziehen.
Sinn und Zweck für Kurzaufnahmen ergeben sich insbesondere unter dem Blickwinkel der Kontrolle oder gesetzlicher Vorgaben. Wenn die Buchhaltung datenbankbasiert abläuft, könnte die Bilanz als Kurzaufnahme bezeichnet werden, da sie 10 Jahre lang unverändert aufgehoben werden muss (§ 257 HGB). Sie wird einmal erstellt und abgespeichert, kann danach aber nur in der so gespeicherten Form und mit den Datensätzen, die zur Erstellungszeit die Suchkriterien erfüllten, betrachtet werden. Eine Sicht dagegen führt jedes Mal neu zum Zeitpunkt des Aufrufs die gespeicherten Abfrageoperationen durch, sodass es günstig ist, häufig vorkommende Abfragen als Sicht zu speichern. Dies erhöht die Arbeitsgeschwindigkeit und erleichtert auch den Aufruf, wenn er manuell z.B. in den Programmiertext eingegeben wird.
7.2 Sichten anlegen und löschen Der Hauptteil der Programmierarbeit besteht eigentlich in der Erstellung der Abfrage, wie wir sie bereits in den zurückliegenden drei Projekten ausführlich (sozusagen in elegischer Breite) diskutierten. Damit von dieser Seite keine Verständnisschwierigkeiten auftreten, übernehmen wir in den
SQL
149
ABFRAGEN
IN VIRTUELLEN
TABELLEN
SPEICHERN
folgenden Beispielen genau diese Abfragen oder modifizieren sie nur leicht. So sticht das eigentlich Interessante besser ins Auge. Die Syntax, um eine Sicht zu erstellen, ergibt sich in folgendem Schema: CREATE VIEW sichtname [{spalte1, spalte2,...] AS abfrage [WITH [CASCADED | LOCAL] CHECK OPTION] Die Bestandteile des an sich unspektakulären Befehls lassen sich mit den nächsten Punkten gliedern: ¾ Strukturell lässt sich die Vorgehensweise in zwei Abschnitte zerlegen. Zunächst wird in der ersten Zeile mit CREATE VIEW das Relationenschema definiert, wobei das entweder explizit durch die Nennung von Spaltennamen oder implizit durch die Struktur der Abfrage geschieht. ¾ Spaltennamen können innerhalb der Sichten anders heißen als in denen der Abfrage zu Grunde liegenden Tabellen. Werden keine uneindeutigen Spaltennamen erzeugt wie z.B. bei der Verwendung von Aggregatfunktionen, können sie auch aus der Abfrage übernommen werden. Es ist nicht möglich, sich auf einige Spalten zu beschränken. Wenn mindestens eine Spalte explizit benannt wird, müssen alle Spalten genannt werden. ¾ Mit dem Schlüsselwort AS schließt sich sodann die Abfrage an. Dies ist der grundlegende zweite Schritt, da hier die Operationen vorgegeben werden, mit denen die Sicht erzeugt werden soll. Sie kann im Vergleich zu den anderen Befehlszeilen ungleich länger sein. ¾ Zum Schluss bieten sich noch diverse Optionen für die Berücksichtigungen von Überprüfungen an, die durchgeführt werden, sobald die Sicht aufgerufen wird. Dies kann sich z.B. auf eine Überprüfung beziehen, die bei einer Aktualisierungssicht (auch das ist möglich) die Regeln der Domänen beachtet. Die beiden attributiven und fakultativen Schlüsselwörter regeln dann den Abarbeitungsmodus bzgl. der Überprüfung.
Sichten werden nicht von allen DBS unterstützt. Neben dieser globalen Einschränkung bestehen in den einzelnen DBS noch weitere hinsichtlich der Möglichkeiten der SELECT – Anweisung. Das schmälert insgesamt auch wiederum den Nutzen der gesamten Vorgehensweise. Standardmäßig darf der ORDER BY – Befehl nicht verwendet werden. Hier müssen Sie sich also auch zunächst informieren, welche Möglichkeiten Sie bei Ihrem DBMS besitzen, um in einer Sicht eine Abfrage zu erstellen.
1. Die einfachste Form besteht daraus, für die Abfrage einer einzelnen Tabelle nur einen Namen der Sicht vorzugeben. In diesem Fall werden die Spaltennamen aus der Abfrage für die Spaltennamen der Sicht übernommen. CREATE VIEW Kursangebot AS SELECT titel, bereich FROM kurse 2. In einer ersten Erweiterung kann man auf die Übernahme der Spaltennamen aus der Abfrage verzichten und eigene Spaltennamen vorgeben. Sie werden wie in der all-
150
SQL
ABFRAGEN
IN VIRTUELLEN
TABELLEN
SPEICHERN
gemeinen Syntax gezeigt in der Reihenfolge ihres Auftretens in der Abfragetabelle in Klammern an den Sichtnamen angeschlossen. Hier muss man Acht geben, dass die Titelliste für die Sicht mit dem Spaltenaufruf in der Abfrage sinnvoll übereinstimmt. CREATE VIEW Kursangebot (Titel, Bereich) AS SELECT titel, bereich FROM kurse 3. Bei nicht eindeutigen Spaltennamen kann es zu Schwierigkeiten kommen, sobald die Relation implizit erzeugt werden soll. Dies kann sich gerade bei Spaltenfunktionen ergeben, wobei eine einfache Hilfe ein Aliasname bei der Verwendung der Funktion darstellt. Dies schafft allerdings wenig Übersichtlichkeit im Quelltext. CREATE VIEW Kursbesuche AS SELECT buchungen.teilnnr, teilnvorname, teilnnachname, COUNT(buchungen.teilnnr)AS Kursbesuche FROM buchungen NATURAL JOIN teilnehmer GROUP BY buchungen.teilnnr 4. Eine sehr übersichtliche Lösung findet man, wenn die Spaltennamen komplett nach der Benennung der Sicht in einer Spaltenliste erscheinen. In diesem Fall benötigt man keine weiteren Aliasnamen. Es werden ausschließlich die in der Spaltenliste vorgegebenen Namen für die Erzeugung der Abfrage verwendet, wie auch die nebenstehende Abbildung zeigt.
CREATE VIEW Kursbesuche (Teilnehmernummer, Vorname, Nachname, Anzahl) SELECT buchungen.teilnnr, teilnvorname, teilnnachname, COUNT(buchungen.teilnnr) FROM buchungen NATURAL JOIN teilnehmer GROUP BY buchungen.teilnnr Wie bei allen anderen Datenbankobjekten auch ist der Löschvorgang trotz seiner Bedeutung verführerisch simpel zu bewerkstelligen: DROP VIEW sichtname
SQL
151
ABFRAGEN
IN VIRTUELLEN
TABELLEN
SPEICHERN
7.3 Sichten aufrufen Wir wollen nicht allzu lange in philosophischen Betrachtungen über die Semantik und Syntax von Programmiersprachen schwelgen, aber an dieser Stelle möchten wir sowohl aus inhaltlichen wie auch didaktischen Gründen auf die Schönheit und Eleganz von SQL hinweisen. Es handelt sich wirklich um eine durch und durch gut organisierte Sprache, die in vielen Punkten der natürlichen Sprache strukturell nachempfunden ist. Ein erstes Beispiel haben Sie bereits mit der WHERE – Klausel kennen gelernt. Überall dort, wo Bedingungen oder Suchkriterien benutzt werden sollen, setzt man diese Klausel ein. Dies geschieht inhaltlich an sehr unterschiedlichen Stellen, denn zwischen einer Lösch- und einer Aktualisierungsabfrage liegen ja tatsächlich Welten. Man muss also lediglich einmal das Konzept erlernen, wie auf Daten ein Suchkriterium angewandt wird, und kann diese Technik dann überall dort einsetzen, wo man genau dies benötigt. Da sich virtuelle Tabellen auf reale Tabellen beziehen, ist es nur logisch und konsequent, dass sie Struktur und Inhalt mit Hilfe einer SELECT – Anweisung erhalten. In diesem Sinne ist es mit Blick auf das Thema dieser Lektion ebenfalls nur konsequent, wie diese virtuellen Tabellen aufgerufen werden. Man könnte sich vorstellen, dass es einen entsprechenden Befehl gibt, der die gesamte Sicht wiedergibt. Tatsächlich aber handelt es sich ja um Tabellen, wenn sie auch nur virtuell sind. Daher haben Sie bereits Konzepte kennen gelernt, die in dieser Situation in all ihrem Reichtum eingesetzt werden können, um an die Daten einer solchen Tabelle heranzukommen: eine Abfrage.
7.3.1 Grundformen des Aufrufs von Sichten Die folgenden Beispiele wiederholen noch einmal die einfachen Sichten der letzten Lektion, damit Sie den Zusammenhang zwischen ihrer Erstellung und ihrer späteren Verwendung leichter sehen können. Dabei verzichten wir allerdings auf die Abbildungen der Sicht-Daten, weil diese natürlich ebenfalls gleich sind. 1. Zunächst wird wieder eine Sicht namens Kursangebot angelegt, die lediglich die beiden Spalten titel und bereich der Tabelle kurse zusammenfasst. CREATE VIEW Kursangebot AS SELECT titel, bereich FROM kurse Um dann diese Sicht aufzurufen, genügt der einfache SELECT- Befehl wie bei der Standardabfrage einer realen Tabelle. Alternativ ist es aber zusätzlich erlaubt, mit einer WHERE – Klausel die in der Sicht zurückgelieferte Datenmenge weiter einzuschränken. SELECT * FROM Kursangebot [WHERE bereich=’Programmierung’] 2. Eine Variation ergibt sich, wenn die Sicht gerade nicht die Spaltennamen der abgefragten realen Tabelle enthalten soll, sondern eigene Namen, wie in diesem Fall Titel und Bereich, mit großen Anfangsbuchstaben erhält. CREATE VIEW Kursangebot (Titel, Bereich) AS SELECT titel, bereich FROM kurse
152
SQL
ABFRAGEN
IN VIRTUELLEN
TABELLEN
SPEICHERN
In diesem Fall muss man darauf in der Abfrage z.B. in der WHERE – Klausel Rücksicht nehmen und die korrekte Spaltenbezeichnung wählen. Dies entspricht dem Vorgehen der bisher verwendeten Abfragetechnik und gilt in Sichten analog. SELECT * FROM Kursangebot WHERE Bereich=’Programmierung’ 3. Für die zuvor erzeugte Sicht ergibt sich eine weitere Variation, wenn nicht alle in der Sicht gespeicherten Spalten benötigt werden, sondern lediglich eine Auswahl. In diesem Fall nennt man die Spalten wie im gewöhnlichen Abfrage-Fall anstatt des Asteristikus, wobei die Schreibweise sich wieder aus der Relationendefinition der Sicht ergibt. SELECT Titel FROM Kursangebot WHERE Bereich=’Programmierung’ 4. Umbenennungen können Sie ebenfalls vornehmen. Sollten Sie Sichten miteinander verknüpfen (siehe Hinweis), können Sie sich darüber hinaus die Möglichkeit nutzbar machen, dass Sie die Spaltennamen entsprechend qualifizieren können. SELECT Kursangebot.Titel AS Kurstitel FROM Kursangebot WHERE Bereich="Programmierung"
Bei einfachen Abfragen ist es ebenso möglich, mehrere Sichten über die PrimärschlüsselFremdschlüssel-Beziehungen zu verbinden. Dies gilt auch für die Kombination reale Tabelle & Sicht. Da innerhalb einer Sicht jedoch ebenfalls solche Konstruktionen möglich sind, können hochkomplexe Gebilde entstehen, die nicht von allen DBMS so abgearbeitet werden können. Zudem erhöht sich die Fehleranfälligkeit erheblich. Syntaktisch gleichen diese Sicht-Abfragen den komplexen Abfragen mit mehreren realen Tabellen. Aus Gründen der Übersichtlichkeit raten wir Ihnen von solchen Raffinessen zu Gunsten einer Verknüpfung innerhalb einer Sicht ab.
7.3.2 Gefahren- und Fehlerquellen bei Sichtdefinitionen Wie so oft sind die Fehlerquellen umfangreicher an der Zahl und schwieriger in der Klassifikationen als die korrekten Verhaltensweisen, sodass wir hauptsächlich mit den nächsten Hinweisen Ihren Blick für Schwierigkeiten schärfen wollen. Sie ergeben sich aus der einfachen Tatsache, dass virtuelle Tabellen auf Abfrageoperationen von realen Tabellen beruhen. ¾ Ein einfaches Problem stellt sich, sobald GROUP BY und HAVING falsch angewandt werden. Dies geschieht automatisch dann, wenn eine gruppierte Spalte auf Eigenschaften innerhalb der WHERE – Klausel geprüft wird und nicht mit HAVING. Hier muss immer die Reihenfolge bedacht werden, in der die einzelnen Funktionen aufgerufen werden. Da es falsch ist, erst eine Spalte in der Abfrage in der SELECT – Anweisung mit einer Aggregatfunktion zu belegen (Summe der Teilnehmer), und diese Summenspalte dann in der WHERE – Klausel weiter einzuschränken (Summenspalte > 15), wird eine solche Konstruktion automatisch im Rahmen einer Sicht falsch. In diesem fall muss unbedingt die HAVING – Klausel eingesetzt werden, die Spaltenei-
SQL
153
ABFRAGEN
IN VIRTUELLEN
TABELLEN
SPEICHERN
genschaften von durch Funktionen erzeugte Spalten überprüft. – Dieses Problem soll exemplarisch für ähnliche, aber komplexere Fälle einmal komplett aufgezeigt werden. Fehlermeldungen zu erzeugen, ist sicherlich sehr leicht, sodass es auf das tiefere Verständnis für die angewandten Zaubermittel ankommt. 1. Zunächst können Sie das Grundproblem an einer einfachen Abfrage entwickeln. In der Sicht wird es dann lediglich um die Sicht-Definition ergänzt und geht dann im Sicht-Aufruf unter. Eine erste Abfrage soll aus der Tabelle buchungen die Kursnummern und ihre Teilnehmerzahlen ausgeben. Die Zählung erfolgt mit der Funktion COUNT, die auf die Spalte buchungsnr angewandt wird. Danach wird die Ausgabe über die GROUP BY – Klausel für die Spalte kursnr gesteuert. Die Sortierung erfolgt automatisch und ist hier nicht relevant. Das Ergebnis dieser einfachen Abfrage sehen Sie in nebenstehender Abbildung. SELECT kursnr AS Kursnr, COUNT(buchungsnr) AS TNZahl FROM buchungen GROUP BY kursnr 2. Danach erweitert man die Abfrage so, dass nur noch die Kurse mit mehr als 15 Buchungen gesucht werden sollen. Wie immer ist es hier falsch, die Spalte in die WHERE – Klausel aufzunehmen, die durch eine Funktion erzeugt wurde. Vielmehr kann dies nur mit HAVING erfolgen. Dies entspricht der allgemeinen Regel zur Verwendung von Aggregatfunktionen und Spalten, die durch sie erzeugt wurden. Es ist also extrem wichtig, dass ein solcher Fall nicht indirekt mit Hilfe einer Sicht erzeugt wird. ¾ Falscher Aufruf: SELECT kursnr AS Kursnr, COUNT(buchungsnr) AS TNZahl FROM buchungen WHERE COUNT(buchungsnr) > 15 GROUP BY kursnr ¾ Richtiger Aufruf: SELECT kursnr AS Kursnr, COUNT(buchungsnr) AS TNZahl FROM buchungen GROUP BY kursnr HAVING COUNT(buchungsnr) > 15
154
SQL
ABFRAGEN
IN VIRTUELLEN
TABELLEN
SPEICHERN
3. Die Gefahrenquelle liegt bei Sichten in der Möglichkeit begründet, Spalten zu erzeugen, die für die Erzeugung der virtuellen Tabelle bereits eine Aggregatfunktion verwenden. In diesem Fall entspricht die Abfrage für die Generierung der Sicht exakt der oben verwendeten. Damit entsteht in der virtuellen Tabelle Teilnehmerzahlen eine Spalte namens TNZahl, die durch die COUNT- Funktion gebildet wird. CREATE VIEW Teilnehmerzahlen (Kursnr, TNZahl) AS SELECT kursnr, COUNT(buchungsnr) FROM buchungen GROUP BY kursnr 4. Nun erzeugt man den falschen und den richtigen Aufruf der Sicht Teilnehmerzahlen. Seien wir ehrlich: ohne die vielleicht nicht so beeindruckende Vorübung in den ersten Schritten mit dem Standardfall würde vielleicht der Fehler im Quelltext gar nicht auffallen. Tatsächlich gerät nämlich die falsche Gruppierung genau dadurch in Vergessenheit oder in den Hintergrund, weil man scheinbar eine gewöhnliche Spalte namens TNZahl aufruft und ihr ein Suchkriterium mit auf den Weg gibt. In Wirklichkeit jedoch läuft die oben beschriebene falsche Abfrage ab und würde eine Fehlermeldung erzeugen. Um dies zu verhindern, muss die Abfrage die gleiche Struktur wie die oben verwendete richtige Abfrage haben. Deswegen wird die zuvor abgebildete Ergebnistabelle nur erzeugt, soweit die HAVING- Klausel die Bedingung für die durch eine Funktion erzeugte Spalte vorgibt. ¾ Falscher Aufruf: SELECT * FROM Teilnehmerzahlen WHERE TNZahl > 15 ¾ Richtiger Aufruf: SELECT * FROM Teilnehmerzahlen GROUP BY Kursnr HAVING TNZahl > 15 ¾ Damit ist es z.B. möglich, durch Aggregatfunktionen Spalten zu erschaffen, die solche Funktionen in realen Tabellen nicht haben. Die Zahlen einer Summenspalte werden ja gerade nicht bei der Definition der Sicht durch den CREATE VIEW – Befehl erzeugt, sondern vielmehr wird lediglich die Operation der Aggregatfunktion gespeichert. Dies bedeutet, dass man eine Fehlermeldung erzeugt, sobald man versucht, innerhalb einer Sicht wiederum eine Aggregatfunktion wie z.B. den Durchschnitt auf die durch eine Funktion erzeugte Spalte anzuwenden. Man würde in diesem Fall ganz klar gegen die Regel verstoßen, dass verschachtelte Funktionen nicht erlaubt sind.
SQL
155
ABFRAGEN
IN VIRTUELLEN
TABELLEN
SPEICHERN
7.4 Änderungen über Sichten realisieren Da die virtuellen Tabellen wie vollwertige Tabellen behandelt werden, ist es ebenso möglich, Datenänderungen über INSERT, DELETE oder UPDATE vorzunehmen. In dieser Lektion werden Sie zunächst entsprechende Beispiele für diese Technologie sowie die Abarbeitungsvorgänge durch das DBMS kennen lernen. Danach möchten wir auch für diese DBOperationen auf eine Handvoll klassischer Schwierigkeiten hinweisen, die sie mit sich bringen. Der Einsatz von Sichten lässt sich in verschiedene Kategorien unterteilen, die kurz im Zusammenhang erklärt werden sollen. Sie stellen die Basis für die Schwierigkeiten (Herausforderungen) mit über Sichten realisierten Änderungsoperationen dar. ¾ Projektionssicht: Spalten aus einer realen Tabelle werden in der Sicht komplett angezeigt. Es existiert also keine Einschränkung im Rahmen einer WHERE – Klausel. CREATE VIEW Kundenliste AS SELECT untname, untstadt FROM unternehmen ¾ Selektionssicht: Spalten in der realen Tabelle werden über ein bestimmtes Suchkriterium in die virtuelle Tabelle übernommen. Dabei können auch arithmetische Berechnungen oder Aggregationsfunktionen unterstützen. CREATE VIEW KundenAusSollbach AS SELECT untname, untstadt FROM unternehmen WHERE untstadt="Sollbach" ¾ Verbundsicht: Die Spalten der virtuellen Tabelle setzen sich aus den Spalten mehrerer realen Tabellen und/oder virtuellen Tabellen zusammen, wobei als Verknüpfungsbedingung Suchkriterien und die Primärschlüssel-Fremdschlüssel-Beziehung eingesetzt wird. CREATE VIEW Kunden AS SELECT untname, titel, COUNT(buchungen.teilnnr) AS Kursbuchungen FROM buchungen, teilnehmer, unternehmen, kurse WHERE buchungen.teilnnr=teilnehmer.teilnnr AND unternehmen.untnr=teilnehmer.untnr
156
SQL
ABFRAGEN
IN VIRTUELLEN
TABELLEN
SPEICHERN
AND buchungen.kursnr=kurse.kursnr GROUP BY titel
7.4.1 Einfügen, Löschen und Aktualisieren Es besteht neben der einfachen Abfrage also auch die Möglichkeit, Aktualisierungen über Sichten durchzuführen. Nachdem in diesem Abschnitt die recht einfache Vorgehensweise erläutert wird, lernen Sie im nächsten Abschnitt mögliche Brandstellen kennen, die sich aufgrund des Abfragetyps und der Eigenschaften der realen Tabellen ergeben. Bildlich kann man sich die Verwendung von Sichten für Aktualisierungen so vorstellen, dass – wie in nebenstehender Abbildung symbolisiert – die Änderungen durch die Sicht auf die reale Tabelle zugreifen. Folgende Beispiele beziehen sich auf die oben beispielhaft angelegten Sichten Kundenliste und KundenAusSollbach. Werden Spaltenbezeichnungen verwendet, so gilt die Namenskonvention in der Sicht. Sollten Sie also eigene Namen innerhalb der Sicht vorgegeben haben, verwenden Sie diese. Sie beziehen sich durch das Relationenschema der Sicht automatisch auf die ihr zu Grunde liegenden Spalten der realen Tabelle. 1. Im Einfüge-Fall ruft man die Sicht genauso auf wie eine reale Tabelle und fügt entweder in sämtliche Spalten der Sicht Daten ein oder nur in eine Spaltenauswahl. Im ersten Fall verzichtet man auf eine Nennung der Spalten, in die eingefügt werden soll. Im zweiten Fall dagegen ist der Spaltenaufruf obligatorisch. INSERT INTO Kundenliste VALUES (’Dr. Starrer-Klinik’, ’Sollbach’) INSERT INTO Kundenliste (untname) VALUES (’Dr. Starrer-Klinik’) 2. Gleiches gilt für eine Löschabfrage, die innerhalb der WHERE – Klausel den Spaltenaufruf beinhaltet und ein Suchkriterium vorgibt. DELETE FROM Kundenliste WHERE untstadt=’Sollbach’ 3. Auch die Aktualisierungsabfrage lässt sich analog zu der bereits vorgestellten Version bilden. Die beiden folgenden Abfragen zeigen aber, dass unter Umständen die WHERE – Klausel entfallen kann, wenn die gleiche Bedingung bereits in der Sicht vorhanden sind. Wenn also die Stadt Sollbach umbenannt werden soll, entfällt in der (Selektions-)Sicht KundenAusSollbach die WHERE – Klausel, da in ihrem Relationenschema genau dieses Suchkriterium bereits vorgegeben wurde. Anders verhält es sich dagegen, wenn in der (Projektions-)Sicht lediglich die nicht durchsuchte Spalte erscheint. Hier muss diese Spalte natürlich zusätzlich abgefragt werden, bevor die Daten eingetragen werden können. UPDATE KundenAusSollbach SET untstadt="Sollbach (Murmeltal)" UPDATE Kundenliste SET untstadt=’Sollbach (Murmeltal)’ WHERE untstadt=’Sollbach’
SQL
157
ABFRAGEN
IN VIRTUELLEN
TABELLEN
SPEICHERN
7.4.2 Gefahren- und Fehlerquellen bei Änderungsvorgängen Folgende Liste enthält die Einschränkungen für änderbare Sichten im SQL-92-Standard, der in einigen Punkten restriktiver als die Implementationen in verschiedenen DBS ist. Bevor Sie sich unnötig einengen lassen oder zu wenig Möglichkeiten erwarten, sollten Sie nachschlagen, welche Optionen Sie in Ihrem DBS besitzen. Das Oberziel der Einschränkungen besteht darin, nicht eindeutige Spaltenzuordnungen zu vermeiden. Dies fällt insbesondere sehr deutlich bei dem Gruppierungsverbot und den Aggregatfunktionen auf. Gerade hier werden neue Informationen sozusagen durch die Abfrage aggregiert, indem Informationen in den betreffenden Datensätzen zusammengefasst werden. So ergeben sich Abfragen, deren Ergebnisse in dieser Form nicht zwangsläufig genauso in der Datenbank vorlagen. Ein schönes Beispiel ist die Antwort auf die Frage, welche Firma wie viele Kurse gebucht hat. Alleine schon die Zahl der Kurse existiert an keiner Stelle mit einer entsprechende Spalte, sondern wird über die COUNT – Funktion und verschiedene Verknüpfungen über die Tabelle buchungen eigens erzeugt. Änderungsabfragen aufgrund einer solchen Spalte können schlichtweg nicht sinnvoll übersetzt werden. ¾ Änderbare Sichten dürfen sich nur auf eine reale oder virtuelle Tabelle beziehen. Verknüpfungen von Tabellen innerhalb einer veränderbaren Sicht sind damit untersagt. ¾ Zuvor genannter Bedingung kann nicht dadurch ausgewichen werden, indem verschachtelte Sichten eingesetzt werden. Virtuelle Tabellen innerhalb der SELECT – Anweisung der SichtDefinition müssen ebenfalls veränderbar sein. ¾ UNION, EXCEPT und INTERSECT können nicht eingesetzt werden. ¾ Gruppierungen und DISTINCT dürfen nicht eingesetzt werden. ¾ Die konstituierenden Abfragen dürfen keine weiteren Unterabfragen enthalten, wenn diese sich auf die Basistabelle beziehen. ¾ Die Spalten der Sicht dürfen keine Spaltenfunktionen enthalten. Spalten dürfen auch nicht mehrfach angesprochen werden. Neben den Ausschlusskriterien, in denen bereits die Standardsyntax Fehler und Datenbankanomalien verhindern möchte, gibt es verschiedene typische Gefahren, die auch bei Beachtung der gerade genannten Regeln eintreten können. Einige Punkte ähneln den Fehlerquellen bei der üblichen Ansprache von realen Tabellen. Im Zusammenhang mit Sichten kann es aber durch eine gewisse Komplexität geschehen, dass eine Fehlermeldung erscheint, da die Sicht scheinbar funktionstüchtig ist. ¾ Wertebereiche können sehr leicht verletzt werden. Werden in die Tabelle unternehmen über die Sicht Kunden lediglich die beiden Spalten der Sicht mit Daten gefüllt, müssten alle anderen Spalten mit NULL aufgefüllt werden. Dies könnte sowohl unerwünscht als auch durch eine NOT NULL – Bedingung verboten sein. Beim Einfügen durch Sichten verliert man die Möglichkeit, sämtliche Spalten der zu Grunde liegenden Basisrelation zu verwenden. ¾ Sichten, die Aggregationsfunktionen verwenden, können bei Aktualisierungsabfragen die Daten, die für eine durch eine Funktion erzeugten Spalten gedacht waren, nicht sinnvoll an die zu Grunde liegende Tabelle weitergeben. ¾ Wenn Gruppierungen nicht wie im Standard ausgeschlossen sind, gelten ähnliche Überlegungen auch für solchermaßen erzeugten virtuellen Tabellen. Hier gibt es ebenfalls keine wirklich korrespondierenden Datensätze in der realen Tabelle. ¾ Sichten müssen bei Aktualisierungen eindeutig zurückverfolgbar sein, um Fehleinträge oder Integritätsverletzungen vermeiden zu können.
158
SQL
ABFRAGEN
IN VIRTUELLEN
TABELLEN
SPEICHERN
7.4.3 Überprüfungen mit WITH CHECK OPTION In der allgemeinen Syntax zu Anfang dieses Projekts haben wir eine fakultative letzte Zeile genannt, mit der die oben genannten Schwierigkeiten in Maßen überprüft und kontrolliert werden kann. Fehler können immer dann weiterhin vorkommen, solange in technischer Hinsicht für die Datenbank als solche keine Schwierigkeiten bestehen. Sie kann nicht eine vollkommene inhaltliche Überprüfung bieten, wenn z.B. eine (nicht durch Funktionen) sehr aggregierte Sicht so viele Daten ausschließt, dass dem Benutzer eine syntaktisch korrekte, aber inhaltlich ungewünschte Operation gelingt. Ebenso überprüft sie nur die Auswirkungen auf die Sicht, löst also damit eigentlich mehr das Problem, dass geänderte Daten plötzlich nicht mehr in der Sicht erscheinen. Dies kann geschehen, wenn die Aktualisierung das die Sicht konstituierende Suchkriterium verletzt. Mit der letzten Überlegung ist das Problem umrissen worden, das entsteht, wenn auf die hier noch einmal wiederholte Sicht KundenAusSollbach ein UPDATE – Befehl ausgeführt wird, der für ein bestimmtes Unternehmen die Stadt von Sollbach nach Willingen verändert. Dies hätte zur Folge, dass der geänderte Datensatz nicht mehr in der Sicht erscheint, weil er ja das Suchkriterium nicht mehr erfüllt. Genau dieses Problem soll durch WITH CHECK OPTION behoben werden. ¾ Definition der Sicht: CREATE VIEW KundenAusSollbach AS SELECT untname, untstadt FROM unternehmen WHERE untstadt="Sollbach" ¾ Aktualisierung, die den Datensatz der Firma Draht Gründling GmbH aus der Sicht befördert (Tupelmigration): UPDATE KundenAusSollbach SET untstadt="Willingen" WHERE untname=" Draht Gründling GmbH " ¾ Allgemeine und vollständige Syntax für die Definition einer Sicht: CREATE VIEW sichtname [{spalte1, spalte2,...] AS abfrage [WITH [CASCADED | LOCAL] CHECK OPTION] Prinzipiell bedeutet also die Verwendung von WITH CHECK OPTION, dass vor dem endgültigen Änderungsvorgang in der realen Tabelle, auf die sich die Sicht bezieht, überprüft wird, ob die Suchkriterien von der Sicht auch nach der Änderung noch vom zu ändernden Datensatz erfüllt werden. Das DBMS führt die Abfrage also nur aus, wenn der Datensatz weiterhin in der Sicht bestehen bleibt. Dieser Befehl kann alternativ um die Optionen CASCADED oder LOCAL ergänzt werden. Die Ergänzung ist nur sinnvoll, wenn die änderbare Sicht sich selbst wiederum auf eine solche änderbare Sicht bezieht. Dies ist ja auch die Voraussetzung, dass eine solche Änderung überhaupt durchgeführt werden kann. In diesem Zusammenhang kann man mit CASCADED steuern, dass auf den einzelnen Stufen (Kaskaden) des Relationenschemas (erste Abfrage, zweite Abfrage) die Suchkriterien weiterhin erfüllt sind. Im Endeffekt können also nur Daten eingefügt werden, die am Ende auch in der obersten Sicht noch sichtbar bleiben. LOCAL hingegen beschränkt dies auf die zuvor definierte Sicht, sodass im Ergebnis der geänderte Datensatz aus der aktuellen Sicht verschwindet.
SQL
159
ABFRAGEN
IN VIRTUELLEN
TABELLEN
SPEICHERN
7.5 Snapshots verwenden Die Kurzaufnahmen präsentieren sich jetzt im Vergleich zu den Sichten eher bescheiden in der Verwendung und Programmierung. Sie zeichnen sich ja gerade dadurch aus, dass sie lediglich den Datenbestand innerhalb der Datenbank zu einem bestimmten Zeitpunkt, nämlich dem der Abfrage, für alle Ewigkeit speichern. Die Ewigkeit wird dabei insbesondere durch den DROP – Befehl stark beeinflusst. CREATE SHNAPSHOT kurzaufnahmenname [{spalte1, spalte2,...] AS abfrage 1. Als Beispiel soll eine Kurzaufnahme für alle Kurse angelegt werden, die für den Monat Juni 2002 geplant waren. Ob sie stattgefunden haben, ist damit uninteressant. Daher genügt eine Verknüpfung zwischen den Tabellen termine und kurse. mit dem Suchkriterium im LIKE – Operator, dass nur Kurse mit der Monatsnummer 6 in die Ergebnisrelation übernommen werden sollen. CREATE SNAPSHOT KurseJuni2002 (Titel, Beginn, Dauer, Preis) AS SELECT titel, beginn, dauer, preis FROM termine NATURAL JOIN kurse WHERE beginn LIKE "2002-06-%" 2. Für die Verwendung einer solchen Kurzaufnahme verwenden Sie danach die allgemein übliche Syntax für die Tabellenabfrage: SELECT * FROM KurseJuni2002 SELECT titel FROM KurseJuni2002 3. Genauso einfach können Sie eine Kurzaufnahme wieder aus der Datenbank entfernen. DROP KurseJuni2002
7.5.1
Zusammenfassung
9 Tabellen lassen sich in vier Typen differenzieren: Für die reale Tabelle speichert die Datenbank sowohl ihre Struktur als auch die Daten physisch auf dem verwendeten Datenträger. Durch eine Abfrage gibt die Datenbank ein Ergebnis in Form einer Abfragetabelle aus, die nur so lange vorhanden ist, wie die Abfrage selbst verwendet. Zu den temporären Tabellen zählen sowohl die Ergebnistabelle als auch die Sicht. Nach Sitzungsende oder nach Übermittlung der Ergebnistabelle werden Struktur und Daten gelöscht. Bei virtuellen Tabellen wird beim Aufruf ihrer Strukturbeschreibung ihr zu Grunde liegender Abfrage-Befehl ausgeführt, sodass aus den realen Tabellen die Ergebnistabelle erzeugt wird.
160
SQL
ABFRAGEN
IN VIRTUELLEN
TABELLEN
SPEICHERN
9 Sichten werden mit CREATE VIEW und einer mit AS angeschlossenen Abfrage erstellt. 9 Die Spaltennamen können dabei direkt aus der Abfrage oder aus den zu Grunde liegenden realen Tabellen übernommen werden. Alternativ kann man selbst definierte Namen verwenden. 9 Sichten werden wie andere Tabellen mit Hilfe einer Abfrage aufgerufen und können zusätzlich weitere Suchkriterien enthalten. 9 Neben dem einfachen Aufruf sind auch Aktualisierungen mit DELETE, INSERT und UPDATE möglich. Dabei greifen diese Aktualisierungsabfragen durch die Sicht auf die reale Tabelle zu. 9 Nicht alle Relationenschemata eignen sich für die Konstruktion einer veränderbaren Sicht. Prinzipiell scheitern Aktualisierungsabfragen immer, sobald Spalten oder Datensätze nicht eindeutig identifizierbar sind. Klassischer Problemfall sind Gruppierungen und Aggregatfunktionen. 9 Mit Hilfe von WITH CHECK OPTION kontrolliert das DBMS, ob Änderungen vorgenommen werden, die den betreffenden Datensatz aus der Sicht befördern. Diese Tupelmigration wird dann verhindert.
7.5.2
Übungen
1. Legen Sie die Sicht Teilnehmer mit teilnvorname, teilnnachname und teilnstadt aus der Tabelle teilnehmer an. 2. Benennen Sie die Spalten für die Sicht in Vorname, Nachname und Wohnort um. 3. Legen Sie eine Sicht Kursbesuche mit Titel, Dauer und Preis an, wobei die Kurse einen Preis haben, der höher als der Durchschnittspreis der Tabelle kurse ist. 4. Legen Sie eine Sicht namens Tagespreise mit den Spalten Kursnr, Titel und Tagespreis an, wobei der Tagespreis sich berechnen soll mit preis / dauer. 5. Legen Sie eine Sicht namens Kursbesuche an, die Teilnehmernummer, Vorname und Nachname für den Kurs mit der Nummer 50232 ausgibt. 6. Legen Sie eine Sicht namens Grafikkurse mit titel, preis und dauer an und fragen Sie diese Sicht dann so ab, dass die Kurse mit einer Länge von mehr als drei Tagen ausgegeben werden. 7. Legen Sie eine Sicht an, die die Anzahl der Teilnehmer pro Stadt ausgibt. Welche Schwierigkeiten für Aktualisierungsoperationen hat diese Tabelle?
SQL
161
ABFRAGEN
IN VIRTUELLEN
TABELLEN
SPEICHERN
8. Fügen Sie in die Sicht Grafikkurse die Werte ("Auto-CAD", 1050, 4) ein. Welche Schwierigkeiten ergeben sich? 9. Löschen Sie mit Hilfe der Sicht Grafikkurse alle Kurse zu Photoshop. Was würde der Befehl WITH CHECK OPTION innerhalb der Sichtdefinition bewirken? 10. Erhöhen Sie die Preise der Sicht Grafikkurse um 30 %.
162
SQL
8 Zugriffskontrolle durch Benutzer, Rechte und Rollen
SQL
163
ZUGRIFFSKONTROLLE
164
DURCH
BENUTZER, RECHTE
UND
ROLLEN
SQL
ZUGRIFFSKONTROLLE
DURCH
BENUTZER, RECHTE
UND
ROLLEN
8 Zugriffskontrolle durch Benutzer, Rechte und Rollen Dieses Projekt stellt die unterschiedlichen Möglichkeiten für Sicherheit und Zugriffskontrollen vor, die durch SQL angeboten werden. Typischerweise werden Sie in jedem DBS eine irgendwie geartete grafische Oberfläche finden, mit der Sie solche Objekte wie Benutzer mit Rechten einfach anlegen können. Daher sollten Sie die hier vorgestellten Konzepte weniger auf ihre Syntax hin lesen, sondern sich vielmehr mit den Möglichkeiten vertraut machen, die sie bieten.
Lernen Sie Zugriffsmöglichkeiten zu unterscheiden und zu vergleichen Benutzer anzulegen Rechte und Rollen zu vergeben Benutzer, Rechte und Rollen zu ändern und zu löschen
8.1 Vorüberlegungen für Zugriffskontrollen Für den Bereich der Zugriffskontrollen kann man verschiedene Ebenen unterscheiden, die auch innerhalb der in diesem Projekt vorgestellten SQL-Befehle berücksichtigt werden. ¾ Neben der direkt in der Datenbank implementierten Benutzer ist Ihnen z.B. bereits bekannt, dass man sich auch beim Start eines Computers oder eines Programms anmelden muss. Diese Anmeldung könnte eine erste Schicht darstellen, die nachher auch für den Zugang zur Datenbank verwendet werden kann. Das bedeutet, dass die Datenbank berücksichtigt, dass sich der Benutzer bereits in das Betriebssystem eingeloggt hat, und akzeptiert diese erfolgreiche Anmeldung nachher auch für den Zugang zur DB. ¾ Alternativ kann die externe Sicht einer Datenbank ebenfalls eine Kennwortabfrage besitzen. Dies könnte ein Programm wie z.B. MS Access sein. Da eine externe Sicht notwendig ist, um überhaupt mit der Datenbank zu kommunizieren, beruht die Zugangskontrolle also darauf, dass gerade diese externe Sicht für Benutzer ohne Kennwort gesperrt ist. ¾ Sollte dies als Schutz nicht ausreichen, weil man sich der Datenbank auch ohne ein Programm, das wiederum auf einem im Netzwerk eingebuchten Computer installiert ist, nähern
SQL
165
ZUGRIFFSKONTROLLE
DURCH
BENUTZER, RECHTE
UND
ROLLEN
kann, muss eine Hilfslösung gefunden werden. Dieser Fall tritt typischerweise auf, wenn Benutzer über das Internet Zugang zu einer Datenbank erhalten. Hier ist eine ähnliche Kennwortabfrage auch für eine Webseite über ein Formular und eine entsprechende Datenbankabfrage denkbar. In naher Zukunft wird ein weiterer Zugang auch mit UMTS möglich sein. Eine solche Abfrage bzw. das Programm, das sie enthält, vergleicht die in den Textfeldern Login und Kennwort mit den zugehörigen Daten in einer Tabelle Mitglieder. Dabei müssen beide Begriffe in einem Tupel erscheinen. Vom Prinzip wird also das im zweiten Fall beschriebene Programm auf dem Webserver aufgerufen, um den Datenbankzugang zu ermöglichen. ¾ Eine letzte Möglichkeit besteht nun darin, direkt in der Datenbank Benutzer mit Kennwörtern zu speichern. Dies ist auch der Fall, den wir mit SQL-Befehen in diesem Projekt vorstellen werden. Typischerweise wird dafür die bereits eingangs erwähnte grafische Oberfläche verwendet. Zusätzlich sind die Optionen der einzelnen DBS-Produkte sehr unterschiedlich im Umfang der Definitionen, sodass wir uns für diese Beispiele an Oracle anlehnen. Es stellt auch mit Blick auf den SQL-Dialekt den größten Sprachschatz zur Verfügung. Die folgende Abstufung in den Möglichkeiten der Zugriffskontrolle innerhalb der Datenbank ergibt sich weitestgehend auch für die anderen Fälle, wenn sie dort jedoch über entsprechende Programmmodule erreicht wird. SQL stellt zusammenfassend die folgenden Strukturen zur Verfügung, um den Zugriff auf die Daten und das Datenmodell zu kontrollieren und administrieren: ¾ Benutzer repräsentieren natürliche oder fiktive Personen wie z.B. den Administrator oder Elvira Hülzemann, die Zugriff auf die Daten oder das Datenmodell erhalten. Während Frau Hülzemann eine reale Person in der Controlling-Abteilung sein kann, die statistische Analysen über das Nutzungs- oder Besuchsverhalten einer Webpräsenz erstellt, können sich durchaus mehrere Administratoren in einem Team als Administrator-Benutzern anmelden und schwergewichtige Änderungen an der Datenbank vornehmen. ¾ Die Sichten des letzten Projekts stellen ebenfalls eine Möglichkeit zur Zugriffskontrolle dar, da ja nur ein vom Administrator bestimmter Teil der Datenbank für einen Benutzer (im tatsächlichen und nicht im obigen technischen Sinne) sichtbar ist. Sie werden darüber hinaus durch die Überprüfungsoption oder Domänen etc. ergänzt, um Aktualisierungsabfragen wunschgemäß administrativ zu steuern. ¾ Während das Konzept des Benutzers primär den Zugang zur Datenbank kontrolliert und damit mehr als Passwortschutz dient, können darüber hinaus spezielle Rechte einerseits für Tabellen, einzelne Spalten und weitere Objekte vergeben werden und andererseits diese Rechte in Rechtepaketen zusammengefasst werden, die mit dem Begriff „Rollen“ bezeichnet werden. Während also ein Benutzer verschiedene Rechte besitzen kann, ist es möglich, ähnlich gelagerte Rechtestrukturen mittels einer Rolle zu bündeln und diese Rolle wiederum einem Benutzer zuzuweisen. Frau Hülzemann wird natürlich regelmäßig umfangreiche Abfragen vornehmen. Wenn Sie zusätzlich eine Kollegin hat, wäre es sicherlich günstiger, die gemeinsamen Rechte in eine Rolle auszulagern (hier also auch wieder das Grundprinzip der Auslagerung und Ordnung) und ihnen beide eine Rolle wie „Statistiker“ zuzuweisen, der praktisch jede SELECT –
166
SQL
ZUGRIFFSKONTROLLE
DURCH
BENUTZER, RECHTE
UND
ROLLEN
Anweisung durchführen darf, die denkbar ist. Verboten für sie könnten allerdings jegliche Aktualisierungsabfragen sein.
8.2 Benutzer anlegen Folgende Ausführungen beziehen sich auf das DBS Oracle und seinen speziellen SQL-Dialekt, den wir hier für das Anlagen von Benutzern ausgewählt haben. Er ist besonders umfangreich, sodass wir hier nur exemplarisch einige wichtige Punkte ansprechen. Wir hoffen, dass wir damit eine gute Auswahl getroffen haben, die Ihnen zeigt, welche Möglichkeiten man (theoretisch) mit einem DBMS als Administrator besitzt. Die allgemeine Syntax hat folgende Form, wobei die einzelnen Einstellungen neben der Grundform Benutzernamen und Kennwort alternativ sind. CREATE USER benutzer IDENTIFIED {BY kennwort | EXTERNALLY} {[DEFAULT TABLESPACE tabellenbereich] |[TEMPORARY TABLESPACE tabellenbereich] [QUOTA {Integer [K|M] | UNLIMITED} ON tabellenbereich]} [PROFILE profil] [DEFAULT ROLE { rolle [, rolle] ... | ALL [EXCEPT rolle [, rolle] ...] | NONE}] Insbesondere die fakultativen Einstellungen, die sich nicht direkt aus dem Befehl erschließen lassen, sollen kurz zusammengefasst werden: ¾ Das allseits beliebte CREATE leitet den gesamten Befehl ein und bestimmt den Namen des Benutzers. ¾ Sein Passwort bestimmt ganz direkt IDENTIFIED BY, während die alternative Option EXTERNALLY den oben beschriebenen Fall abdeckt, dass ein Benutzer sich beim Starten des Systems (Computers) eingeloggt hat und dieser Zugang auch für die Datenbank gelten soll. Dies ist insoweit obligatorisch, wenn ein Benutzer kein eigenes Passwort besitzt, da die gesamte Option IDENTIFIED nicht fakultativ ist. Sie gehört stets zum Anlegen eines Benutzers dazu. ¾ Der Tabellenbereich, der einmal temporär und einmal standardmäßig vorgegeben werden kann, ist ein Konzept von Oracle und DB2, womit physischer Speicherplatz gemeint ist, der für Tabellen auf dem Datenträger der Datenbank angelegt wird. Er wird hier in diesem Sinne nicht angelegt, sondern vielmehr zugewiesen, wobei ein entsprechender CREATE TABLESPACE – Befehl mit einer Vielzahl an Optionen von beiden Systemen zur Verfügung steht. Strukturell entsprechen Überlegungen dieser Art der Vorgabe im MS SQL Server, wie groß eine Datenbank ungefähr sein wird, damit entsprechender Speicherplatz auf dem Datenträger reserviert wird. Eine realistische Angabe ist nötig, damit die Daten abfrageoptimal in großer Nähe auf dem Datenträger untergebracht sind. Dieser Punkt ist die Schnittstelle zu Themen wie Datenträger und Datenstrukturen auf technischer Ebene in der konzeptionellen Sicht einer Datenbank. ¾ Beide Befehle benötigen jeweils eine Angabe des Speicherplatzes über das Schlüsselwort QUOTA, wobei eine entsprechende Zahl (Integer) mit K für Kilobyte oder M für Megabyte angeschlossen wird.
SQL
167
ZUGRIFFSKONTROLLE
DURCH
BENUTZER, RECHTE
UND
ROLLEN
¾ Mit Hilfe des Schlüsselworts PROFILE können Sie ein zuvor festgelegtes Profil angeben. Das über CREATE PROFILE angelegte Profil existiert in dieser umfangreichen Form auch nur in Oracle. Es speichert alle möglichen Einstellungen für das Passwort (Gültigkeitsdauer, Wiederholungsabstände von alten Passwörtern) oder Sitzungen (höchste Dauer an Inaktivität während einer Sitzung, Verbindungszeit, Anzahl gleichzeitiger Sitzungen eines Benutzers). ¾ Zum Schluss können noch eine oder mehrere Rollen für einen Benutzer über ROLE vergeben werden. Ebenso simpel ist der Löschvorgang für einen Benutzer, wenn Frau Hülzemann mit ihren statistischen Erkenntnissen bei der Konkurrenz eine besser dotierte Stelle erhält und nicht mehr für das Unternehmen tätig ist. Der DROP – Befehl löscht unter Aufrufen des Benutzernamens den gesamten Benutzer. DROP USER benutzer [CASCADE] Die Option CASCADE sorgt dafür, dass nicht nur der Benutzer, sondern auch alle Objekte, die in seinem Namen angelegt wurden, entfernt werden. Um also tatsächlich einen kompletten Löschvorgang durchzuführen, ist dieses Schlüsselwort notwendig. 1. Um für die schon in Erscheinung getretene Frau Hülzemann nun endlich einen Benutzer anzulegen, der lediglich ein Passwort besitzt, genügt die einfache Grundform ohne die fakultativen Ergänzungen. CREATE USER ElviraHuelzemann IDENTIFIED BY bochum 2. Nun erhält Frau Hülzemanns Benutzer weitere Eigenschaften Sie kann also bspw. eigene Tabellen in der Größe des zuvor festgelegten Tabellenbereich analyse_hm abspeichern, während temporäre Daten wie z.B. bei Abfragen in analyse_hm_temp abgelegt werden sollen. Beide Bereiche erhalten 50 MB Speicherplatz. Beachten Sie hier, dass es natürlich möglich ist, mehrere Benutzer auf den gleichen Speicherplatz zugreifen zu lassen (was typischerweise für temporäre Tabellen für bessere Betriebssystemarbeit empfehlenswert ist), sodass sich hier die zugewiesenen MB von den gesamten verfügbaren unterscheiden können. Das heißt also, wenn Frau Hülzemann in einer Arbeitsgruppe arbeitet, für die ein Tabellenplatz namens analysen mit 100 MB Speicherplatz angelegt wurde, könnte sie selbst ebenso gut nur einen gewissen (kleineren) Bereich davon zur freien Verfügung erhalten. CREATE USER ElviraHuelzemann IDENTIFIED BY bochum DEFAULT TABLESPACE analyse_hm QUOTA 50M ON analyse_hm TEMPORARY TABLESPACE analyse_hm_temp QUOTA 50M ON analyse_hm_temp 3. Um die Eigenschaften eines Benutzers zu ändern, genügt wie immer der Befehl ALTER, wobei die restliche Syntax des obigen allgemeinen Befehls erhalten bleibt. Für den wohl häufigsten Fall, dass ein Passwort geändert wird, bedeutet dies, dass lediglich ALTER und das neue Passwort vorgegeben werden müssen. In diesem Fall wird jetzt bochum gegen duesseldorf ausgetauscht. ALTER USER ElviraHuelzemann IDENTIFIED BY duesseldorf 4. Zum Schluss wechselt Frau Hülzemann tatsächlich das Unternehmen und muss brutal aus der Datenbank entfernt werden, wobei der Benutzername und CASCADE angegeben werden muss, damit auch alle von Frau Hülzemann angelegten Objekte verschwinden.
168
SQL
ZUGRIFFSKONTROLLE
DURCH
BENUTZER, RECHTE
UND
ROLLEN
DROP USER ElviraHuelzemann CASCADE
8.3 Rechte vergeben und versagen Die oben definierte und rücksichtslos gelöschte Frau Hülzemann ist ein Benutzer, was lediglich bedeutet, dass auf einem irgendwie gearteten Anmeldebildschirm ein Login für den Benutzernamen ElviraHuelzemann mit dem Passwort bochum möglich ist. Erst die korrekte Angabe beider Begriffe ermöglicht ihr den Zugriff auf die Datenbank oder auf die in ihrem System gespeicherten DB-Objekte wie z.B. Sichten. Das in dieser Lektion vorgestellte Konzept der Rechte hingegen konzentriert sich vielmehr auf spezielle Tätigkeiten, die mit den in den anderen Projekten vorgestellten Techniken möglich sind. Sie können für den einen oder anderen Benutzer erlaubt oder untersagt werden, wobei diese Erlaubnisse genau die Rechte sind, die der Benutzer für Tätigkeiten und Aktionen innerhalb der Datenbank besitzt. Es sind also sozusagen weitere Eigenschaften neben seinem Benutzernamen und seinem Passwort. Beachten Sie hier, dass die unterschiedlichen DBS neben der Grundkonstellation aus Benutzername und Passwort auch allerhand andere Eigenschaften für das DB-Objekt des Benutzers bereithalten. Die Quelltexte in dieser Lektion folgen daher wieder dem SQLStandard, da die Dialekte sehr zahlreich und unterschiedlich sind.
8.3.1 Rechte für Benutzer anlegen Für die Rechtevergabe existieren im Standard zwei verschiedene Möglichkeiten. Die erste konzentriert sich auf Abfrage- und Aktualisierungsaktionen bzgl. einzelner Tabellenspalten oder der gesamten Tabelle mit folgender allgemeiner Syntax: GRANT {ALL PRIVILEGES | SELECT | DELETE | {INSERT [(spalte1 [, spalte2,...])} | {UPDATE [(spalte1 [, spalte2,...])} | {REFERENCES [(spalte1 [, spalte2,...])} }[, ...] ON [TABLE] tabellenname TO {benutzer1 [, benutzer2, ...]} | PUBLIC [WITH GRANT OPTION] Die einzelnen Rechte dürften sich durch die Befehlsliste unmittelbar einleuchtend vergeben, sodass die folgenden Punkte zur detaillierten Erläuterung relativ kurz ausfallen:
SQL
169
ZUGRIFFSKONTROLLE
DURCH
BENUTZER, RECHTE
UND
ROLLEN
¾ Man kann bei der Rechtevergabe alternativ wählen zwischen einer Kombination von speziellen Rechten, die über die einzelnen Befehle SELECT usw. aufgeführt sind, oder über die Zuweisung aller Rechte durch ALL PRIVILEGES. Für temporäre Tabellen ist im Standard keine andere Möglichkeit vorgesehen, als mit ALL PRIVILEGES Rechte an solchen Tabellen zu vergeben. Anders verhält es sich dagegen mit virtuellen Tabellen. Diese nennt man wie reale Tabellen ebenfalls in der Tabellenliste. ¾ Insbesondere für die Änderungen (abgesehen vom Löschvorgang) ist es zusätzlich möglich, für einzelne Tabellen, die wiederum mit dem ON – Schlüsselwort aufgerufen werden, einzelne Spalten auszuwählen. Diese Befehlsliste inklusive der notwendigen Tabellen(spalten)liste kann mehrfach wiederholt werden, damit die einzelnen Tabellen erfasst werden können, auf die sich solche Änderungen erstrecken. ¾ Zum Schluss nennt man den oder die Benutzer, auf die sich diese Rechte beziehen. Hier besteht auch wie immer die Möglichkeit, global allen Benutzern Rechte einzuräumen, um Schreibarbeit und vor allen Dingen aufwändige Änderungsarbeiten bei Datenmodellmodifikationen zu vermeiden. Die Rechte können mit dem Schlüsselwort PUBLIC für alle Benutzer vergeben werden. ¾ Eine besonders weitreichende Option ist WITH GRANT OPTION, die es dem Benutzer ermöglicht, anderen Benutzern mit dem gleichen Befehl seine eigenen Rechte weiterzugeben. Einerseits entsteht so eine nicht mehr genau fassbare Struktur für den Administrator, welcher Benutzer welche Rechte besitzt. Andererseits jedoch kann man so eine gewisse Freiheit und Flexibilität in der Rechtestruktur einrichten. Da Benutzer mit dieser Option lediglich maximal ihre eigenen Rechte weitergeben können, ergibt sich ein verästelter Rechtebaum. An den Knoten sitzen die Benutzer mit dem Privileg, zumindest ihre Rechte zu vergeben oder innerhalb ihres Teams leichte Einschränkungen vornehmen zu können. Dies erspart dem Administrator, in größeren Gruppen oder in differenzierten Gruppenstrukturen jedes Mal selbst Rechte zu vergeben. – Eine andere Lösung für dieses Organisations- und Strukturproblem ergeben die Rollen in der nächsten Lektion. 1. Um allen Benutzern sämtliche Rechte für die Tabelle buchungen einzuräumen, weil z.B. jeder Mitarbeiter die Buchungswünsche eines Anrufers erfassen können soll. Dieser allgemeine Fall ergibt sich mit folgender einfachen Syntax, die sämtliche Standardwerte übernimmt. GRANT ALL PRIVILEGES ON TABLE buchungen TO PUBLIC 2. Eine einfache Variante, um Frau Hülzemann für alle Spalten Abfragen zu ermöglichen, ist ebenfalls sehr kurz und benötigt nur wenige Informationen. GRANT SELECT ON teilnehmer TO ElviraHuelzemann 3. Im nächsten Beispiel erhält Frau Hülzemann nur die Einfüge-Rechte für die Spalten, die sich weder mit den Vorkenntnissen noch den eigentlichen Kursinhalten beschäftigen, damit keine falschen Informationen eingetragen werden. Eine entsprechende Abfrage auf der Webseite könnte verhindern, dass Datensätze mit leeren Feldern überhaupt angezeigt werden. So entsteht eine kleine Kontrollfunktion mit dem Ergebnis, dass eine weitere Person die Kursinhalte verfassen muss und dass auch nur Kurse mit Kursinhalten auf der Webseite veröffentlicht werden. Der Unterschied zwischen UPDATE und INSERT besteht nun darin, dass für UPDATE sämtliche Spalten zu den Rechten hinzugenommen werden und daher nicht extra aufgeführt
170
SQL
ZUGRIFFSKONTROLLE
DURCH
BENUTZER, RECHTE
UND
ROLLEN
werden müssen. Lediglich der gegenteilige Fall, wenn also eine Einschränkung benötigt wird, erfordert eine Nennung der Spalten. GRANT SELECT DELETE INSERT (kursnr, titel, bereich, preis, dauer) UPDATE ON TABLE kurse TO AnnaMBullock WITH GRANT OPTION 4. Wenn man Rechte an mehreren Tabellen an mehrere Benutzer vergeben möchte, muss man den Block mit den Rechten entsprechend oft wiederholen. In diesem Fall möchte man an die Benutzer AnnaMBullock und MarieVareche Rechte an allen ausdrücklich genannten Spalten der Tabellen kurse und buchungen vergeben. GRANT SELECT DELETE INSERT (kursnr, titel, bereich, preis, dauer, vorkenntnisse, themen) UPDATE (kursnr, titel, bereich, preis, dauer, vorkenntnisse, themen) ON TABLE kurse INSERT (buchungsnr, kursnr, teilnnr) UPDATE (buchungsnr, kursnr, teilnnr) ON TABLE buchungen TO AnnaMBullock, MarieVareche Für mehr administrative Objekte einer Datenbank stellt SQL einen speziellen Befehl zur Verfügung. Sie hatten ja bereits gesehen, dass im obigen Fall lediglich Rechte für Tabellen bzw. Aktionen, die sich auf ihre Spalten beziehen, vergeben wurden. Wenn man den Zugriff dagegen auf DB-Objekte, die wir noch in keinem Projekt direkt erstellt haben, erlauben möchte, gibt es folgende allgemeine Syntax. Dabei bedeutet USAGE lediglich das Anlegen, Löschen oder Verändern (also insgesamt die Verwendung) von solchen Datenbankobjekten. GRANT USAGE ON DOMAIN name | COLLATION name | CHARACTER SET name | TRANSLATION name TO {benutzer1 [, benutzer2, ...]} | PUBLIC [WITH GRANT OPTION]
SQL
171
ZUGRIFFSKONTROLLE
DURCH
BENUTZER, RECHTE
UND
ROLLEN
8.3.2 Benutzern Rechte verweigern Neben einer expliziten Rechtevergabe besteht gleichfalls die Möglichkeit, Rechte ebenso explizit für Benutzer zu verweigern. Dadurch lässt sich insbesondere verhindern, dass Benutzer, die vom DB-Administrator aus eigentlich ein spezielles Recht nicht erhalten haben, dieses Recht von anderen Benutzern zugewiesen bekommen. Die allgemeine Syntax ähnelt strukturell der zuvor beschriebenen für die Rechtevergabe: DENY {ALL PRIVILEGES} | SELECT | DELETE | {INSERT [(spalte1 [, spalte2,...])} | {UPDATE [(spalte1 [, spalte2,...])} | {REFERENCES [(spalte1 [, spalte2,...])} }[, ...] ON [TABLE | VIEW] tabellenname TO {benutzer1 [, benutzer2, ...]} | PUBLIC [CASCADE] Folgende wenige Punkte gilt es zu beachten: ¾ Während mit ALL PRIVILEGES alle Rechte verweigert werden können, besteht ebenso die alternative Möglichkeit, explizit Befehle vorzugeben, die für Objekte oder Spalten nicht zugelassen sind. ¾ Über CASCADE verhindern sie, dass dieser Benutzer Rechte weitergeben kann.
8.3.3 Benutzern Rechte entziehen Hat ein Benutzer erst einmal Rechte erhalten, stellt sich natürlich alsbald das Problem, dass sie geändert oder gelöscht werden sollen. Dafür existiert ein Befehl, der dem Befehl für die Rechtevergabe vollkommen ähnlich ist: REVOKE [GRANT OPTION FOR] recht [, ...] ON tabelle FROM {benutzer1 [, benutzer2, ...]} | PUBLIC {CASCADE | RESTRICT} Zunächst erläutern wir kurz die allgemeinen Optionen dieses analogen Befehls, ehe wir noch einmal auf die Besonderheiten eingehen, die sich unmittelbar ergeben, wenn Benutzer das Recht haben, anderen Benutzern Rechte zu vergeben. Innerhalb des Rechtebaums entstehen in dem Moment des Rechteentzugs nachgelagerte Rechteentzüge. (Am besten ist ja ohnehin – wie Sie schon seit jeher vermuteten -, wenn der Administrator genug Schergen hat, über das ganze System seine grausige Herrschaft auszuüben – aber das nur am Absatzende.) ¾ Die im Befehl für die Rechtevergabe genannten Rechte benennt man in diesem Befehl an der Stelle von recht. Der Tabellenaufruf bleibt strukturell gleich. ¾ Die Benutzer erwähnt man entweder einzeln oder in einer Benutzerliste. Alternativ kann man auch der gesamten Öffentlichkeit durch PUBLIC das entsprechende Recht entziehen.
172
SQL
ZUGRIFFSKONTROLLE
DURCH
BENUTZER, RECHTE
UND
ROLLEN
¾ Abhängigkeiten in der Rechtevergabe berücksichtigt man beim Rechteentzug durch GRANT OPTION FOR. Dadurch kann man einem Benutzer das Recht nehmen, ein spezielles Recht einem anderen Benutzer zu übergeben. In nebenstehender Abbildung symbolisieren besonders kunstvoll arrangierte Totenköpfe die Problematik. Die Problematik, die sich durch einen Rechteentzug ergibt, stellt sich auf zwei Ebenen: Zum einen kann es passieren, dass der erste nachgelagerte Benutzer genau Rechte an diesem Recht weitergegeben hat. Diese Möglichkeit entfällt dann ja automatisch, sodass die nachgelagerten zweiten Benutzer das Recht verlieren. Zum anderen besteht die Möglichkeit, dass durch die Verwendung von GRANT OPTION FOR genau die Möglichkeit zur weiteren Rechtevergabe entzogen wird, die vom ersten nachgelagerten Benutzer bereits für zweite nachgelagerte Benutzer eingesetzt wurde. In diesem Sinne könnte man die Grafik noch mit beispielhaften Rechten ergänzen, wobei die Rechteweitergabe sich unterschiedlich auf die nachgelagerten Benutzer auswirkt, sobald die Rechte verschieden vergeben wurden und daher auch verschieden verringert werden. Dies verkompliziert aber nur noch das Grundproblem. Zur Versprachlichung der in der Grafik gezeigten Situation kann man die Rechte-Abhängigkeit noch mit direkt und indirekt charakterisieren. Der äußerste Baumast hängt direkt vom zweiten ab, aber indirekt vom ersten. Zur Lösung dieses Problems stellt der REVOKE – Befehl die beiden Optionen CASCADE und RESTRICT zur Verfügung: ¾ Im ersten Fall verwendet man REVOKE GRANT OPTION FOR ... RESTRICT: Das DBS prüft, ob Rechte an Dritte (in)direkt vergeben sind und beendet den Befehl mit einer entsprechenden Fehlermeldung. Dieselbe Prüfung läuft für DB-Objekte und virtuelle Tabellen ab, die der Benutzer angelegt hat. Sie könnten ja ebenfalls von anderen benutzt werden. ¾ Im zweiten Fall verwendet man REVOKE GRANT OPTION ... CASCADE: Man löscht damit die Berechtigung des nachgelagerten Benutzers, das Recht zu vergeben. Es bleibt hingegen selbst beim nachgelagerten Benutzer erhalten. Zusätzlich löscht man die Objekte der zweiten nachgelagerten Benutzer, die sie mit diesem Recht erstellt haben. ¾ Im dritten Fall verwendet man lediglich REVOKE ... CASCADE: Diese Kombination entzieht allen Benutzern das Recht, die es (in)direkt erhalten haben. Gleichzeitig löscht man damit auch alle DB-Objekte, die von ehemals berechtigten Benutzern erstellt wurden. 1. Um Frau Hülzemann keine Abfragen an der Tabelle teilnehmer zu erlauben und ihr ruhige Tage ohne Statistik zu gönnen, benutzt man den Standardbefehl, wobei man das Recht mit SELECT unter Nennung des Tabellennamens wieder zurücknimmt. REVOKE SELECT ON teilnehmer FROM ElviraHuelzemann 2. Damit die gesamte Öffentlichkeit daran gehindert wird, irgendwelche Buchungen in der Tabelle buchungen vorzunehmen, kann man ihr genauso leicht wie die Erlaubnis auch ein Verbot erteilen. Dabei ist der Adressat wie vorhin PUBLIC, während die verschiedenen Rechte erneut mit ALL PRIVILEGES zusammengefasst werden. REVOKE ALL PRIVILEGES ON buchungen FROM PUBLIC 3. Wenn Anna Mae Bullock weiteren Personen Rechte an der Tabelle kurse eingeräumt hat, dann verbleiben die ihr zugewiesenen Rechte, aber die Benutzer, denen sie die gleichen Rech-
SQL
173
ZUGRIFFSKONTROLLE
DURCH
BENUTZER, RECHTE
UND
ROLLEN
ten gegeben hat, verlieren diese. Gleichzeitig löscht man eventuelle DB-Objekte dieser Benutzer. REVOKE GRANT OPTION FOR SELECT, DELETE, INSERT, UPDATE ON kurse FROM AnnaMBullock CASCADE
8.4 Rollen einrichten Sie haben in den letzten Abschnitten gesehen, dass eine sehr sorgfältige, sprich realistische, Verteilung von Rechten sehr umfangreich und umständlich handhabbar wird. Das liegt einfach daran, dass man mit der derzeit vorhandenen Technik für jeden Benutzer Rechte vergeben muss und lediglich gleiche Rechte an mehrere Benutzer vergeben kann. Schöner wäre dagegen, man könnte Rechte in Mengen mit klaren Bezeichnungen zusammenfassen, um sozusagen Vorlagen mit Rechten zu erhalten. Diese Vorlagen bezeichnet man mit dem Begriff Rolle. Es ist mit ihnen also möglich, bei Benutzern häufig auftretende oder geplante Rechtestrukturen zu bündeln und diese Bündel Benutzern zuzuweisen. Dabei kann man nachher die Bündelstruktur ändern, ohne die Benutzerrechte einzeln aufzurufen. Die allgemeine Syntax für das Anlegen solcher Rollen ähnelt in der Zusammenschau sehr dem Anlegen von Benutzern: {ALTER | CREATE} rollenname [NOT IDENTIFIED |{IDENTIFIED BY kennwort | EXTERNALLY}] ¾ Zunächst muss die Rolle und ein eventuell zusätzliches Kennwort angelegt werden. Standardmäßig genügt allerdings, einen Rollennamen zu bestimmen. ¾ Alternativ kann man sich bei der Kennwortvergabe auch wiederum mit EXTERNALLY auf die Passwortüberprüfung des Betriebssystems verlassen. Eine nur benannte Rolle nützt natürlich wenig, wie Sie sich vielleicht schon gedacht haben, da ja innerhalb der Rollendefinition keine Rechtevergabe stattfindet. Diese beruht tatsächlich auf einem neuen Befehl, der eine Variation des vorhin vorgestellten GRANT – Befehls darstellt. Der einzig interessante Unterschied besteht darin, dass nicht die Möglichkeit besteht, die Öffentlichkeit aufzurufen: GRANT {ALL PRIVILEGES | SELECT | DELETE
174
SQL
ZUGRIFFSKONTROLLE
DURCH
BENUTZER, RECHTE
UND
ROLLEN
| {INSERT [(spalte1 [, spalte2,...])} | {UPDATE [(spalte1 [, spalte2,...])} | {REFERENCES [(spalte1 [, spalte2,...])} }[, ...] ON [TABLE] tabellenname TO {rolle1 [, rolle2, ...]} [WITH GRANT OPTION] Änderungen der Rolle beziehen sich wegen der Kürze des Definitionsbefehls auch nicht auf die Rechte, sondern vielmehr auf die Änderung des Passwortes. ALTER ROLE rolle NOT IDENTIFIED | {IDENTIFIED BY password | EXTERNALLY} Bleibt noch zu klären, wie ein Benutzer eine Rolle annehmen kann. Dafür gibt es eine Erweiterung des GRANT – Befehls, in dem die Rolle aufgerufen und über TO einem Benutzer zugewiesen wird: GRANT {recht | rolle} TO {[benutzer | rolle | PUBLIC]} ¾ Syntaktisch ist es möglich, Rollen wiederum Rollen zuzuweisen. Es entsteht dabei eine ähnliche Struktur wie der Rechtebaum, der hier ein Rollenbaum wäre. ¾ Darüber hinaus kann man auch der gesamten Öffentlichkeit eine Standardrolle über die Option PUBLIC zuweisen. Der Löschvorgang gestaltet sich zum Schluss wie immer trotz seiner Tragweite recht sang- und klanglos und beruht auf DROP. DROP ROLE rolle 1. Wenn mehrere Mitarbeiter mit statistischen Analysen betreut sind, lohnt es sich, eine entsprechende Rolle anzulegen. Dies geschieht mit der CREATE – Anweisung. CREATE ROLE Statistik 2. Dieser Rolle sollen dann für alle Tabellen Abfrage- und Aktualisierungsrechte zugeteilt werden. Dafür kommt der GRANT – Befehl mit den nötigen Einstellungen für diese Rolle ins Spiel. GRANT ALL PRIVILEGES ON teilnehmer ON buchungen ON kurse TO Statistik 3. Um diese Rolle zu löschen, wird sie lediglich im DROP – Befehl aufgerufen. DROP ROLE Statistik 4. Eine weitere Rolle namens Buchungsannahme soll angelegt werden. CREATE ROLE Buchungsannahme 5. Sie soll verschiedene Rechte enthalten, wobei eine Einschränkung für Änderungen gilt: Buchungsnummern sollen nachträglich nicht mehr geändert werden dürfen, um Fehler durch doppelt vergebene Nummern zu verhindern. Eine gesamte Buchung darf dagegen storniert wer-
SQL
175
ZUGRIFFSKONTROLLE
DURCH
BENUTZER, RECHTE
UND
ROLLEN
den. Zusätzlich räumt man dem Rollenträger auch noch die Möglichkeit ein, seine Rechte an einen anderen Benutzer oder eine andere Rolle zu übertragen. GRANT SELECT DELETE INSERT UPDATE kursnr, teilnnr ON buchungen TO Buchungsannahme WITH GRANT OPTION 6. Um die Rolle Statistik nun Elvira Hülzemann bzw. ihrem Benutzer zuzuweisen, genügt ebenfalls der einfache GRANT – Befehl. GRANT Statistik TO ElviraHuelzemann
8.4.1
Zusammenfassung
9 Man unterscheidet auf drei Ebenen Zugriffskontrollen: 1. Anmeldung über das Betriebssystem, 2. Anmeldung über ein Programm oder eine Webseite (mit einem entsprechenden Programm) und 3. Anmeldung direkt bei der Datenbank. 9 Für die Datenbankanmeldung bietet SQL drei Konzepte, die unterschiedlich in den einzelnen DBMS-Produkten implementiert wurden: 1. Benutzer, 2. Rechte und 3. Rollen. 9 Ein Benutzer ist eine natürliche oder künstliche Person, die eine DB-Sitzung mit Hilfe eines Benutzernamens und einem Passwort startet. 9 Rechte stellen Transaktionen wie Abfragen oder Aktualisierungen dar, die an Tabellen bzw. ihren Spalten ausgeführt werden. Sie werden anhand der SQL-Befehle unterschieden und können für eine Rolle oder einen Benutzer festgelegt werden. Wenn man eine solches Recht vergibt, erlaubt man, dass solche Transaktionen durchgeführt werden dürfen. 9 Rollen stellen Bündel von Rechten dar. Damit können typisierte Rechteverhältnisse oder Rechtemengen ausgelagert werden. Dies erlaubt dem Administrator, Benutzern solche Rollen und damit solche Rechtebündel zuzuweisen. 9 Über WITH GRANT OPTION verleiht man einem Benutzer oder einer Rolle das Recht, anderen Benutzern oder Rollen Rechte zu vergeben. Dabei entsteht ein Rechtebaum, der sich anhand der Benutzerstruktur und ihrer Rechtevergabe bildet. Eine direkte Abhängigkeit entsteht, sobald ein Rechteträger an einen direkt nachgelagerten weitere Rechteträger Rechte vergibt. Hat der erste Rechteträger seine Rechte wiederum von einem Rechteträger erhalten, so entsteht eine indirekte Abhängigkeit (via den zweiten Rechteträger) vom dritten zum ersten Rechteträger.
176
SQL
ZUGRIFFSKONTROLLE
8.4.2
DURCH
BENUTZER, RECHTE
UND
ROLLEN
Übungen
1. Legen Sie den Benutzer HeidiStern an, der über 842953 identifiziert wird. 2. Legen Sie erneut obigen Benutzer an und weisen Sie ihm direkt 20 MB Speicherplatz für den Tabellenbereich kursplanung_hs und kursplanung_hs_temp zu. 3. Ändern Sie das obige Passwort zu karlsruhe. 4. Weisen Sie alle Rechte an der Tabelle kurse der Öffentlichkeit zu. 5. Frau Stern darf die Tabelle kurse aktualisieren und abfragen. 6. Heidi Stern darf in der Tabelle termine folgende Spalten einfügen: Kursnummer, Beginn, Ende, Titel, und folgende Spalten aktualisieren: Titel, Beginn, Ende, Ort. Löschen und Abfragen ist ebenfalls erlaubt. 7. Entziehen Sie ihr Aktualisierungs- und Abfragerechte an der Tabelle kurse. 8. Entziehen Sie der Öffentlichkeit alle Rechte an der Tabelle kurse. 9. Legen Sie eine Rolle Dozent an. 10. Erlauben Sie den Dozenten, Titel, Themen, Vorkenntnisse und Dauer eines neuen Kurses in die Tabelle kurse einzutragen und in der Tabelle termine Kursnummer, Beginn und Ende. 11. Weisen Sie den beiden Autoren (deren Benutzernamen sich wie bei Heidi Stern bilden) die Rolle Dozent zu (danke).
SQL
177
ZUGRIFFSKONTROLLE
178
DURCH
BENUTZER, RECHTE
UND
ROLLEN
SQL
ZUGRIFFSKONTROLLE
DURCH
BENUTZER, RECHTE
UND
ROLLEN
9 MySQL, MS SQL Server und Oracle
SQL
179
ZUGRIFFSKONTROLLE
180
DURCH
BENUTZER, RECHTE
UND
ROLLEN
SQL
M Y S Q L , MS SQL S E R V E R
9 MySQL, MS SQL Server und Oracle
UND
ORACLE
Lernen Sie die ODBC- Schnittstelle kennen eine Datenbank in MySQL, MS SQL Server und Oracle anzulegen Tabellen in MySQL, MS SQL Server und Oracle anzulegen
Bisher haben Sie bereits einiges an Wissen zu Standard- SQL erworben. Dies ist, wie bereits vorab erwähnt, unabhängig von einem Datenbanksystem, was auch sehr gut ist. Somit kann man zum Beispiel mit einer Programmiersprache auf im Netz verteilte heterogene Datenbanken zugreifen und normalerweise die gleichen Abfragestrukturen benutzen.
Abfragen an das Datenbanksystem zu übermitteln
Mit Hilfe dieses Projekts können Sie mit einem der drei vorgestellten Systeme eine SQLUmgebung für Testzwecke einrichten. Bei MS Access gestaltet sich das recht einfach, allerdings haben wir es hier an vielen Stellen mit einem SQL-Dialekt zu tun, der überhaupt nicht dem Standard entspricht. Daher haben wir bisher aus gutem Grund MS Access nicht benutzt, um SQL in allen Einzelheiten zu erklären. MS Access ist allerdings ein Programm, welches eine intuitiv zu bedienende Oberfläche hat. Daher bietet sich MS Access auch an, wenn man Prototypen entwickelt. Diese kann man dann leicht auf den MS SQL-Server von Microsoft portieren. Eine komfortable Oberfläche ist bei Datenbanksystemen nicht ganz selbstverständlich. Nun gibt es bei MS Access einen entscheidenden Nachteil: Was ist, wenn Sie zum Beispiel die Daten zentral auf einem Server liegen haben möchten, auf dem jeder Benutzer die Daten ändern, löschen, anlegen oder einfach abfragen möchte? Dies dürfte eine typische Situation für eine Firma sein. MS Access gestaltet sich hier zunächst als Desktoplösung, wobei die Datenbank nur auf lokalen Rechnern vorhanden ist. Ab Office 2000 Premium Edition ist die Microsoft Database Engine MSDE mit enthalten. Diese ist ein abgespeckter SQL Server, der verwendet werden kann, wenn MS Access in der beschriebenen Situation nicht ausreicht. In diesem Projekt wird vor den konkreten Installations- und Konfigurationshinweisen zunächst jeweils der theoretische Hintergrund erklärt. In den Schritt-für-Schritt-Anleitungen zeigen wir Ihnen dann für die drei Datenbanksysteme MySQL, dem MS SQL- Server und Oracle, wie die Installation abläuft und wie Sie z.B. Abfragen an das System senden können. Bitte beachten Sie, dass wir hier natürlich keine ausführliche Beschreibungen der jeweiligen Systeme angeben können. Wir können Ihnen hier nur Anregungen geben, die Sie befähigen, erste Schritte mit Ihrem System zu gehen. Bei diesem Buch handelt es sich ja um ein reines SQL-Buch, welches sich an den Standard hält. Konkrete Datenbankmanagementsysteme halten sich im Einzelfall nicht an den SQLStandard oder bieten darüber hinaus weitere Möglichkeiten und Dialekte. Auch gibt es einige SQLBefehle, die dem Standard entsprechen, aber zum Beispiel von MySQL nicht unterstützt werden. In diesem Fall empfehlen wir den MS SQL-Server von Microsoft oder das marktführende Datenbanksystem von der Firma Oracle. Den MS SQL-Server gibt es als Test-Version kostenlos als 120- Tage-Version auf den Seiten von Microsoft http://www.microsoft.de, Oracle gibt es ebenfalls kostenlos für Testzwecke auf der Seite http://www.oracle.de.
SQL
181
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
9.1 Die ODBC- Schnittstelle Eine Möglichkeit ist, MS Access als Frontend bzw. als externe Sicht für den Benutzer einzusetzen. Für den MS SQL-Server ist das auch die empfohlene Variante. Ein Datenbankserver stellt dann das Backend für die Verwaltung dar. Die eigentliche Datenbank ist also im Netzwerk auf einem Server physikalisch vorhanden. Dies hat den Vorteil, dass Änderungen für alle angeschlossenen Benutzer gleichzeitig sichtbar sind. Bei der Datenpflege, um die sich mehrere Personen gleichzeitig kümmern, wäre dies von Vorteil, da man ansonsten immer die gesamte MS Access-Datenbank zum Beispiel per Mail durch die Gegend schicken müsste, bzw. diese auf einem Fileserver zur Verfügung stellen muss. Aber bei 5 gleichzeitigen Benutzern ist die Geschwindigkeit bereits so schlecht, das diese Lösung untragbar wird. Die Lösung mit Access als Frontend kann unter Windows, aber auch unter Linux, für jedes Datenbankserversystem eingesetzt werden, für die es einen ODBC- Treiber gibt. ODBC (Open Database Connectivity) ist eine universelle Schnittstelle für Datenbanken von der Firma Microsoft und hält sich an den SQL-Standard. ODBC liefert damit eine Schnittstelle für Anwendungen, die es zum Beispiel ermöglicht, eine Reihe von Clients auf die Ressourcen der Datenquelle zuzugreifen. Bei den Clients kann es sich um Benutzer, aber auch um Anwendungen handeln. Ein Beispiel für eine Anwendung wäre ein Verwaltungssystem wie Lexware, oder sogar SAP. Es gibt also eine eigene Oberfläche für dieses Programm, welches mittels der ODBC-Schnittstelle die Daten in einen Datenbankserver eintragen kann. Um ODBC einsetzen zu können, benötigen Sie einen Treiber, den es für die verschiedenen Betriebssysteme gibt. Es wird auch zwischen den Treibern von Windows9X/ME/NT/2000/XP unterschieden. Dabei handelt es sich bei ODBC nicht etwa um ein käufliches Produkt und es ist auch gewiss keine Anwendung. Normalerweise wird der Herstellers des Datenbanksystems den ODBCTreiber für alle erdenklichen Betriebssysteme mitliefern. Anderenfalls müssen Sie selbst im Internet danach suchen und ggf. herunterladen. Einer der großen Vorteile von ODBC ist, dass man in der Regel die zu Grunde liegende Datenbank einfach austauschen kann, ohne Änderungen am Programm vornehmen zu müssen. Mit ODBC kann man also Datenbankunabhängig programmieren. Nahezu jede Datenbank unterstützt ODBC und steht somit überall zur Verfügung. Aber es gibt auch einige Nachteile: ¾ Somit können zum Beispiel viele Funktionen des Datenbanksystems mit ODBC nicht genutzt werden, weil ODBC natürlich nur den Teil, der dem Standard entspricht, verarbeiten kann. Daraus resultiert auch, dass sich die speziellen Sicherheitseinstellungen des verwendeten Datenbanksystems nicht nutzen lassen. ¾ Abgesehen davon ist ODBC verhältnismäßig langsam, da jeder Befehl eben zunächst diese Schnittstelle durchläuft. Teilweise schaffen hier Treiber von Drittanbietern Abhilfe. Zum Beispiel gibt es für Oracle Treiber die deutlich schneller sind als die in Ihrem Betriebssystem vorinstallierten Treiber. ¾ Ein weiterer Nachteil ist, dass Microsoft seit einiger Zeit an der Entwicklung von OLE DB als neue universelle Schnittstelle zu Datenbankservern arbeitet. Dies soll ODBC gänzlich ersetzen und wesentlich einfacher und besser sein. Somit ist die Zukunft von ODBC ungewiss oder auf Dauer sogar besiegelt. Wenn Sie mit Windows NT/2000/XP arbeiten, können Sie mehrere Datenbanken standardmäßig benutzen. Unter anderem handelt es sich dabei um: ¾ MS Access (alle Versionen von 97 bis 2002) ¾ MS Excel
182
SQL
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
¾ MySQL ¾ SQL- Server (alle Versionen von 6.5 bis 2000) ¾ Oracle Wenn Sie nun mit mehreren Programmiersprachen auf die Datenbank zugreifen möchten, kann dies ohne ODBC sehr aufwändig werden. Mit ODBC ist es relativ einfach damit umzugehen. Im Internet können Sie mit Java, ASP, Perl, Python, PHP und weiteren Programmiersprachen auf Ihre Datenbank ohne Probleme zugreifen. PHP beispielsweise unterstützt eine Vielzahl an Funktionen von ODBC. Ihr Vorteil ist, dass Sie die Datenbank auf einem preiswerten und Ressourcen schonenden Datenbanksystem wie Access entwickeln und dann auf einfache Weise die Daten nach MySQL, MS-SQL oder sogar Oracle transferieren können. Die ODBC- Architektur besteht aus vier Schichten: ¾ Applikationsschicht (z.B. ein PHP- Skript) ¾ Treiber- Manager (Windows ODBC- Manager) ¾ ODBC- Treiber (z.B. MySQL – ODBC- Treiber für Windows) ¾ Datenquelle (MySQL- Server) Ein Begriff im Zusammenhang mit ODBC ist die Datenquelle (Data Source). Diese hat meistens den Namen Data Source Name (DSN). Es handelt sich dabei um einen logischen Namen, der frei vergeben werden kann. Dieser Name wird im ODBC- Manager eingerichtet. Dabei gibt es drei Arten von ODBC- Quellen, auf die Sie als Benutzer zugreifen können. ¾ User- DSN Hierbei handelt es sich um eine nutzerspezifische Datenquelle. Nur der aktuell angemeldete Nutzer des Computers kann auf diese Quelle zugreifen. Die Datenquelle kann dabei physikalisch auf einem Computer im Netzwerk vorhanden sein. ¾ System-DSN Hierbei wiederum handelt es sich um eine maschinenspezifische Datenquelle. Diese Datenquelle ist nur der Maschine zugeordnet. Es können nur Benutzer darauf zugreifen, die Zugriff auf den Computer selbst haben. Auch laufende Dienste bei Windows NT/2000/XP wie zum Beispiel der Webserver können auf diese Datenquelle zugreifen. ¾ File-DSN Es handelt sich hier wieder um eine nutzerspezifische Datenquelle, die aber von mehreren Personen genutzt werden kann. Dabei kann die Datenbank selbst immer irgendwo im Netzwerk liegen Hier kann aber auch die ASCII-Datei, in der der DSN gespeichert ist im Netz liegen. Es können alle darauf zugreifen, die über einen gleichartigen Treiber verfügen. Diese DSN speichert die Parameter in Textdateien. Im Folgenden möchten wir Ihnen Schritt für Schritt eine kompletten Installation aufzeigen, die Sie dann direkt nachvollziehen können.
9.2 MySQL und ODBC Bei dem Datenbanksystem MySQL handelt es sich um ein „schmales“ Open-Source Produkt. Die Lösung ist für den Firmeneinsatz allerdings sehr kostengünstig, im privaten Bereich darf MySQL sogar kostenlos genutzt werden. Somit ist dies eventuell der erste Datenbankserver, den Sie tes-
SQL
183
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
ten können und werden. Für viele Zwecke ist diese Lösung völlig ausreichend, für Großdatenbanken mit komplizierten Anforderungen ist diese Lösung sicherlich nicht geeignet. Zur Information: MySQL wurde von der schwedischen Consultingfirma TcX entwickelt, die ein extrem schnelles und flexibles Datenbanksystem benötigte. MySQL basiert zu einem kleinen Teil auf einem anderen Datenbank-Management-System (DBMS) namens mSQL. MySQL ist sehr weit verbreitet, vor allem Internetlösungen bedienen sich sehr gerne dieser Lösung. Die Popularität von MySQL erklärt sich zu einem großen Teil durch die Open- Source- Bewegung, aber sicherlich auch durch die Entwicklung von Linux in der Netzwerkserverumgebung. Als Beispiel möchten wir Ihnen zunächst zeigen, wie Sie MySQL installieren. Danach stellen wir Ihnen eine Oberfläche namens MySQL-Front vor, mit deren Hilfe Sie Datenbanken erstellen und löschen, Tabellen anlegen, verändern und löschen können. An sich wäre das Datenbanksystem so schon benutzbar, aber es ist immer noch etwas schwergängig. Daher wird es nachfolgend eine Anleitung geben, wie Sie MS Access nun tatsächlich mit ODBC als Frontend für MySQL benutzen können. Hier wird, wie Sie später noch sehen werden die Eingabe für den Datenbankbenutzer auch wesentlich einfacher.
9.2.1 Installation von MySQL unter Windows Folgendes Beispiel stellt eine Installation unter Windows 2000 dar. Selbstverständlich können Sie auch mit Windows 98/ME/NT arbeiten. Wir gehen innerhalb der Schritte kurz auf die wesentlichen Unterschiede ein, die Sie bei der Installation beachten müssen: 11. Zunächst gehen Sie auf die Seite http://www.mysql.com und laden sich die neuste stabile Version von MySQL herunter. Wichtig ist hierbei, dass Sie wirklich die Stable-Version nehmen, da die andere Version unter Development noch in der Testphase beziehungsweise noch in der Entwicklungsphase ist.
12. Nach dem ersten Klick kommen Sie auf eine Seite, auf der Sie verschiedene Versionen von MySQL finden werden. Für unsere Windows-Installation scrollen Sie bitte ein Stückchen nach unten, bis Sie an der entsprechenden Stelle den Download unter Windows finden. Betätigen Sie nun den Link Download.
184
SQL
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
13.Sie kommen nun auf eine Seite, auf der Sie einfach nur einen Server wählen können, der Ihnen den Download bereitstellt. Selbstverständlich empfehlen wir Ihnen, einen deutschen Server zu nehmen, wenn Sie sich in Deutschland befinden. Alle anderen funktionieren selbstverständlich ebenfalls, dürften aber nicht sehr schnell sein. Wählen Sie hier bitte FTP, und es wird Ihnen das für Windows typische Fenster angeboten.
14. Nun können Sie die Datei zunächst auf Ihren Desktop speichern. Selbstverständlich können Sie jeden anderen Speicherort wählen. 15.Im nächsten Schritt sollten Sie sich beispielsweise das Programm Winzip aus dem Internet downloaden. Dieses finden Sie unter http://www.winzip.com. Es würde sicherlich den Rahmen sprengen, eine Installationsanweisung des Programms Schritt für Schritt darzustellen. Wir sind jedoch der Meinung, dass dies wirklich sehr einfach ist und falls Sie nicht sogar ohnehin schon das Programm benutzen. 16. Öffnen Sie nun für die heruntergeladene gezippte MySQL-Version das Kontextmenü mit der rechten Maustaste. In dem erscheinenden Menü klicken Sie nun bitte auf Winzip / Extract to Folder. Sie nehmen dasjenige, welches nachher die Pfadangabe zu Ihrem Desktop enthält. Das File wird dann genau auf der Ebene (also hier den Desktop ) in einen Ordner entpackt. 17. In dem Ordner befindet sich nun eine Setup- Datei. Wenn Sie darauf doppelklicken, erscheint das Eingangsmenü. Klicken Sie bitte nun einfach zunächst zweimal auf die Schaltfläche Next.
SQL
185
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
18.An der nächsten Stelle können Sie den Installationspfad wählen. Übernehmen Sie hier bitte die Vorgaben. Merken Sie sich diesen Pfad genau und klicken Sie erneut zweimal auf Next.
Nach dem letzten Schritt haben Sie nun MySQL erfolgreich installiert. Es folgen im nächsten Abschnitt dieses Projekts einige Erklärungen dazu, wie Sie den MySQL-Server starten, wie Sie manuell Datenbanken, Tabellen und Datensätze einfügen. Bedenken Sie bitte vorab, dass der MySQL-Server selbst keine Oberfläche bereithält. Daher zeigen wir Ihnen zunächst einige Befehle, wie Sie den MySQL Server manuell mit Hilfe des DOS-Fensters bedienen können.
Im letzten Schritt haben wir den Ordner für den MySQL-Server den Pfad c:\mysql gewählt. In diesem Ordner mysql finden Sie die Dateien des Systems und der Datenbanken von MySQL.
9.2.2 Arbeiten mit der Eingabeaufforderung Nun aber beginnen wir, den Server zu starten und einen Überblick über Datenbanken und Tabellen zu erhalten, die bereits enthalten sind. 1. Starten Sie die Eingabeaufforderung Ihrer Windows-Version und geben Folgendes ein: C:\mysql\bin\mysql. Diese Eingabe spiegelt den Installationspfad von MySQL wider. In dem Ordner befindet sich der Unterordner bin, in dem sich die Startdatei von MySQL namens mysql befindet. 2. In einem zweiten Schritt sehen wir uns an, welche Datenbanken bereits vorhanden sind. Geben Sie dazu bitte den Befehl: SHOW DATABASES; ein. Damit die eingegebene SQL-Anweisung ausgeführt wird, müssen Sie am Zeilenende ein Semikolon (;) setzen. Das Semikolon ist das Zeichen das dem SQL-Interpreter bedeutet, dass der Befehl nun ausgeführt werden kann die nachfolgenden Anweisungen von dieser Anweisung getrennt sind. Drücken Sie nun
186
SQL
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
die Eingabetaste, und Sie sehen, wie die vorhandenen Datenbanken aufgelistet werden. 3. Nachdem wir nun die vorhandenen Datenbanken aufgelistet vor uns haben, können wir zum Beispiel die Datenbank mysql auswählen, indem wir den Befehl: USE mysql; eingeben. MySQL wechselt daraufhin zur Datenbank test Selbstverständlich können Sie sich mit dem Befehl auch andere Datenbanken ansehen, indem Sie eben statt test den aufgelisteten Namen der anderen Datenbank eingeben. 4. Nach der Auswahl der Datenbank können wir uns nun die Tabellen eben dieser Datenbank anzeigen lassen. Dazu benutzen Sie den Befehl: SHOW TABLES FROM test
Dies sollte als erste Einführung genügen. Sie können selbstverständlich hier die SQL-Befehle eingeben. MySQL unterstützt jedoch nicht alle Befehle aus dem Standard-SQL. Dabei handelt es sich insbesondere um Unterabfragen und Sichten, die Sie in den vorangegangen Projekten kennen gelernt haben. Zur Unterstützung von MySQL gibt es noch einige Oberflächen, die im Internet zur Verfügung gestellt werden. Dazu gibt es einmal den phpMyAdmin, bei dem es sich um eine webbasierte Lösung handelt, die unter PHP läuft. Nachteil hier ist, das wir zunächst einen Webserver aufsetzen und das PHP-Modul integrieren müssen. Diese Umgebung macht sofort Sinn, wenn Sie mit PHP programmieren. Das Programm ist sehr gut und vereinfacht das Anlegen einer Datenbank und die Erstellung von Tabellen und vor allem die Eingabe von Datensätzen in eine Tabelle, da man hier eine schon recht komfortable Oberfläche zur Verfügung hat.
9.2.3 Installation von MySQL- Front Eine Alternative bietet das Programm MySQL-Front. Auch bei diesem Programm handelt es sich um eine freie leistungsfähige Windowsoberfläche zu MySQL. Der Vorteil dieser Variante besteht darin, dass Sie hier eine grafische Oberfläche haben und nicht mit den Tippschwierigkeiten in der Eingabeaufforderung zu kämpfen haben. Ohne Ihnen in allen Einzelheiten dieses Programm zeigen zu wollen, folgen hier nur kurz einige erste Schritte. Ansonsten ist das Programm einfach und intuitiv zu bedienen. Wir hoffen, Sie beherrschen etwas Englisch, eine deutsche Version gibt es derzeit nicht:
SQL
187
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
1. Zum Download des Programms gehen Sie auf die Seite: http://www.anse.de/mysqlfront/. Dort finden Sie die neuste Version des Programms. Klicken Sie auf: Version 2.2 available oder die entsprechende neue Version. Suchen Sie wiederum erneut einen Speicherplatz für das Installationsprogramm von MySQLFront.
2. Im nächsten Schritt klicken Sie auf die Setup.exe-Datei der MySQL-Front-Version bitte doppelt, und es erscheint die Frage auf Englisch, ob Sie die Installation fortsetzen möchten. Klicken Sie hier bitte auf die Schaltfläche Ja.
3. Nun kommen Sie in das Setup-Programm, wobei Sie nun wiederum die Schaltfläche Next anklicken.
4. Nun müssen Sie die Lizenzvereinbarung mit Ja bestätigen. Hiermit unterschreiben Sie die Lizenzvereinbarung, die besagt, dass das Copyright bei dem Hersteller bleibt. 5. Klicken Sie bitte nunmehr noch fünfmal mal die Schaltfläche Nex. Im Wesentlichen legen diese Schritte Einstellungen wie zum Beispiel den Speicherort des Programms fest. Sie kommen dann zu einem Punkt wo Sie dann nur noch mit Finish bestätigen müssen, das Sie die Installation abgeschlossen haben. 6. Nun können Sie das Programm starten. Auf dem Desktop sowie in Start / Programme gibt es einen Eintrag zu MySQlFront, wo Sie das Programm starten können. Hier müssen einige Eintragungen vorgenommen werden, bevor Sie auf die Schaltfläche Connect klicken können:
188
SQL
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
7. In Description müssen Sie eintragen, ob Sie eine vorhandene Verbindung öffnen möchten oder ob Sie eine neue Verbindung zum MySQL-Server herstellen möchten. An dieser Stelle sollten Sie sich für New Connection entscheiden. 8. Als Nächstes geben Sie Ihren Host ein. Sie können hier zunächst, um es auszuprobieren, localhost oder eben die IP-Adresse 127.0.0.1 eingeben, die ebenfalls den localhost beschreibt. 9. Bei der Standardinstallation ist zunächst root der standardmäßige user. Ein Passwort ist derzeit noch nicht vergeben, also bleibt das entsprechende Feld leer. 10.Der Port ist auf Ihrer Windows-Installation 3306 und den Timeout setzen Sie bitte auf 30 Sekunden. Dies ist meistens vorgegeben, sodass Sie dies nicht eingeben müssen. 11.Bei Database müssen Sie nun noch den Namen der Datenbank eintragen, um zur entsprechenden Datenbank eine Verbindung aufzubauen. Gegebenenfalls kann das Feld leer bleiben, Sie haben in MySQL-Front später die Möglichkeit, die Datenbank auszuwählen. 12.Achten Sie darauf, dass Sie den MySQLServer bereits gestartet haben, nur dann können Sie mit der Oberfläche MySQLFront arbeiten, da es sich nur um ein Frontend für MySQL handelt. Nun klicken Sie auf die Schaltfläche Connect. Falls Sie keine Verbindung zu MySQL bekommen, achten Sie bitte darauf, dass Sie MySQL wirklich gestartet haben. Sie sehen sofort, dass Sie MySQLgestartet haben, wenn Sie nun eine Darstellung wie in nebenstehender Abbildung erhalten. Hier können Sie Datenbanken, Tabellen und schließlich sogar Datensätze anlegen.
9.2.4 DB und Tabellen anlegen in MySQL-Front In dieser Lektion lernen Sie, wie Sie die bereits angelegte Datenbank SemiTex aus Projekt 2 einfach in MySQL importieren. Dazu benötigen Sie an dieser Stelle kein neues theoretisches Wissen, da wir Ihnen ja bereits zuvor schon gezeigt haben, wie Sie eine Datenbank anlegen und wie Sie wiederum darin Tabellen und Datensätze anlegen. Dieses vorher erworbene Wissen müssen Sie nunmehr als Abfrage an den MySQL-Server schicken. Dies gestaltet sich sehr einfach, wie Sie den nachfolgenden Schritten ersehen können.
Sie finden die Tabellendefinitionen in der Datei SemiTex.sql.
SQL
189
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
1. Als Erstes müssen Sie in MySQL-Front die Tabelle SemiTex anlegen. Im Menüeintrag finden Sie zu diesem Zwecke unter dem Eintrag Tools den entsprechenden Eintrag Create Database. Es folgt ein Dialogfenster, in dem Sie den Namen der Datenbank, die Sie anlegen möchten, eingeben. In diesem Fall ist das SemiTex.
2. Darauf folgend können Sie die in Kapitel 2 als Abfrage erstellte Datenbank SemiTex eingeben. Klicken Sie dazu bitte auf der rechten Seite auf den Registereintrag Query. Nun können Sie den SQL-Abfragetext, den Sie erstellt haben, in die Abfrage hereinkopieren. Dazu können Sie ganz normal alles in Ihrem Textfile kopieren und dann entsprechend in MySQL-Front per Edit und dann Paste einfügen. Achten Sie bitte bei dem Vorgang darauf, dass Sie sich mit Ihrem Mauscursor in dem entsprechenden Query-Fenster befinden. 3. Nun schicken Sie die Abfrage an den MySQL-Server, indem Sie oben in der Symbolleiste auf den grünen Pfeil klicken. Danach müssen Sie allerdings noch einmal Tools / Refresh betätigen, sodass auf der linken Seite Ihre Datenbank SemiTex angezeigt wird.
4. Wenn Sie auf der linken Seite die Datenbank SemiTex anklicken, sehen Sie auf der rechten Seite verschiedene Karteikarten. Hier sind z.B. die Tabellen aufgelistet, die Sie angelegt haben, sobald Sie auf die Karteikarte Database klicken. Des Weiteren können Sie auf der linken Seite eine Tabelle auswählen und die Datensätze editieren.
190
SQL
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
Wir hoffen, dass diese Hinweise Sie weitestgehend in die Lage versetzt haben, alleine mit MySQL die SQL-Skripte zu testen. Experimentieren Sie also mit einigen der in den Projekten 2 bis 4 angegebenen Abfragen. Es sollte das entsprechende Ergebnis angezeigt werden - und dies in einer sehr komfortablen Oberfläche. Diese Abfragen können Sie natürlich eingeben, nachdem Sie die Registerkarte Query betätigt haben. Dort sehen Sie nach Betätigung des grünen Feldes unterhalb der Eingabe Ihrer Abfrage das Ergebnis der Abfrage in einer Tabelle aufgeführt.
9.2.5 ODBC- Verbindung zu MySQL mit MS Access Während der Datenbankentwickler sein Werkzeug hat, um die Datenbank zu modellieren, hat es der Datenbankbenutzer immer noch etwas schwer. Da es sich zumeist um unbedarfte Anwender (pardon) handelt, sollten diese es so einfach wie möglich haben. MS Access ist sehr einfach zu bedienen, zumindest wenn es darum geht, Datensätze in einem Formular oder direkt in eine Tabelle einzugeben. Daher zeigen wir Ihnen nun, wie Sie MS Access als Frontend für MySQL benutzen können. Das bietet auch letztendlich im Netzwerk einiges an Komfort, da ja eine größere Anzahl an Leuten mit dieser Datenbank arbeiten sollen. Dabei können Sie nicht viel an Vorkenntnissen bei allen Benutzern voraussetzen. Es gibt allerdings auch einen Nachteil bei der MySQL-MS Access-Lösung: MySQL verarbeitet keine gleichzeitigen Zugriffe. Die grundlegende Erklärung finden Sie als Hinweis im zweiten Projekt zum Thema Transaktionen. Bevor wir Ihnen Schritt für Schritt die Vorgehensweise aufzeigen, gestatten Sie uns noch einige theoretische Bemerkungen. In MS Access legen Sie zunächst eine Datenbank an. Dabei ist es wichtig, dass diese Datenbank auf jedem einzelnen Rechner, den wir nachher mit MySQL verbinden möchten, existiert. Das bedeutet, dass Sie in MS Access eine Datenbank anlegen und danach eine Verbindung zum MySQL-Datenbankserver aufbauen. Dabei kann natürlich MySQL auf einem ganz anderen Rechner vorhanden sein als auf den Rechnern, auf denen sich MS Access befindet. Dies bedeutet natürlich auch, dass Sie nicht auf die Datenbank zugreifen können, wenn der Rechner, auf dem der MySQL-Server läuft, heruntergefahren wird oder anderweitig ausgefallen ist. ODBC ist - wie bereits vorab schon erwähnt - auf Ihrem System implementiert. Was fehlt, ist der entsprechende Treiber zu MySQL. Wir werden Ihnen also in der anschließenden Schritt-fürSchritt-Erklärung aufzeigen, wie Sie ODBC installieren, in einem nächsten Abschnitt werden wir MS Access über ODBC mit der MySQL-Datenbank SemiTex verbinden. 1. Laden Sie sich als Erstes den entsprechenden ODBC-Treiber für MySQL von der offiziellen Seite von MySQL herunter: http://www.mysql.com. Auf der rechten Seite finden Sie ihn unter dem MySQL-Server, den Sie sich ja bereits aus dem Internet heruntergeladen haben. Der Download funktioniert auf die gleiche Art und Weise wie bei der Installation des MySQL-Servers beschrieben wurde. Achten Sie aber bitte darauf, dass Sie die entsprechende Windows-Version herunterladen. Wie bei den Gerätetreibern wird zwischen Windows NT/2000 und Windows 9X/Me unterschieden. 2. Im nächsten Schritt müssen Sie natürlich zunächst wieder beispielsweise mit dem Programm Winzip die heruntergeladene Datei entpacken. In dieser Datei finden Sie
SQL
191
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
dann eine Setup-Datei, die Sie wiederum doppelklicken müssen.
3. Nun geht’s weiter mit der Schaltfläche Continue. Danach bestätigen Sie die nächsten Schaltflächen und klicken dann einfach auf close. Sie müssen vorab nichts markieren. Nach Beendigung des Schrittes haben Sie den ODBC-Treiber installiert.
4. Den ODBC- Treiber können Sie in der Systemsteuerung finden. Unter Windows 2000 finden Sie ihn bspw. in Systemsteuerung / Verwaltung. Wenn Sie dort doppelklicken, finden Sie die Einstellmöglichkeiten von ODBC unter Windows. Sie finden dort die Benutzer-DSN, die System-DSN und die Datei-DSN, die weiter oben in diesem Kapitel beschrieben sind.
Der ODBC Treiber ist nun installiert. Jetzt wollten wir Ihnen noch zeigen, wie man MS Access nun mit der Datenbank SemiTex verbindet. Die Kenntnis wie man in MS Access eine Datenbank anlegt, setzen wir voraus, dies ist auch nicht schwer herauszubekommen: 1. Legen Sie in Access eine Datenbank namens SemiTex an. Diese speichern Sie bitte auf Ihren Desktop. 2. Wählen Sie Datei / Externe Daten / Tabellen verknüpfen.
3. MS Access fragt nun nach einem Speicherort. Da wir allerdings über ODBC unsere Datenbank ansprechen möchten, interessiert uns an dieser Stelle eher der DSNName, Benutzername und Passwort und schließlich der Host. Diese Informationen reichen für ODBC aus, um die Datenbank anzusprechen. Wählen Sie also bitte in der Abfrage des Speicherortes den Dateityp ODBC Databases().
192
SQL
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
4. Sie kommen dann automatisch in eine weitere Auswahl, wo Sie Computerdatenquelle auswählen. Diese Auswahl treffen Sie, weil Ihr MySQL-Server auf einem bestimmten Computer läuft und dort über ODBC ansprechbar ist.
5. Wählen Sie nun die Schaltfläche Neu. Sie kommen dann in ein weiteres Menü. Wählen Sie hier die Option Systemdatenquelle. Auf diese Weise kann jeder Benutzer des Computers auf die Datenquelle zugreifen. Wählen Sie dagegen Benutzerdatenquelle, kann nur der gerade angemeldete Benutzer auf die Datenbank zugreifen.
6. Wählen Sie an dieser Stelle den ODBCTreiber aus, über den Sie sich mit Ihrer Datenbank verbinden möchten. Da wir hier MySQL ansprechen wollen, wählen Sie also den neuesten MySQL-ODBC- Treiber aus und klicken auf die Schaltfläche Weiter.
7. Sie müssen nun noch ein Formular ausfüllen, mit dem Sie die entsprechenden Informationen an ODBC weitergeben. Es sind im Groben zwei Angaben, einmal die über den DSN und einmal die Parameter für die MySQL-Verbindung. Der DSN stellt den Namen der Datenbank dar. Wenn Sie diesen bisher noch nicht in ODBC vergeben haben, können Sie diesen hier frei vergeben. In das Feld Description können Sie eine frei wählbare Beschreibung einfügen, so dass Sie Informationen speichern können. Wichtig sind nun noch die Parameter für die Verbindung zu MySQL. In unserem Fall können Sie einfach localhost oder 127.0.0.1 für den Host eingeben, da Sie hier die Datenbank auf Ihrem anlegen und nicht im Netzwerk. Sonst müsste hier die IP- Adresse des entsprechenden Computers im Netzwerk stehen auf dem sich der MySQL-Server befin-
SQL
193
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
det.. In das Feld Database Name muss SemiTex, also der Name der anzusprechenden Datenbank eingegeben werden. 8. Wählen Sie die Schaltfläche Alle Auswählen und danach die Schaltfläche OK. Hier wählen Sie alle Tabellen aus, die Sie mit MS Access selbst verbinden möchten. Selbstverständlich können Sie auch nur eine oder mehrere Tabellen auswählen.
9. Wählen Sie im nächsten Schritt die Feldnamen für jede einzelne Tabelle aus. Sie sollten diesen Schritt sooft wiederholen, bis Sie alle Feldnamen aller Tabellen ausgewählt haben.
10.Sie sehen nun die Tabellen mit einem Pfeil von links auf ein Weltsymbol. Daneben steht die Bezeichnung der Tabelle. Dies ist das Zeichen einer Verbindung zu ODBC. Um alles Weitere, wohin verbunden wird etc., kümmert sich ODBC. Es ist auf diese Weise möglich auch innerhalb der gleichen MS Access-Tabelle auf verschiedene Systeme zuzugreifen. ¾
Nun haben Sie es geschafft, MS Access als Frontend für MySQL zu installieren. Das klappt zunächst einwandfrei. Wenn Sie MySQL auf einem anderen Rechner installiert haben möchten, können Sie dies bei Schritt 7 entsprechend eintragen. Weitere Erklärungen hierüber würden den Rahmen dieses Buches sprengen. Wir möchten an dieser Stelle auf den Coach über MySQL verweisen. Schwierigkeiten treten bei den Abfragen auf. Diese müssen Sie im Programm MS Access anpassen, da MS Access selbst bei den Abfragen einen teilweise für MySQL unverständlichen SQLCode erzeugt. Allerdings sollte Sie das nach den erworbenen Kenntnissen nicht mehr überfordern. Abfragen finden Sie unter den Objekten auf der linken Seite in Access. 1. Wählen Sie innerhalb des Objektes Abfragen den Punkt in der kleinen Symbolleiste des Objektes Neu aus.
194
SQL
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
2. Im nächsten Schritt wählen Sie den Eintrag Entwurfsansicht und klicken dann auf OK.
3. Die folgende Dialogbox Tabelle anzeigen können Sie einfach schließen. Dies können Sie per Mausklick auf das Kreuz oben tun, oder aber Sie betätigen die Schaltfläche Schließen.
4. Wählen Sie nun unter dem Menüpunkt Ansicht den Eintrag SQL-Ansicht. In dem folgenden Textfeld können Sie Ihr gelerntes Wissen einsetzen und wie gelernt den SQL-Befehl eingeben. Bedenken Sie bitte hier, dass Sie den SQL-Befehl an das Datenbanksystem MySQL abschicken und nicht an MS Access.
9.3 Der MS SQL- Server und MS Access Den ersten Teil haben Sie also geschafft. Nun möchten wir Ihnen gerne vorstellen, wie Sie den MS SQL- Server installieren. Hierzu ist zu sagen, dass Sie ab der Version von Access 2000 im Office Premium-Paket bereits einen kleinen MS SQL-Server erworben haben. Es handelt sich dabei um die so genannte Microsoft Data Engine (MSDE), die kompatibel mit dem MS SQL–Server ist. Anders als der MS SQL- Server unterstützt MSDE jedoch nur Datenbanken bis zu einer Größe von 2 GB. Zudem gibt es keine so umfangreiche Benutzerverwaltung wie bei MS SQL- Server. Zwar unterliegt MSDE keinen lizenzrechtlichen Beschränkungen hinsichtlich der Anzahl von Benutzern, allerdings ist er für nur fünf Benutzer optimiert. Bei über fünf Benutzern sollten Sie allein schon aus Performancegründen auf den MS SQL-Server zurückgreifen. Verwenden Sie eine kleine Serverdatenbank für kleine Arbeitsgruppen oder verwenden Sie Ihre Serverdatenbank nur zu Testzwecken und möchten Ihre Programme testen, so ist MSDE eine kostengünstige Alternative. Programmiertechnisch lässt MSDE sich genauso ansprechen wie der MS SQL-Server selbst. Wir werden Ihnen in diesem Kapitel zeigen, wie Sie wiederum die Datenbank SemiTex in den MS SQL-Server importieren und dann Ihre Abfragen an den Server verschicken. Selbstverständlich arbeitet der MS SQL-Server bzw. die MSDE noch sehr viel besser mit MS Access als Frontend zusammen, was nicht verwunderlich ist, da ja beide Programme von Microsoft kommen. Genau genommen ist MS Access die eigentliche Oberfläche zum MSDE. Der MS SQL- Server und somit auch der MSDE unterstützen konzeptuell den SQL-Standard. Außerdem verfügt der MS SQLServer über eine mächtige Erweiterung namens Transact SQL. Hierbei handelt es sich um eine Erweiterung von SQL. Somit stellt der MS SQL-Server eine mächtige Abfrageprogrammiersprache zur Verfügung. Eine Anweisung beschreibt eine ganz detaillierte Aufgabe, die der MS SQL-Server ausführen soll. Das ganze nächste Projekt beschäftigt sich eingehender mit dieser umfangreichen
SQL
195
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
Programmiersprache. In diesem Kapitel beschränken wir uns auf die Installation des MS SQLServers und der Verbindung mit MS Access als benutzerfreundliches Frontend.
9.3.1 Installation des MS SQL-Servers 1. Der erste Schritt ist natürlich der Start des Setup-Programms. Danach können Sie eine Auswahl treffen. Der eigentliche Server besteht aus den SQL Server 2000Komponenten. Wählen Sie also hier bitte die Schaltfläche SQL Server 2000Komponenten. 2. In einer weiteren Auswahl wählen Sie bitte den Eintrag Datenbankserver installieren.
3. Das nächste Dialogfeld kennen Sie aus typischen Installationen. Klicken Sie also hier bitte zunächst auf die Schaltfläche Weiter. Sie kommen im nächsten Schritt dann an eine Stelle, wo Sie wieder zwischen Lokaler Computer und Remotecomputer wählen können. Wählen Sie hier bitte Lokaler Computer und klicken Sie auf die Schaltfläche Weiter. Dabei ist der Lokale Computer der Computer vor dem der Benutzer gerade sitzt, währen der Remotecomputer ein Rechner im Netzwerk sein kann den man vom lokalem Computer aus steuern möchte.
196
SQL
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
4. Im nächsten Schritt legen Sie eine neue Instanz von SQL Server an. Hier können Sie entweder einen neuen SQL-Server auf dem oben ausgewählten Rechner (also lokal oder entfernt (engl. remote)) installieren, oder, falls bereits ein SQL-Server installiert ist eine neue Instanz (verhält sich so, wie ein zweiter MS SQL-Server, der aber physikalisch auf dem selben Rechner läuft) installieren.
5. Nun geben Sie Ihren Namen und gegebenenfalls Ihren Firmennamen ein. Der Firmenname ist nicht zwingend. Wählen Sie nachfolgend die Schaltfläche Weiter und bestätigen Sie den Lizenzvertrag.
6. Wählen Sie an dieser Stelle bitte die Server- und Clienttools aus. Unter anderem kann man damit auch Benutzer verwalten. Sie können an dieser Stelle auswählen, ob Sie entweder nur die Clienttools installieren möchten (d.h. Sie haben nur die Tools auf Ihrem Rechner; der DB-Server läuft auf einem anderen Rechner, den Sie aber nach der Installation von einem anderen Rechner aus verwalten können). Server- und Clienttools installiert den Server und die Clienttools, damit man den Server auch verwalten kann. Unabdingbar ist diese Auswahl deswegen, weil ansonsten kein MS SQL-Server installiert wird. Der dritte Punkt installiert die Konnektivität, d.h es wird nur all das installiert, was man braucht um z.B. mit einer Anwendung wie Access auf den Server zuzugreifen. Dies ist die Einstellung, die man für Client-Arbeitsplätze treffen muss, die keine Adminstrationstools benutzen sollen, also für die Anwender.
SQL
197
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
7. Im nächsten Schritt ist Standard in einem Kontrollkästchen ausgewählt. Sie haben nun die Möglichkeit, eine zusätzliche benannte Instanz von dem MS SQL-Server auf diesem Computer zu installieren. Wenn Sie dabei einen Namen eingeben, so darf dieser höchstens 16 Zeichen lang sein. Lassen Sie das Kontrollkästchen Standard aktiviert und klicken Sie auf die Schaltfläche Weiter.
8. Beim nächsten Schritt können Sie Ihr Benutzerkonto anpassen. Auf dieser Dialogseite können Sie angeben, unter welchem Benutzerkonto der MS SQL-Server Dienst laufen soll. Damit legen Sie automatisch fest, was der Dienst mit dem Rechner, auf dem er läuft machen darf und was nicht. Sie könnten für Ihren MS SQL-Server z.B. ein Benutzerkonto anlegen, das keine NT-Benutzer anlegen darf und nicht auf die wichtigen Dateien auf dem Server zugreifen darf. So können Sie verhindern dass ein Hacker in den MS SQL-Server eindringen kann (z.B. mit leerem Kennwort) und zudem nicht auch noch die Kontrolle über den Rechner erlangt, auf dem der SQL-Server läuft. Wenn Sie das Konto Lokales System auswählen, so läuft der MS SQL Server im Prinzip mit denselben Berechtigungen wie der Windows NT Kernel. Ein großer Nachteil wenn man das Konto Lokales System verwendet besteht darin, dass der MS SQL-Server dann nicht mehr mit MS SQL-Servern auf anderen Rechnern in derselben Domäne kommunizieren kann (Replikation). Hat man mehrere MS SQL-Server, so sollte man auf jeden Fall ein gesondertes Domänenbenutzerkonto verwenden. Unter Windows 9X/ME gibt es den Eintrag nicht, weil Win 9X keine wirklichen Benutzerkonten unterstützt. Wählen Sie bitte die Schaltfläche Weiter.
198
SQL
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
9. Im Windows Authentifizierungs-Modus wird lediglich die von NT zur Verfügung gestellte Authentifizierung verwendet (one user one password-Strategie). Die Benutzer selbst werden nicht in den MS SQL Server übernommen. Dort müssen Sie dann noch festlegen, welche Ihrer Domänenbenutzer überhaupt auf den MS SQL-Server zugreifen dürfen (Knoten-Sicherheit im EM) und auf welche Datenbanken (Datenbankbenutzer). Es wird vom MS SQL Server weiterhin keine Authentifizierung vorgenommen.
Wenn sich der Benutzer huelze an der Domäne anmelden konnte und wenn er Zugriffsberechtigungen auf dem MS SQL-Server hat, dann kann dieser Benutzer direkt zugreifen und muss nicht extra noch ein Konto und ein Passwort eingeben. Im gemischten Modus geht das auch. Der Unterschied ist allerdings, dass man zusätzlich noch Benutzerkonten auf dem Datenbankserver anlegen kann und sich mit diesen dann (Passwort + Konto) am Server anmelden kann. Wenn man eine Datenbankanwendung schreibt ist es immer besser, den gemischten Modus zu verwenden. Viele Datenbankanwendungen melden den Anwender über ein MS SQL-Konto an, das extra zu diesem Zweck erstellt wurde. Belassen Sie es also bitte bei der vorherigen Einstellung Windows- Authentifizierungsmodus und betätigen Sie die Schaltfläche Weiter.
10.Nach diesen Schritten haben Sie nun alles eingestellt, wählen Sie also die Schaltfläche Weiter und installieren Sie somit das Programm. Am Ende müssen Sie noch einmal bestätigen, dass Sie die Installation Beendet haben, wie für Windows- Programme üblich.
9.3.2 Arbeiten mit dem MS SQL-Server Nach der Installation zeigen wir Ihnen in diesem Kapitel, wie Sie den MS SQL-Server starten, beenden, Datenbanken anlegen und Abfragen an den Server schicken. Weiterhin möchten wir natürlich wieder eine ODBC- Verbindung herstellen und die Datenbank SemiTex mit MS Access bearbeiten. Das wesentliche Prinzip ist das gleiche wie bei dem MySQL-Server.
9.3.3 Starten, Anhalten und Beenden des MS SQL-Servers 1. Sie finden den so genannten DienstManager von dem MS SQL-Server unter Start /Programme / Microsoft SQLServer.
SQL
199
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
2. Sie können hier den Server starten, anhalten und beenden. Anhalten bedeutet quasi, eine Pause einzulegen. Das heißt, dass während dieser Pausenzeit keiner auf den MS SQL-Server zugreifen kann. Weiter unten in einem Kontrollkästchen können Sie einstellen, ob der Dienst beim Start des Betriebssystems automatisch gestartet werden soll. Jedes Mal, wenn Sie also den Rechner mit dem MS SQL-Server neu starten, wird der MS SQL-Server ebenfalls gestartet.
9.3.4 Der Enterprise Manager Wir stellen Ihnen in einem kurzen Abschnitt den Enterprise Manager vor. Hier werden wir nur einige wenige Worte darüber verlieren, da man mit diesem Programm die Benutzerverwaltung und Sicherheitssysteme und viele weitere Einstellmöglichkeiten des MS SQL-Servers vorfindet. Sie können dort auch Tabellenstrukturen verändern und verwalten, Sichten speichern und Vieles mehr. 1. Bitte öffnen Sie den Enterprise Manager über den Befehl Start / Programme / Microsoft SQL Server 2000.
2. Der Enterprise Manager bietet eine Fülle an Einstellmöglichkeiten. Dabei ist er ähnlich aufgebaut wie der Windows-Explorer, nur dass es sich natürlich nicht um Ordner und Dateien handelt, sondern um Objekte, die eine Datenbank beschreiben. Zum Beispiel können Sie sich hier die Datenbanken anzeigen lassen, die auf Ihrem MS SQLServer laufen.
9.3.5 Der Query Analyzer Der Query Analyzer ist ein Tool, vergleichbar mit dem Tool MySQL-Front für den Datenbankserver MySQL. Hier können Sie einfach Ihren SQL-Code eingeben, und Sie bekommen Ihr Abfrageergebnis in Tabellenform. Dabei unterscheidet sich allerdings der SQL-Code ein bisschen von dem, den Sie für MySQL-Abfragen benötigen. Im nächsten Abschnitt erklären wir Ihnen einige Haken.
200
SQL
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
1. Rufen Sie den Query Analyzer auf unter Start / Programme / Microsoft MS SQL Server 2000 / Query Analyzer.
2. Im nächsten Schritt können Sie den MS SQL-Server auswählen. Hier empfehlen wir wiederum die Windows-Authentifizierung. Wählen Sie nun bitte die Schaltfläche OK. In dem Query Analyzer können Sie nun wiederum Ihre Abfragen einfügen und an den Server verschicken.
9.3.6 Das Anlegen der SemiTex- Datenbank Nun gilt es noch die Datenbank SemiTex anzulegen. Beachten Sie hier bitte die Schwierigkeiten, die aus dem unterschiedlichen Dialekt von MS SQL-Server und dem MySQL- Server erwachsen. Wir haben Ihnen einfach den kompletten SQL-Code für diese Datenbank zum Download angeboten. Vergleicht man nun die beiden SQL-Quelltexte, so kommt man auf folgende Unterschiede, die wir in unten stehender Tabelle zusammengefasst haben: MySQL
MS SQL
int(5)
Int
varchar(5)
varchar
date
datetime
TYPE=MyISAM
Nicht vorhanden
Tab.1: Unterschiede des Codes MySQL- MS SQL- Server
Sie finden die Tabellendefinitionen in der Datei SemiTex_MS_SQL_Server.sql.
Nun erstellen wir die Datenbank SemiTex im MS SQL- Server:
SQL
201
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
1. Wir haben Ihnen den gesamten SQL- Code als Textdatei unter dem Namen SemiTex_MS_SQL_Server.sql zur Verfügung gestellt. Bitte kopieren Sie den Text in das Abfragefenster vom Query Analyzer. Schauen Sie sich ein wenig den SQL:- Code an und vergleichen Sie ihn gegebenenfalls noch einmal mit dem SQL-Code der MySQL- Datenbank. Zusätzlich machen wir es uns durch eine erste Zeile noch einmal einfach, indem wir die komplette Datenbank mit Hilfe von SQL anlegen. 2. Klicken Sie daraufhin auf die grüne Pfeiltaste - wie in der vorhergehenden Abbildung zu sehen. Danach haben Sie Datenbank, Tabellen und Datensätze fertig eingegeben. Anhand dieser Datenbank können Sie wiederum die Beispiele aus den ersten Kapiteln ausprobieren. Bevor Sie sich hierbei im Einzelfall über Fehlermeldungen kümmern, schauen Sie einfach erst einmal im Enterprise Manager nach, ob alle Tabellen angelegt sind.
9.3.7 ODBC- Verbindung von MS SQL-Server zu MS Access Im Wesentlichen passiert nun nichts Neues mehr. Sie können wiederum auf einfache Weise auch mit MS Access auf diese Datenbank zugreifen. Dies zeigen wir Ihnen in einer sehr kurzen Schritt für Schritt-Anweisung. 1. Wiederholen Sie bitte die Schritte der ODBC- Verbindung zu dem MySQL- Server bis zum Schritt 6, wo Sie allerdings nicht den MySQL- Server auswählen, sondern eben den MS SQL Server. Betätigen Sie die Schaltfläche Weiter. 2. Der nächste Schritt ist ähnlich dem Schritt 7 der Beschreibung zu der ODBC- Verbindung zu MySQL. Das auszufüllende Formular sieht hier etwas anders aus. Zudem sollten Sie für einen anderen Namen vergeben wie zuvor bei der MySQLDatenbank. ODBC merkt sich ja die Verbindung, und die mit dem DSN SemiTex ist bereits für die MySQL-Verbindung vergeben. Wählen Sie den entsprechenden SQL- Server aus und klicken Sie auf die Schaltfläche Weiter. 3. An der nächsten Stelle taucht wieder die Auswahlmöglichkeit auf, sich über NT zu authentifizieren oder über den MS SQLServer selbst. Bitte ändern Sie hier zunächst gar nichts und wählen Sie die Schaltfläche Weiter.
202
SQL
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
4. Im Prinzip kann hier irgendeine Datenbank angegeben werden. Das ist dann die Standard-Datenbank, die der SQL-Server nimmt, um nicht voll qualifizierte Tabellennamen aufzulösen. Hier können Sie die Datenbank angeben, in der man sich befindet, wenn man sich über diese ODBCVerbindung am SQL-Server anmeldet. Hier findet der ODBC- Treiber bzw. der MS SQL Server die entsprechenden Informationen.
5. Klicken Sie danach einfach erneut auf die Schaltfläche Weiter und im nächsten Schritt wiederum auf Fertig stellen. Danach springt ein Meldungsfenster auf, welches Sie mit OK bestätigen müssen. Bereits in diesem Meldungsfenster können Sie über die Schaltfläche Verbindung testen die Verbindung zunächst überprüfen. Dann können Sie wie vorhin schon bei der ODBCVerbindung zu MySQL beschrieben (Schritt 8) - die einzelnen Tabellen auswählen. Hierbei muss natürlich noch erwähnt werden, dass der MS SQL-Server einige System-Tabellen automatisch anlegt, die Sie vielleicht nicht benötigen, um mit MS Access darauf zuzugreifen. Diese müssen also nicht mit ausgewählt werden.
9.4 Oracle installieren und einrichten Kommen wir nun zum Marktführer für den Bereich der Großdatenbanken. Oracle hat die ANSI/ISO Norm SQL von 1999 in allen wesentlichen Punkten in seinen Produkten umgesetzt. Die neue Version 9i ist das Aushängeschild und läuft auf allen wichtigen Plattformen. Dabei ist Oracle 9i als Datenbankserver extrem gut gelungen. Oracle 9i teilt sich wie sein Vorgänger in mehrere Versionen auf, die selbstverständlich auch auf unterschiedlichen Preisniveaus und Ressourcenniveaus liegen: Oracle 9i Standard Edition, Oracle 9i Enterprise Edition und schließlich die Oracle 9i Personal Edition: ¾ Die Standard Edition kann für Rechnersysteme mit maximal vier CPUs lizenziert werden. Teil des RDBMS ist die Java Virtual Machine, sie verarbeitet gespeicherte Prozeduren oder erzeugt Java Server Pages. Oracle und Java ist ein sehr gutes Team, allerdings würde eine genauere Beschreibung natürlich den Rahmen dieses Buches sprengen. ¾ Die Oracle 9i Enterprise Edition beinhaltet selbstverständlich den Funktionsumfang der Standard Edition. Hinzu kommen allerdings noch viele weitere Eigenschaften und Merkmale, für Enterpriseanwendungen wie z.B Clustering. ¾ Die entsprechende Personal Edition ist für einen einzelnen Datenbankentwickler unter Windows2000 oder NT gedacht. Bis auf wenige Eigenschaften entspricht die Personal OracleVersion ansonsten der Oracle 9i Enterprise Edition. Somit kann der Einzelentwickler zu einem wesentlich günstigeren Preis als vor einigen Jahren alle Funktionalitäten von Oracle 9i Enterprise Edition testen. Dabei ist es ja noch gar nicht so lange her, als Freiberufler oder kleine Firmen nur schwer an ein Oracle-DBMS kommen konnten. Weitere Oracle-Produkte sind Oracle Forms, welches ein Entwicklungswerkzeug für die Erstellung formularbezogener Anwendungen gedacht ist. Speziell für formatierte Datenbankberichte oder
SQL
203
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
Analysen ist im Programm Oracle Reports integriert. Mit PL/SQL existiert des Weiteren eine eigene mächtige Erweiterung, die ungleich komplexer als Transact SQL ist und mit der man anspruchsvolle Programme entwickeln kann. In diesem Kapitel möchten wir Sie kurz in die komplexe Welt des wohl größten Datenbanksystems weltweit versetzen. Mehr als Ihnen die Angst vor einem ersten Kontakt zu nehmen, vermögen wir hier an dieser Stelle nicht, dies würde nämlich wieder einmal den Rahmen dieses Buches sprengen. Die folgenden Ausführungen dienen lediglich dazu, Ihnen Hinweise zur Installation des Servers und zur Einrichtung von Datenbanken und Tabellen zu geben.
9.4.1 Die Installation von Oracle 1. Sie finden das Datenbankprogramm zu Oracle auf der Seite http://www.oracle.de unter Download. Hier müssen Sie sich als Benutzer registrieren. Der Download zu Testzwecken ist kostenlos. Allerdings sollten Sie den Download gut organisieren; es handelt sich nämlich um drei umfangreiche CDs mit Daten. Doppelklicken Sie bitte auf der ersten CD die Setup.exe-Datei.
2. Im nächsten Schritt können Sie den Installationspfad und den Quellpfad bestimmen, indem Sie auf Durchsuchen an der rechten Seite klicken. Wenn Sie Ihre Quelle der Installation gefunden und sich für einen Installationspfad entschieden haben, wählen Sie bitte die Schaltfläche Weiter. Wählen Sie in den nächsten Dialogboxen Oracle9i Database X. aus, wobei das X für die neueste Version steht. Daraufhin wählen Sie bitte die Enterprise-Edition aus. Danach haben Sie alle Vorarbeiten für die eigentliche Installation vorgenommen.
3. Bitte geduldigen Sie sich für eine lange Zeit. Es dauert sehr lange, bis Oracle Sie auffordert, die nächste CD einzulegen. Werden Sie also nicht ungeduldig und brechen Sie nicht vorschnell ab. Insgesamt dauert es auch nach der dritten CD sehr lange, bis Oracle sich selbst und Ihr System konfiguriert hat. Bitte geben Sie dann einfach den Pfad zu Ihrem nächsten heruntergeladenen Ordner an.
204
SQL
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
4. In dem nächsten Schritt geben Sie bitte Ihr Systemkennwort ein. Dies können Sie frei wählen. Es muss im Übrigen ein Kennwort vergeben werden, Sie können die Felder also nicht leer lassen. Betätigen Sie danach die Schaltfläche OK.
5. Das nächste Dialogfenster bietet Ihnen weitere Installationen an. Die einfache Installation für eine Minimalkonfiguration und erste Experimente mit dem System ist allerdings abgeschlossen.
Nun ist es also soweit, Oracle ist installiert. Wie in den anderen Datenbanksystemen soll auch in Oracle die Datenbank der Firma SemiTex angelegt werden. Es gibt nun plötzlich viele Einträge zu Oracle innerhalb von Start / Programme, als dass wir diese alle einzeln vorstellen möchten. Wir wollen uns an dieser Stelle vielmehr auf das Wesentliche konzentrieren und unsere SemiTexDatenbank direkt per SQL anlegen.
Natürlich gibt es auch eine umfangreiche grafische Oberfläche, aber – wie gesagt – sie ist sehr umfangreich. Zudem können wir uns die fantastische Eigenschaft von SQL zu Nutze machen und es für die Bedienung des Systems anwenden.
9.4.2 Eine Datenbank in Oracle anlegen Nun, da Sie Oracle erfolgreich installiert haben, möchten wir Ihnen zeigen, wie man eine Datenbank anlegt. Hierzu möchten wir gerne auch noch einmal auf den bhv Coach zu Oracle verweisen, wo Ihnen wesentlich mehr Informationen gegeben werden. Hier an dieser Stelle würde es sicherlich zu weit gehen, wenn wir Ihnen eine grundlegende Einführung in Oracle geben würden. Nun werden wir allerdings in Oracle einmal eine Datenbank anlegen. Dies ist ein komplexes Unterfangen im Gegensatz zu MySQL, MS Access oder dem MS SQL-Server.
SQL
205
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
1. Sie finden unter Start / Programme / Oracle-OroHome92 / Configuration and Migration Tools / Database Configuration Assistant einen – wie der Name schon vermuten lässt – hilfreichen Assistenten für die gestellte Aufgabe.
2. Im sich öffnenden Dialogfenster wählen Sie die Schaltfläche Weiter. 3. Wählen Sie dann bitte die Option Datenbank erstellen.
4. Wählen Sie in der nächsten Dialogbox bitte die Option General Purpose aus. Betätigen Sie danach die Schaltfläche Weiter.
5. Im nächsten Schritt geben Sie für Globale Datenbanknamen SemiTex ein. Der Eintrag für die SID entsteht automatisch und sollte hier genauso heißen wie der Globale Datenbankname. Wählen Sie bitte wiederum die Schaltfläche Weiter. 6. Im nächsten Dialogfeld wählen Sie bitte die Option Dezidierter Servermodus aus und betätigen Sie die Schaltfläche Beenden.
7. Bei den nächsten zwei Schritten wählen Sie bitte jeweils die Schaltfläche Weiter. Hiernach folgt ein Hinweis, den Sie bitte mit OK bestätigen. 8. Nun müssen Sie an zwei Stellen zunächst Kennwörter eingeben. Bitte wählen Sie hier in diesem Zusammenhang beide Male das Kennwort oracle. Wenn Sie nun noch die Schaltfläche OK wählen, haben Sie die Datenbank angelegt.
206
SQL
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
9.4.3 Tabellen in die DB einfügen Nun ist es wieder an der Zeit, die Datenbank von SemiTex per SQL anzulegen. Hier gibt es wiederum ein paar Unterschiede, was den SQL-Quellcode anbelangt. 1. Zunächst starten Sie das SQLPlus Worksheet. Sie finden es unter Start/Programme/ Oracle-OraHome92 / Application Development/SQLPlus Worksheet.
2. Nun folgt ein Anmeldefenster. Melden Sie sich hier mit dem Benutzernamen system, dem Kennwort oracle , dem Dienst SemiTex an. In das Anmelden &als – Feld Wählen Sie bitte den SYSDBA aus.
3. Nun kommen Sie in das SQLPlus Worksheet. Kopieren Sie darin wiederum SemiTex_Oracle- Daten und betätigen Sie dann die Schaltfläche Ausführen, die Sie links in der Symbolleiste als Blitz dargestellt vorfinden.
9.4.4 ODBC mit Oracle verbinden Nun haben Sie es wieder geschafft. Sie haben eine Datenbank angelegt und die Tabellen und Daten darin eingespielt. Nun fehlt natürlich noch die Verbindung mit ODBC zu Oracle. Das ganze funktioniert zunächst nur, wenn Sie Oracle und Access auf dem selben Computer installiert haben. Ansonsten müssen Sie noch die Oracle-Netzwerkinfrastruktur auf dem Client Installieren. Im Wesentlichen ist die Vorgehensweise genauso wie in den beiden anderen Fällen. Sie haben es in Oracle natürlich mit einer ganzen Anzahl an Sicherheitstabellen und Administrationstabellen zu tun die wir hier nicht weiter erklären wollen. Sie müssen daher Ihre Tabellen, die für Sie relevant sind, an den jeweiligen Namen heraussuchen, was bei der Vielzahl nicht ganz so einfach ist. Nun aber wieder zu MS Access und der ODBC- Verbindung.
Sie finden die Tabellendefinitionen in der Datei Semitex_Oracle.sql.
SQL
207
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
1. Bis zum Schritt 6 ist wiederum alles identisch mit den beiden vorherigen Beschreibungen. Hier müssen Sie dann statt der anderen Treiber eben den Oracle-Treiber verwenden
2. Wählen Sie den Data Source Name SemiTex2. Im Feld Description können Sie eine allgemeine Beschreibung für die Datenbank eingeben. Dabei können Sie hier freien Text Ihrer Wahl eingeben. Ins nächste Feld TNS Service Name wählen Sie bitte den Eintrag SEMITEX aus. Betätigen Sie nun die Schaltfläche OK.
3. Im nächsten Dialogfeld müssen Sie erneut den Service Name SEMITEX eingeben und wiederum den User Name system, sowie das Password oracle. Bitte wählen Sie danach die Schaltfläche OK.
4. Nun kommen wir an eine von vorherigen Datenbanksysteme bekannten Stelle. Wir können jetzt die Tabellen auswählen, die zur Auswahl stehen, was im Fall von SemiTex die bereits bekannten Tabellen darstellen.
Somit haben wir nun auch in Oracle die Datenbank angelegt und mit MS Access wiederum eine ODBC-Verbindung hergestellt. Wir hoffen Sie haben nun genügend Material, um SQL wirklich auszuprobieren.
208
SQL
M Y S Q L , MS SQL S E R V E R
9.4.5
UND
ORACLE
Zusammenfassung
9 MySQL ist ein im privaten oder halb-kommerziellen Bereich (Vereine, kleine Organisationen) einsetzbares DBS, das gerade auch im Internet kostengünstig bei vielen Providern nutzbar ist. Seine Leistungsfähigkeit liegt bei einer kleinen Größe in seiner großen Arbeitsgeschwindigkeit, die allerdings mit dem Verzicht auf z.B. Unterabfragen erreicht wird. 9 MySQL lässt sich über die Eingabeaufforderung oder über Werkzeuge wie z.B. MySQL Front steuern. Insbesondere in Zusammenhang mit PHP gibt es ein bei verschiedenen Providern installiertes PHP-Programm namens phpMyAdmin, mit dem man die DB über das Netz mit Hilfe vieler HTML-Formulare ansprechen kann. 9 Einer der großen Vorteile von ODBC ist, dass man in der Regel die zu Grunde liegende Datenbank einfach austauschen kann, ohne Änderungen am Programm vornehmen zu müssen. Mit ODBC kann man datenbankunabhängig programmieren Nahezu jede Datenbank unterstützt ODBC und steht somit überall zur Verfügung. 9 Der MS SQL-Server stellt eine mittelgroße bis große Lösung dar und eignet sich besonders für den Einsatz in einer Microsoft-Umgebung mit den MS Office-Programmen. Ab Office 2000 Premium besitzt MS Access bereits einen kleinen MS SQL-Server: die Microsoft Data Engine (MSDE), die kompatibel mit dem MS SQL–Server ist. Anders als der MS SQL- Server unterstützt MSDE jedoch nur Datenbanken bis zu einer Größe von 2 GB. Im Prinzip können Sie (fast) alles mit der MSDE machen, was mit dem SQL-Server auch möglich ist. Bei der MSDE ist keine grafische Benutzeroberfläche enthalten. Sie können allerdings den Enterprise Manager eines SQL Servers dazu nutzen, die MSDE zu verwalten, ansonsten steuern Sie die MSDE über die Oberfläche von Access. 9 Oracle ist ein Großdatenbanksystem, das den SQL-Standard außerordentlich gut befolgt. Es ist besonders schwierig zu bedienen, aber mit SQL-Kenntnissen kann man alle wichtigen Konzepte dieses Buchs im SQL*Plus-Worksheet eintippen und ausführen lassen.
9.4.6
Übungen
1. Wie starten Sie MySQL? 2. Wie legen Sie eine Datenbank und DB-Objekte in MySQL an? 3. Wie legen Sie in Oracle eine Datenbank an? 4. Wie legen Sie in Oracle Tabellen und weitere DB-Objekte an und führen Abfragen aus? 5. Wie können Sie die Datenbanken mit ODBC verbinden?
SQL
209
M Y S Q L , MS SQL S E R V E R
UND
ORACLE
6. Wie können Sie MS Access prinzipiell mit den in diesem Projekt vorgestellten DBS verbinden? 7. Aus welchen Schichten besteht die ODBC-Architektur?
210
SQL
10 MS SQL Server und Transact SQL
SQL
211
M S SQ L S E R V E R
212
UND
T R A N S A C T SQ L
SQL
M S SQ L S E R V E R
UND
T R A N S A C T SQ L
10 MS SQL Server und Transact SQL Mit diesem Projekt verlassen wir die Beschreibung von Standard SQL und stellen Ihnen die Konzepte vor, die die Hersteller von DBMS entwickelt haben. Sie fußen dabei auf dem Transaktionskonzept, das hier auch kurz vorgestellt werden soll. Für jede dieser SQLErweiterungen gilt, dass wir der Breite den Vorzug vor der Tiefe geben. Für die Bedienung der Produkte wie MS SQL Server oder Oracle gehört in jedem Fall mehr als die Beherrschung der Transaktionsbefehle. Vielmehr geht es um eine Zusammenschau über die unterschiedlichen Möglichkeiten.
10.1
Lernen Sie das Konzept der Transaktionen kennen Transact SQL kennen die Datentypen vom MS SQL Server und Oracle zu unterscheiden in den Erweiterungen Variablen anzulegen und mit Daten zu füllen Anweisungsblöcke zu schreiben Kontrollstrukturen zu verwenden
Grundprinzip von Transaktionen
Die bisherigen Aktivitäten innerhalb der Datenbank waren relativ kurz, sodass Überlegungen über Implikationen, die mit diesen Aktivitäten in Zusammenhang stehen, gar nicht in den Vordergrund traten. Eine einfache Abfrage bereitet tatsächlich keine Schwierigkeiten für ein DBMS. Einerseits erfüllt es den Grundtatbestand einer Transaktion, dass die Datenbank von einem konsistenten oder korrekten Zustand in einen anderen solchen Zustand überführt wird, aber Aktionen bauen nicht aufeinander auf. Eine Überweisung von einem Konto auf ein anderes Konto besteht aus zwei grundlegenden Vorgängen: 1. Geld auf dem Quell-Konto abbuchen 2. Geld auf das Zielkonto buchen. Stürzt der Rechner ab, nachdem das Geld vom 1. Konto abgebucht wurde und unterstützt das System keine Transaktionen, so ist das Geld verloren, da es ja von Konto 1 abgebucht wurde, aber nie auf Konto 2 gutgeschrieben wurde. Unterstützt das System dagegen Transaktionen, so wird der Fehler erkannt und der Status vor der misslungenen Transaktion wieder hergestellt, d.h. das Geld wird wieder auf Konto 1 zurückgebucht. Der Zustand vor der Transaktion ist wieder hergestellt. Eine Transaktion stellt wie in der Abbildung eine Reihe von einzelnen Aktionen dar, die in einem logischen und inhaltlichen Zusammenhang stehen. Dabei können diese Aktionen sowohl vom Benutzer als auch im Rahmen eines Programms ausgeführt werden. Letzterer Fall ist im Zusammenhang mit SQL-Erweiterung von besonderer Bedeutung, weil mit ihnen Programme entwickelt
SQL
213
M S SQ L S E R V E R
UND
T R A N S A C T SQ L
werden können, die komplexe Vorgänge mit Vergleichen, Entscheidungen und fallweiser Datenmanipulation selbstständig ausführen können. Als Beispiel für ein Programm, das mit Transact SQL möglich ist, soll folgende Überlegung dienen: Eine Firma kontrolliert die Abverkäufe von Produkten in einem Webshop oder in einem angeschlossenen Ladennetz. Dabei setzt man eine einfache Heuristik als Controlling-Werkzeug ein, um Neubestellungen und Preise zu kontrollieren. Als kritische Schwelle wurde ein Nachfragerückgang von 25 % ermittelt, der nur über einen gewissen Zeitraum akzeptiert wird. Neben dem Preisrückgang wird also in einer ersten analysierenden Abfrage auch der Zeitpunkt erfasst, seit wann dieser Nachfragerückgang anhält. Die eigentliche Analyse besteht dann aus drei einfachen Faustregeln, die ein Vielfaches des vorgegebenen Zeitraums wie eine Woche oder einen Monat einbeziehen: ¾ Wenn der Zeitraum für den Nachfragerückgang mehr als den doppelten Vergleichszeitraum umfasst, sollen der Preis um 10 % und das Bestellvolumen um die Hälfte gesenkt werden. Dies könnte man damit erklären, dass normalerweise bei einem Produkt am Ende des Produktlebenszyklus der Lagerbestand unter Berücksichtigung der verringerten Bestellmenge an den Nachfragerückgang angenähert ist. ¾ Wenn der Zeitraum für den Nachfragerückgang dagegen schon mehr als den dreifachen Vergleichszeitraum beträgt, vergrößert sich der Preisrückgang auf 15 %, während das Produkt allerdings gar nicht mehr bestellt werden soll. ¾ Wenn der Zeitraum für den Nachfragerückgang dagegen sogar mehr als den fünffachen Vergleichszeitraum umfasst, soll die verbleibende Ware nicht nur aus dem Angebot genommen werden, sondern natürlich auch nicht mehr bestellt werden. Unschwer erkennen Sie an diesem Beispiel, dass eine Vielzahl von einzelnen DB-Aktionen mit den Befehlen SELECT, UPDATE oder DELETE zu einer größeren Anwendung, also einer klassischen Transaktion zusammengefasst werden. Während die Fallunterscheidung bereits ganz typisch nach einer if-elseVerzweigung aussehen, sind die einzelnen Aktionen wie Preisreduktion oder Bestellungsverminderung in den einzelnen Anweisungsblöcken gespeichert. Zwei Problemkreise bzw. gemäß der Abbildung zwei Gewitterwolken schweben über DBTransaktionen: Wie bei allen Anwendungen und insbesondere Anwendungen in größeren Netzwerken kann es durch Komplexitäten innerhalb der Anwendung oder Datenübertragungen zu Problemen im Bereich des Datenerhalts und Strukturerhalts gehen. Unter gar keinen Umständen darf es geschehen, dass
214
SQL
M S SQ L S E R V E R
UND
T R A N S A C T SQ L
im Rahmen der Transaktion ein Fehler geschieht, der einen ungewollten Datenverlust oder eine Strukturänderung der Datenbank selbst nach sich zieht. Ein weiteres Problemfeld, das vom DBMS gelöst werden muss, ist die zeitgleiche Anfrage für die Abarbeitung von Transaktionen unterschiedlicher Benutzer. Hierbei muss insbesondere darauf geachtet werden, dass eine konkurrierende Abfrage während der Abarbeitungszeit nicht das Grundprinzip zerstört, dass die Datenbank von einem konsistenten Zustand in einen anderen überführt wird. Gerade bei Mehrbenutzerbetrieb und umfangreichen Transaktionen, die über einfache Abfragen oder kurzen Eintragungsvorgängen hinausgehen, und somit längere Zeit in Anspruch nehmen, muss das DBMS die Abfragen in einer geeigneten Reihenfolge abarbeiten, dass Abfragen mit überschneidenden Befehlen wie Lösch- und Einfügevorgänge in die gleiche Tabelle oder aufgrund gleicher Suchkriterien nicht zu Inkonsistenzen führen. Prinzipiell setzt das DBMS dabei parallele Anfragen so um, dass sie in eine geeignete Reihenfolge gebracht und damit eigentlich nicht wirklich gleichzeitig abgearbeitet werden. Die beiden entscheidenden SQL-Befehle sind COMMIT und ROLLBACK: ¾ COMMIT (programm) übermittelt die Transaktionen und setzt sie damit für alle Benutzer, die zeitgleich mit der Datenbank arbeiten, sichtbar um. ¾ ROLLBACK (programm) versetzt die Datenbank wieder in einen korrekten Zustand.
10.2 Transact SQL - Variablen und ihre Datentypen Transact SQL ist der SQL-Dialekt, der im MS SQL Server implementiert ist und mit dem umfangreiche Programme erstellt werden können.
10.2.1
Datentypen im MS SQL Server
Bevor wir direkt mit der Variablendeklaration beginnen, nennen wir kurz die in diesem DBMS vorhandenen Datentypen. Die Variablen können nur die Datentypen annehmen, die für die Daten in der Datenbank bereitstehen. ¾ Zeichenstrings char [(länge)] speichert Zeichenkette in fester Breite. Nur für diesen Zeichenkettentyp können Sie also eine Längenangabe machen wie z.B. für den klassischen Fall der Postleitzahlen. varchar berücksichtigt keine voreingestellte Länge, sondern eignet sich für kurze Texte wie Familiennamen, Produktbezeichungen und natürlich gemischt-alphanumerische Ausdrücke wie Telefonnummern mit Klammern oder Pluszeichen für die Ländervorwahl. text speichert lange Texte wie für Produktbeschreibungen oder Kommentare. ¾ Numerische Datentypen int übernimmt ganze Zahlen ohne Kommawerte von -2,147,483,648 bis +2,147,483,647, wobei die Kommata die englischen Tausenderpunkte darstellen.
SQL
215
M S SQ L S E R V E R
UND
T R A N S A C T SQ L
smallint übernimmt ganze Zahlen von -32,768 bis 32,767. tinyint übernimmt ganze Zahlen von 0 bis 255. float übernimmt positive oder negative Zahlwerte mit Dezimalstellen, deren Standardenauigkeit 15 Stellen umfasst. real speichert sehr große Dezimalzahlen zwischen 3.4E-38 bis 3.4E+38 (Exponentialschreibweise). ¾ Datumswerte datetime speichert Datumswerte vom 1. Januar 1753 bis 31. Dezember 9999. smalldatetime speichert Datumswerte vom 1. Januar 1900 bis 6. Juni 2079 aus. ¾ Datentypen für Währungen money speichert Preise zwischen -922,337,203,685,477.5808 und +922,337,203,685,477.5807, wobei die Kommata die englischen Tausenderpunkte und der Punkt das englische Dezimalkomma ist. smallmoney speichert Preise zwischen -214,748.3648 und +214,748.3647 mit den obigen Schreibkonventionen. ¾ Binäre Zeichenketten / Daten binary speichert binäre Zeichenkette mit einer festen Länge. varbinary speichert binäre Zeichenkette für eine variable Länge. image speichert sehr große binäre Zeichenketten wie sie von Bilddateien verursacht werden. ¾ Logische Daten Wenn Sie bereits mit MS Access Optionsfelder mit Ja/Nein-Abfrage erstellt und gespeichert haben, wissen Sie, dass die beiden Zahlen 1 und 0 für die beiden Werte WAHR und FALSCH zur Verfügung stehen und auch genauso in der Datenbank bzw. in der entsprechenden Spalte erscheinen.
10.2.2
Variablen deklarieren und mit Werten füllen
Die allgemeine Syntax für die Deklaration von Variablen besteht aus dem Befehl declare, an den der Variablennamen mit @-Zeichen angefügt wird, gefolgt vom Datentyp der Variable. Da es hier um die Variablen in einer reinen Datenbank-Umgebung geht, ist Transact SQL wie die anderen SQL-Erweiterungen natürlich typbasiert. Dies wird vermutlich weniger überraschen als das Vorgehen, wie einer Variable ein Wert zugewiesen wird. Hierbei erfolgt der Aufruf über select oder set, einen angeschlossenen Zuweisungsoperator und den eigentlichen Wert. Anstatt eines explizit genannten Werts kann man auch eine geeignete Abfrage anschließen. declare @variablenname datentyp select @variablenname = wert set @variablenname = wert 1. Legen Sie eine Variable PLZSollbach für die Postleitzahl der Stadt Sollbach fest. Da eine deutsche Postleitzahl gespeichert werden soll, eignet sich der oben beschriebene Datentyp char mit der Länge 5. Der Befehl go gehört nicht zu Transact SQL, sondern veranlasst den MS SQL Server, die Befehle abzuarbeiten. declare @PLZSollbach char(5)
216
SQL
M S SQ L S E R V E R
UND
T R A N S A C T SQ L
go 2. Um mehrere Variablen direkt nacheinander festzulegen, schließt man sie aneinander, indem sie durch ein Komma verbunden werden. Sie können natürlich auch in einer Zeile stehen, doch fördert das bei wechselnden Datentypen oder einer längeren Liste nicht die Übersichtlichkeit. declare @PLZSollbach char(5), @PLZWedelingen char(5), @PLZWillingen char(5) go 3. Variablen benötigen Werte, um sinnvoll in Programmen eingesetzt werden zu können. Wenn sie bereits zuvor einen Wert erhalten sollen, kann er einfach über den Befehl select und einen angeschlossenen Zuweisungsoperator in Form eines Gleichheitszeichens übergeben werden. Zeichenketten benötigen Redezeichen, um sie zu begrenzen, Zahlwerte wie immer keine. declare @PLZSollbach char(5) select
@PLZSollbach = 84571
declare @PLZSollbach char(5) select
@PLZWillingen = 84569
go Es ist sowohl interessant, Variablen feste Werte mit auf ihren Weg zu geben, als auch, Werte durch eine Abfrage im Programmablauf zu ermitteln und dieses Ergebnis zu verwenden.
Bei den über DECLARE deklarierten Variablen handelt es sich um lokale Variablen, d.h. sie sind in dem Skript bzw. der gespeicherten Prozedur verfügbar, in der sie deklariert wurden. Im Gegensatz zu den lokalen Variablen gab es unter den alten Versionen des MS SQL-Servers (bis 6.5) die globalen Variablen, die mit zwei @-Symbolen beginnen (z.B. @@VERSION für die das Versionsdatum des Servers oder (@@total_read für die Anzahl der Lesezugriffe seit Serverstart). Seit dem SQL-Server 7.0 werden diese als Funktionen bezeichnet, was die eigentlichen Funktion dieser „globalen Variablen“ besser beschreibt, da man die Werte der globalen Variablen nicht ändern kann.
1. Variablen können innerhalb einer gemeinsamen Deklaration nur einen Datentyp besitzen, die unbedingt die Datenstruktur der eingehenden Informationen widerspiegeln müssen. Im folgenden Beispiel sollen die Daten für die Variablen über Abfragen mit Aggregatfunktionen erzeugt werden. Dies bedeutet, dass bei Durchschnittspreisen regelmäßig Kommazahlen entstehen, die über den Datentyp float gespeichert werden können. Dagegen benötigt man für einfache Zählungen den Datentyp int. declare @tagespreis money, @durchschnittsdauer float @buchungszahl int
SQL
217
M S SQ L S E R V E R
UND
T R A N S A C T SQ L
2. Da man für diese Variablen keine statischen Werte speichern möchte, sondern stattdessen die aktuellen Berechnungen auf Grundlage der Daten innerhalb der Datenbank, muss man sich geeignete Abfragen überlegen, die genau einen Wert extrahieren, den man in den Variablen speichern kann. Diese Abfragen stellen prinzipiell die gleichen Abfragen wie in den zurückliegenden Projekten dar. Der einzige Unterschied besteht nun darin, dass direkt nach select die Variablenbezeichnung mit dem Zuweisungsoperator steht. select @durchschnittspreis = avg(preis)/avg(dauer) from kurse select @durchschnittsdauer = avg(dauer) from kurse select @buchungszahl = count(*) from buchungen go 3. Die im letzten Schritt beschriebenen Abfragen liefern die Werte in der nebenstehenden Abbildung. Alternativ könnte man sie auch mit der folgenden Syntax direkt zuweisen. declare @tagespreis money select
@tagespreis = 292.46
declare @durchschnittsdauer float select
@durchnschnittsdauer = 2.7600
declare @buchunsgzahl int select
@buchungszahl = 191
go
10.3
Verzweigungen und Schleifen
Neben bloßen Variablen braucht man für halbwegs interessante Programmabläufe neben einer interessanten Fragestellung auch Möglichkeiten, die Programmausführung zu steuern. Dazu unterscheidet man strukturell zwischen Verzweigungen und Schleifen, die von Transact SQL zur Verfügung gestellt werden: ¾ Mit einer Verzweigung kann über eine Fallunterscheidung eine Auswahl unter verschiedenen Programmabläufen getroffen werden. Damit dient die Bedingung, die für die Fallunterscheidung geprüft wird, wie eine Kreuzung dazu, die eine oder andere Verzweigung bzw. den einen oder anderen Programm-Ast auszuwählen. ¾ Mit einer Schleife hingegen bietet sich die Möglichkeit, einen Anweisungsblock so lange zu wiederholen, bis eine Bedingung erfüllt ist.
218
SQL
M S SQ L S E R V E R
10.3.1
UND
T R A N S A C T SQ L
Die if - else - Anweisung
Der Anweisungsblock in Transact SQL wird nicht – wie in vielen anderen Programmiersprachen typisch – mit geschweiften Klammern umschlossen, sondern besitzt die Struktur: begin anweisungen anweisungen end Innerhalb der IF – Anweisung befindet sich zunächst der zu überprüfende Ausdruck. Ist der zurückgelieferte Wert WAHR, wird der Anweisungsblock A durchlaufen. Im gegenteiligen Fall arbeitet der Server den Anweisungsblock B ab, der mit dem Schlüsselwort ELSE eingeleitet wird. 1. Zunächst wird der Durchschnittspreis wie zuvor in einer neuen Variable @durchschnittspreis gespeichert und der Wert durch eine Abfrage der Tabelle kurse bestimmt. Nebenstehende Abbildung soll nicht das Programm illustrieren, sondern gibt einige Informationen, die für das Programm nützlich sind. Neben der Angabe des Durchschnittspreises finden Sie dort auch die Anzahl der Kurse, die teurer als der Durchschnitt sind. Das Programm soll dann überprüfen, ob der Durchschnittspreis über 1000 Euro liegt. Dies könnte der Fall sein, da es relativ viele Kurse zu einem Preis über diese Grenze im Angebot gibt. declare @durchschnittspreis money select
@durchschnittspreis = avg(preis) from kurse
2. In der Abfrage soll nun überprüft werden, ob der Durchschnittspreis über 1000 Euro liegt. Diese Bedingung tragen Sie lediglich in den Ausdruck nach if mit Hilfe des Vergleichsoperators „größer als“ ein. if (@durchschnittspreis > 1000) 3. Der erste Anweisungsblock soll dann mit Hilfe der Funktion print die Information ausgeben, dass der Durchschnittspreis tatsächlich oberhalb dieser Grenze liegt, während der zweite Anweisungsblock (ohne Bedingung) das Gegenteil ausgibt. Die Ausgabe erfolgt nur im Server und nicht etwa auf der Webseite. begin print 'Der Durchschnittspreis liegt über 1000 Euro.' end else
SQL
219
M S SQ L S E R V E R
UND
T R A N S A C T SQ L
begin print 'Der Durchschnittspreis liegt unter 1000 Euro.' end go Mit dem Ihnen bereits bekannten Operator exists kann man gerade in einer Bedingung arbeiten. Dies ist ein Beispiel, wie ein zurückgelieferter Wert im DBMS eingesetzt werden kann. Man möchte ermitteln, ob überhaupt Kurse aus dem Bereich Server und Betriebssysteme stattgefunden haben, wofür man die Tabellen buchungen und kurse verknüpfen muss. In diesem Fall kann man über exists ermitteln, ob ein Abfrageergebnis existiert, d.h., ob überhaupt eine Ergebniszeile zurückgegeben wird. 1. Dieses Mal benötigen Sie keine schon vorher definierte Variable. Stattdessen wird alles Benötigte in den Anweisungsblock ausgelagert, der ausgeführt wird, sobald der Wert TRUE zurückgeliefert wird. Dies ist der Fall, wenn die Abfrage bzgl. möglicher Kursbuchungen aus dem Server-Bereich mindestens eine Ergebniszeile liefert. Nebenstehende Abbildung zeigt sowohl das inhaltliche Ergebnis der Bedingungsabfrage wie auch die Anzahl der Buchungen. (Dass es sich um Kurse zu MS SQL Server handelt, ist schicksalhafter Zufall, wie EDVTrainer sie mühevoll einzurichten wissen.) if exists (select titel, buchungen.kursnr, buchungen.buchungsnr from buchungen natural join kurse where kurse.bereich="Server / BS") 2. Im Anweisungsblock nun definieren Sie die Variable @buchungenanzahl, die ja erst benötigt wird, wenn klar ist, dass überhaupt Buchungen erfolgt sind. Sie ermittelt über eine Abfrage mit der Aggregatfunktion count die Anzahl der Buchungsvorfälle für diesen Bereich. Über die Funktion print geben Sie diese Zahl wieder aus. begin declare @buchungenanzahl int select
@buchungenanzahl = count(*)
from buchungen natural join kurse where kurse.bereich="Server / BS" print @buchungenanzahl end 3. Im gegenteiligen Fall müssen Sie die leere Menge nicht extra ermitteln, weil dieser Block nur ausgeführt wird, wenn ohnehin keine Buchungen, also keine Ergebniszeilen, in der geprüften Abfrage vorliegen. Daher genügt es, wenn Sie mit print genau diese Information ausgeben lassen. else begin
220
SQL
M S SQ L S E R V E R
UND
T R A N S A C T SQ L
print 'Noch keine Buchungen aus dem Server-Bereich.' end go Eine letzte Variante, die wir vorstellen wollen, ist eine Abfrage, deren Ergebnis man selbst mit einer Bedingung prüfen kann. Ergebnisse, welche eine Zahl zurückliefern, eignen sich hierfür besonders. Damit sind Abfragen gemeint, die auf den Aggregatfunktionen max, min, count oder avg aufbauen. Um also z.B. zu überprüfen, ob die Saqua GmbH zu den Premiumkunden mit mehr als 50 Buchungen gehört, genügt eine Zählung der Buchungen und eine Verknüpfung zu der Tabelle unternehmen durch die Tabelle teilnehmer. Nebenstehende Abbildung zeigt die Ergebnisse: Ingesamt buchte dieses Unternehmen für vier Kurse 56 Leute und zählt damit in der Statistik „Teilnehmer pro Firma“ zu den besten Kunden von SemiTex. if (select count(buchungen.teilnnr) from
buchungen, teilnehmer, unternehmen, kurse
where buchungen.teilnnr=teilnehmer.teilnnr and unternehmen.untnr=teilnehmer.untnr and buchungen.kursnr=kurse.kursnr and untname="Saqua GmbH") > 50 begin print 'Die Saqua GmbH zählt zu den Spitzenkunden.' end else begin print 'Die Saqua GmbH ist ein normaler Kunde.' end go
10.3.2
Die if – else if – else – Anweisung
Eine Ergänzung der Verzweigungen stellt die erweiterte if-else-Verzweigung dar, die mit den Schlüsselwort else if weitere Bedingungen abfragen kann. Dabei ist es möglich, eine Vielzahl von Fällen vorzugeben, die der Reihe nach geprüft werden. Ihr Anweisungsblock
SQL
221
M S SQ L S E R V E R
UND
T R A N S A C T SQ L
wird dann je nach Ergebnis der Prüfung ausgeführt oder nicht. 1. Folgendes Programm greift das zurückliegende Beispiel noch einmal auf und erweitert es um einige Fälle. So werden Klassen von jeweils 10 Buchungseingängen gebildet. Fällt der für die Saqua GmbH geprüfte Buchungsanfall in einen dieser Bereiche, entsteht eine entsprechende Meldung. Alternativ könnte man die Firma über den insert into – Befehl in eine spezielle Tabelle bringen, die gute Kunden sammelt. Zunächst deklarieren Sie die Variable @BuchungenSaqua, die als Wert die Anzahl der gebuchten Kurse aus der Datenbank ermittelt. declare @BuchungenSaqua int select
@BuchungenSaqua = count(buchungen.teilnnr) from
buchungen, teilnehmer, unternehmen, kurse
where buchungen.teilnnr=teilnehmer.teilnnr and unternehmen.untnr=teilnehmer.untnr and buchungen.kursnr=kurse.kursnr and untname="Saqua GmbH" 1. Erstellen Sie dann die einzelnen Fälle mit Hilfe von if, else if und natürlich else. Dabei sollten Sie darauf achten, dass die Bereichsgrenzen immer auch mit „größer gleich“ oder „kleiner ich“ erfasst sind und dass diese Berücksichtigung eindeutig ist. if (@BuchungenSaqua < 10) begin print 'Mäßiger Buchungseingang.' end else if (@BuchungenSaqua >= 10 and <20 ) begin print 'Guter Buchungseingang.' end else if (@BuchungenSaqua >= 20 and <30 ) begin print 'Sehr guter Buchungseingang.' end else begin print 'Premiumkunde.' end go
222
SQL
M S SQ L S E R V E R
10.3.3
UND
T R A N S A C T SQ L
Schleifen bilden und Zähler verwenden
Schleifen ermöglichen es ebenso, in Abhängigkeit von einer Bedingung einen Anweisungsblock auszuführen zu lassen. Hier ist es allerdings möglich, über spezielle Zählkonstruktionen die Anzahl der Durchläufe zu bestimmen. declare @i int select
@i = 1
while (@i < 10) begin print @i select @i = @i + 1 end print 'Stopp!' So wie das Aufzählen von Zahlen auch in anderen Programmiersprachen nur für den Übungsteil (merken Sie sich also diese Seite, wenn Sie die Übungen machen möchten) zum Syntaxtraining spannend ist, so ist es auch für Transact SQL nicht mehr als das zu gebrauchen. Das folgende Beispiel kombiniert daher diese Standardtechnik mit einer etwas realistischeren Anwendung, die hoffentlich schon mit den wenigen Befehlen zeigt, was man mit DB-Programmierung machen kann. Folgendes Problem soll gelöst werden: Die Tabelle buchungen enthält Buchungen mit fortlaufender Buchungsnummer. Dabei fügt man Buchungen für einen Kurs geschlossen nacheinander ein. (Realistische Änderungen wie späteres Löschen oder eine nachträgliche Eintragung für einen Teilnehmer lassen wir jetzt außen vor.), sodass die entsprechende Kursnummer so oft untereinander steht, wie Teilnehmer im Kurs sitzen werden. Die Teilnehmernummer selbst wird bei neuen Teilnehmern ebenfalls fortlaufend vergeben, sodass sich für den Fall „Füge neue Teilnehmer in die Tabelle buchungen ein“ eine Situation ergibt, die man hervorragend automatisieren kann. Mit Hilfe einer Schleife soll man also automatisch eine bestimmte Anzahl von neuen Teilnehmern direkt in die Tabelle einfügen können, wobei der Benutzer lediglich Kursnummer und Teilnehmeranzahl angeben muss.
SQL
223
M S SQ L S E R V E R
UND
T R A N S A C T SQ L
1. Zunächst benötigen wir Variablen für die Elemente, die nachher automatisch in die Datenbank eingetragen werden sollen. Für die Tabelle buchungen sind es gerade Variablen für die Spalten buchungsnr, teilnnr und kursnr. Während die Kursnummer vom Benutzer vorgegeben werden muss, soll er nur noch bestimmen, wie viele Teilnehmer eingefügt werden sollen. Daher müssen die Variablen @BuchugnsNr und @TeilnehmerNr ihre Werte selbst beschaffen. Sie ermitteln sich als der um 1 erhöhte größte Wert der Tabelle teilnehmer und buchungen. Nachher trägt der Anweisungsblock die zunächst in der Variablendeklaration um 1 erhöhten und dann in der Schleife jeweils weiterhin um 1 erhöhten Buchungs- und Teilnehmernummern in die Tabelle buchungen ein. Prinzipiell ist es egal, ob Sie die erste Erhöhung gleich schon wie hier in der Variablendeklaration vornehmen oder nachher in der Schleife. Wichtig ist inhaltlich, dass die Erhöhung vor dem ersten Eintrag stattfindet. Strukturell ist bedeutsam, dass die Erhöhung gleich in der Variablendeklaration die Funktionsweise des Programms stark verdeutlicht. declare @BuchungsNr int select
@BuchungsNr = max(buchungsnr) from buchungen
select
@BuchungsNr = @BuchungsNr +1
declare @KursnNr int select
@KursNr = 50232
declare @TeilnehmerNr int select
@TeilnehmerNr = max(teilnnr) from teilnehmer
select
@TeilnehmerNr = @TeilnehmerNr +1
2. Zur Steuerung der Schleife ist es am einfachsten (man könnte alternativ auch eine Berechnung mit der Teilnehmernummer vornehmen), der Eintragevorgang wird so oft vorgenommen, wie eine einfache Zählvariable einen bestimmten Wert noch nicht erreicht hat. Dieser bestimmte Wert sollte genau der Anzahl der Teilnehmer entsprechen, welche wiederum in der Variable @TNAnzahl gespeichert wird. Deswegen erhält die Variable @i einerseits den Wert 0 zugewiesen und wird andererseits in der Schleifenbedingung auf „kleiner gleich“ geprüft, sodass das Erreichen der in der Variable @TNAnzahl gespeicherte Wert noch einen letzten Eingefügevorgang auslöst. An dieser Stelle können wir Ihnen leider nicht zeigen, wie Sie ein entsprechendes Formular z.B. in MS Access gestalten und über ein Auswahlmenü (1 bis 10 Teilnehmer) die Variable @TNAnzahl auffüllen. Es handelt sich um ein wichtiges Problem, stellt aber eine Schnittstelle zu VBA und tieferem Eindringen in den MS SQL Server dar. Als Vereinfachung geben wir diese Variable einfach vor. declare @i int select
@i = 0
declare @TNAnzahl int select
@TNAnzahl = 8
3. Schließlich folgt das eigentliche Programm, das komplett im Anweisungsblock der while – Schleife untergebracht ist. Die Prüfung vergleich für jeden Durchlauf, ob die Zählervariable, die
224
SQL
M S SQ L S E R V E R
UND
T R A N S A C T SQ L
mit jedem Durchlauf um 1 erhöht wird, kleiner oder gleich der geplanten Teilnehmeranzahl ist. Ist dies der Fall, werden zunächst die Daten in die Tabelle eingefügt. Wenn Sie – wie oben kurz erwähnt – die Erhöhung von Buchungsnummer und Teilnehmernummer nicht in der Variablendeklaration, sondern in der Schleife erledigen wollen, müssen Sie diese Erhöhung direkt vor dem Einfügen planen, damit die aktualisierten Werte übernommen werden können. Danach werden alle Variablen für den evtl. nächsten Durchlauf um 1 erhöht, wobei die aktuelle eingefügte Teilnehmernummer als Bestätigung und Information, welche Teilnehmernummern automatisch für die neuen Teilnehmer erzeugt wurden, ausgegeben wird. while (@i<=@TNAnzahl) begin insert into buchungen(@BuchungsNr, @TeilnehmerNr, @KursNr) select @BuchungsNr = @BuchungsNr + 1 print
@TeilnehmerNr
select @TeilnehmerNr = @TeilnehmerNr + 1 select @i = @i + 1 end 1. Zum Schluss erhält der Benutzer eine Bestätigung über den erfolgreichen Vorgang, wobei er nun die Teilnehmernummern zusammen mit weiteren Daten in die Tabelle teilnehmer eingeben muss. print 'Alle Buchungen erfasst! Aktualisieren Sie jetzt die Tabelle teilnehmer bzgl. der Namen.'
10.4
DB-Prozeduren in MS SQL Server
Transact SQL und der MS SQL Server bieten über die Möglichkeiten, die wir Ihnen in den zurückliegenden Abschnitten gezeigt haben, auch die Möglichkeiten, solche Programme im Rahmen von Prozeduren abzuspeichern. Sie können dann sehr einfach aufgerufen werden, sind bereits vorher übersetzt und warten nur noch auf die Eingabe gewisser Parameterwerte. Durch die bereits zuvor erledigte Übersetzung wird die Abarbeitungsgeschwindigkeit stark erhöht. Bei kleineren Programmen wie den hier gezeigten, fällt es evtl. auf, wenn man durch ein Netzwerk auf den Server zugreift. Ansonsten wächst dieser Vorteil wie immer mit dem Programmumfang bzw. wird erst dann auch spontan und nicht nur im Millisekundenbereich deutlich. Für die Gestaltung einer Prozedur existiert folgende allgemeine Syntax: CREATE PROCEDURE prozedurname [; nummer] [[(]@parameter1 datentyp [= standardwert] [OUTPUT] [{, @parameter2 datentyp [= standardwert] [OUTPUT]]} … [)]] [WITH RECOMPILE] as anweisungen Die einzelnen Bestandteile lassen sich mit den nächsten Punkten klassifizieren:
SQL
225
M S SQ L S E R V E R
UND
T R A N S A C T SQ L
¾ Jede Prozedur erhält einen eindeutigen Namen, der durch eine fakultative Nummer noch weiter charakterisiert werden kann. Über diese Lösung kann eine Familie von Prozeduren entwickelt werden, die sich nur über eine fortlaufende Nummer unterscheiden. ¾ Wie in anderen Programmiersprachen auch folgt eine Liste von Variablen bzw. Parametern, die in die Prozedur eingehen. Hier bestimmt diese auch sofort den entsprechenden Datentyp und einen evtl. Standardwert. Dies entspräche einer Vorinitialisierung. ¾ Parameter, welche einen Rückgabewert an das übergeordnete Programm liefern sollen, erhalten als weiteren Zusatz die Eigenschaft OUTPUT. ¾ Möchte man verhindern, dass die Prozedur bereits übersetzt im DBMS vorliegt, kann man die Übersetzung mit WITH RECOMPILE ausschalten. Die Übersetzung findet dann nur statt, die Prozedur aufgerufen wird.
Das Aufrufen und Erstellen von Prozeduren stellt ebenfalls ein Recht dar, das mit einem Befehl wie GRANT CREATE PROCEDURE übergeben werden kann.
Der stets beliebte DROP – Befehl eignet sich auch hier: DROP PROCEDURE prozedurname Das oben entwickelte kleine Programm wäre noch funktionstüchtiger, wenn man es einfach als Prozedur aufrufen könnte. Daher wollen wir es im nächsten Beispiel in eine Prozedur umwandeln. Die Grundstruktur des Programmablaufs bleibt unverändert. Es treten allerdings nun deutlicher die Eingangskanäle des Programms in Form der Parameter hervor. 1. Zunächst definiert man die beiden eingehenden Parameter. Dabei handelt es sich um die Kursnummer in Form der Variable @KursNr und die Teilnehmeranzahl, für die der Kurs gebucht werden soll, in Form der Variable @TNAnzahl. Beide behalten ihre Datentypen bei, haben allerdings keine Standardwerte, weil sich beide Zahlen immer ändern werden. Alternativ könnte man sich überlegen, für jeden Kurs eine eigene Prozedur zu schreiben und diese mit Hilfe der Kursnummer abzuspeichern. CREATE PROCEDURE KursBuchen (@KursNr int, @TNAnzahl int) 2. Mit dem Schlüsselwort as schließt man dann das eigentliche Programm an. Die Variablendeklaration des vorherigen Beispiels verkürzt sich lediglich um die beiden Parameter. as declare @BuchungsNr int select
@BuchungsNr = max(buchungsnr) from buchungen
select
@BuchungsNr = @BuchungsNr +1
declare @TeilnehmerNr int select
@TeilnehmerNr = max(teilnnr) from teilnehmer
select
@TeilnehmerNr = @TeilnehmerNr +1
declare @i int select
226
@i = 0
SQL
M S SQ L S E R V E R
UND
T R A N S A C T SQ L
3. Gleiches gilt für den eigentlichen Programminhalt, in dem die Eintragungen erfolgen. Die zuvor erstellten Variablen werden mit jedem Durchlauf inkrementiert, bis die im Parameter @TNAnzahl angegebene Zahl erreicht ist. Die Eintragungen erfolgen ebenfalls in der gleichen Weise, wobei im Parameter @KursNr die Spalte kursnr eingefügt wird. while (@i<=@TNAnzahl) begin insert into buchungen(@BuchungsNr, @TeilnehmerNr, @KursNr) select @BuchungsNr = @BuchungsNr + 1 print
@TeilnehmerNr
select @TeilnehmerNr = @TeilnehmerNr + 1 select @i = @i + 1 end print 'Alle Buchungen erfasst! Aktualisieren Sie jetzt die Tabelle teilnehmer bzgl. der Namen.' Der Aufruf einer Prozedur erfolgt über den Befehl execute und hat folgende allgemeine Syntax: [EXECUTE] [@rueckgabewert=] prozedurname [; nummer] {[@parameter1=] wert | [parameter1=] @variable |, @parameter2=] wert | [parameter2=] @variable [, ...]} OUTPUT [WITH RECOMPILE] Die verschiedenen Bausteine dieser Syntax greifen die folgenden Punkte kurz auf: ¾ Die einzelnen Parameter können in der erwarteten Reihenfolge nur mit ihrem Wert übergeben werden. ¾ Alternativ kann man auch den Parameternamen explizit nennen oder auch eine Variable bzw. ihren Wert direkt übergeben. ¾ Sollen wieder Daten an das übergeordnete Programm zurückgegeben werden, benötigen Sie ausdrücklich die Option OUTPUT nach dem Parameter, dessen Wert übermittelt werden soll. Im obigen Fall ergibt sich der nächste kurze Befehl: execute KursBuchen @KursNr = 50232, @TNAnzahl = 5
10.4.1 Zusammenfassung 9 Mehrere DB-Operationen werden in einer Transaktion gekapselt, damit man den Ausgangszustand vor den DB-Operationen wiederherstellen kann, wenn eine DB-Operation nicht erfolgreich durchgeführt werden konnte.
SQL
227
M S SQ L S E R V E R
UND
T R A N S A C T SQ L
9 Die verschiedenen DBS implementieren eigene SQL-Dialekte. Sie stellen völlig neuartige Entwicklungen oder starke Veränderungen von Standard-SQL dar. Transact SQL stellt dabei den Dialekt vom MS SQL Server dar, während Oracle ähnliche Programmiermöglichkeiten mit PL/SQL bietet. 9 Die Datentypen der Variablen stellen die Datentypen des DBMS dar.
10.4.2 Übungen Die folgenden Übungen beziehen sich auf Transact SQL für den MS SQL Server.
1. Deklarieren Sie in eine Variable für den Durchschnittspreis und füllen Sie diese Variable automatisch mit einer Abfrage aus der Datenbank. Welcher Datentyp eignet sich nur? Wie würde die Wertzuweisung aussehen, wenn Sie keine Abfrage verwendeten? 2. Schreiben Sie ein Programm, das für den automatisch ermittelten Tagespreis testet, ob dieser Tagespreis über oder unter 300 Euro liegt. Geben Sie jeweils eine entsprechende Mitteilung aus. Geben Sie auch zum Vergleich Abfragen an, um den Tagespreis als Zahl zu ermitteln und um die Kurse auszugeben, die über- oder unterhalb dieser Grenze liegen. 3. Entwickeln Sie ein Programm, das die Anzahl der gebuchten Kurse aus den Bereichen Grafik oder Webdesign ausgibt, wenn überhaupt Buchungen für diesen Bereich stattgefunden haben. Im gegenteiligen Fall geben Sie die Information aus, dass keine Buchungen erfolgten. 4. Geben Sie die ungeraden Zahlen 1 bis 23 aus. 5. Schreiben Sie ein Programm, das die Struktur der Tabelle buchungen so ausnutzt, dass eine komplette Buchung zurückgenommen werden kann. Dabei soll vor allen Dingen die Anzahl der falschen Buchungssätze (Anzahl der Teilnehmer) und die erste falsche Buchungsnummer in den Programmablauf einfließen. Als Beispiel nehmen Sie die Buchungen für den Kurs mit der Nr. 20239, der von 11 Leuten besucht werden sollte und mit der Buchungsnummer 23 beginnt. Entwickeln Sie die Funktionsweise evtl. anhand einer entsprechenden Abfrage dieser Tabelle. 6. Wandeln Sie das in Aufgabe 5 entwickelte Programm in eine Prozedur mit dem Namen BuchungenLoeschen. Überlegen Sie genau, welche Parameter in die Prozedur eingehen sollen. Starten Sie dann die Prozedur für den oben ausgewählten Kurs.
228
SQL
M S SQ L S E R V E R
UND
T R A N S A C T SQ L
11 Oracle und PL/SQL
SQL
229
M S SQ L S E R V E R
230
UND
T R A N S A C T SQ L
SQL
ORACLE
11 Oracle und PL/SQL
UND
P L / SQ L
Lernen Sie
Mit diesem letzten Projekt über SQL zeigen wir Ihnen grundlegende Konzepte von PL/SQL, der SQL-Erweiterung für Oracle. PL/SQL steht für „Procedural Language extension to SQL“ und ermöglicht sowohl die Realisation verschiedener SQL-StandardKonzepte, die kleine Datenbanksysteme wie MySQL nicht erlauben, als auch die Erstellung komplexer Programme.
das Grundkonzept von PL/SQL kennen Variablen und Kontrollstrukturen zu erstellen Ausgaben im Ausgabefenster zu machen
11.1 Grundüberlegungen Wenn Sie dieses Projekt bearbeiten, haben Sie sich möglicherweise das nächtliche Vergnügen gegönnt, um die Oracle-Testversion aus dem Netz zu laden und sich beim Frühstück vom Installationsvorgang erheitern lassen. Möglicherweise haben Sie auch nach einer kurzen Bekanntschaft mit dem DB-Assistenten unseren Quelltext für die einzelnen Tabellen in SQL*Plus übertragen und auf die Blitz-Schaltfläche geklickt. In diesem Sinne haben Sie Anweisungen direkt an das DBS übertragen, die dann – hoffentlich erfolgreich – ausgeführt wurden. Mit SQL*Plus steht Ihnen dabei eine Schnittstelle für die komplette Steuerung der Datenbank über SQL-Quelltext zur Verfügung. Das ist beeindruckend genug, entspricht aber auch dem Verhalten einem kleinen DBS wie z.B. MySQL. Weitaus interessanter ist daher die Fähigkeit, Programme abzuspeichern, die dann später erneut aufgerufen werden. Dies haben Sie evtl. schon im Kapitel über Transact SQL kennen gelernt, als wir die gespeicherten Prozeduren präsentiert haben. Oracle verfügt, was gespeicherte Programme anbelangt, über vier verschiedene Typen: ¾ Trigger: Trigger (engl. für den Auslöser am Fotoapparat oder den Zünder einer Bombe) stellen das Konzept für die Beantwortung der Frage dar, wie man die DB auf bestimmte Ereignisse reagieren lassen kann, die beim Einfügen, Löschen oder bei der An- und Abmeldung eines Benutzers eintreten können. Sie lassen sich also nicht wie die gleich beschriebenen Prozeduren und Funktionen per Befehl auslösen, sondern starten, sobald eine Situation eintritt, die für sie vorgegeben wurde. Daher erhalten Sie auch keine Parameterliste wie z.B. Funktionen. ¾ Pakete: Wie in den Programmiersprachen Java oder C++ lassen sich gewisse Situationen mit dem Einsatz von Modulen bewerkstelligen, die über Befehle zu Beginn eines Programms eingebunden und damit zur Laufzeit geladen und bereit gestellt werden. Sie enthalten Prozeduren
SQL
231
ORACLE
UND
P L / SQ L
und Funktionen, mit denen Sie komplexe Ausgaben lösen können. Neben den vom DBS zur Verfügung gestellten Paketen hat man auch die Möglichkeit, entsprechende Prozeduren oder Funktionen zu eigenen Modulen zusammenzustellen. Des Weiteren können innerhalb eines Moduls globale Variablen definiert werden, die bis zum Sitzungsende (Abmeldung) eines Benutzers gültig sind. ¾ gespeicherte Prozeduren: Gewöhnliche Programme, die Sie in SQL*Plus eingeben, lassen sich unter einem eigenen Namen abspeichern und bei passender Gelegenheit aufrufen und zur Ausführung bringen. Dabei legt man in der Spezifikation der Prozedur nicht nur einen eindeutigen Namen fest, sondern auch die formalen Argumente, also die eingehenden Variablen. Für die Aufnahme des eigentlichen Inhalts ist dann der Rumpf verantwortlich, in dem die Variablen wunschgemäß verarbeitet werden. Möchte man eine solche gespeicherte Prozedur später aufrufen, übergibt man in der korrekten Reihenfolge die benötigten Variablen bzw. ihre Werte. ¾ gespeicherte Funktionen: Prozeduren und Funktionen ähneln sich darin, dass sie eingehende Variablen auf eine bestimmte Art und Weise verarbeiten (Umrechnungen oder Formatierungen ausführen). Funktionen können wie die Ihnen bereits bekannten SQL-Funktionen an nahezu beliebiger Stelle in Programmen eingesetzt werden, um dort ihre standardisierte Wirkung zu entfalten. Dies unterscheidet sie von den Prozeduren. Wie die skalaren Funktionen von Standard-SQL könnte man eine Funktion, die Währungsumrechnungen ausführt, in der SELECT – Anweisung für die Spalte mit einer Währungsangabe einbauen. Der zurückgelieferte, neue Wert in einer anderen Währung kann dann für Vergleiche in der WHERE – Klausel benutzt werden. In nebenstehender Abbildung sehen Sie die einzelnen Konzepte noch einmal in einer Zusammenfassung. Innerhalb der Datenbank sind Trigger, Funktionen, Prozeduren sowie zusammenfassende Pakete gespeichert. Dabei beziehen die Trigger Programmabläufe z.B. auch aus Funktionen und Prozeduren. Während der Benutzer (hier unschwer als Elvira Hülzemann zu identifizieren) über eine Webseite oder eine andere Applikation, die sich auf die Datenbank bezieht, mit der Oberfläche Änderungen am Datenbestand vornimmt, verwendet sie vorgefertigte Programmabläufe. Um z.B. für 10 Leute automatisch einen Kurs zu buchen, könnte sie auf eine entsprechende Schaltfläche klicken, in einem Dialogfeld die Anzahl der Teilnehmer eingeben und die Anfrage absenden. Die Buchung erfolgt über in der Datenbank gespeicherte Programme, sodass sie also keineswegs irgendwelche SQL-Befehle eingeben muss. Dabei kann es allerdings geschehen, dass im Rahmen der Buchung ein Teilnehme als neu erfasst werden soll, der aber tatsächlich schon gespeichert ist. Dies würde von einem Trigger als auslösendes Ereignis abgefangen und entweder mit einer Fehlermeldung oder einer automatischen Korrektur des Befehls beantwortet. Wichtig ist hier die Unterscheidung, dass Trigger auf Ereignisse oder Zustände reagieren, die im Rahmen einer Benutzeranfrage eintreten können, während die Benutzeranfrage sich direkt auf gespeicherte Prozeduren bezieht. Es ist also nicht möglich, direkt einen Trigger aufzurufen. Die Auslagerung geeigneter DB-Programmabläufe bietet folgende drei typische Annehmlichkeiten für den DB- und Programmentwickler: ¾ Einige der Beispiele in diesem Projekt werden Sie an Situationen erinnern, die Sie evtl. auch mit einer Programmiersprache Ihrer Wahl meistern können. Dabei läuft die Behandlung eines
232
SQL
ORACLE
UND
P L / SQ L
Abfrageergebnisses und insbesondere von Schwierigkeiten mit ihm (kein Datensatz betroffen, Duplikate, Unstimmigkeiten) darauf hinaus, dass Sie die zurückgelieferte Ergebnistabelle mit geeigneten Funktionen (Zählung der Reihen, Durchlaufen der Reihen, formatierte Ausgabe) bearbeiten und hier und da für die erwähnten Schwierigkeiten geeignete Bedingungen und Anweisungen bereit halten. Bei kleineren DBS besteht keine Möglichkeit, es grundlegend anders zu handhaben. Lediglich häufig verwendbare Funktionen könnte man auslagern und so zumindest innerhalb der einzelnen Fallunterscheidungen das Ausmaß an Quelltext verringern. Bei größeren DBS wie bspw. Oracle hat man jedoch die Möglichkeit, exakt die gleichen Fallunterscheidungen bereits in der Datenbank zu treffen, Fehlermeldungen zu generieren, DBAktionen auszulösen und in jedem Fall erst nach Verarbeitung der eingegangen Abfrage das endgültige Ergebnis zurückzuliefern. Nicht alle Programmiersprachen unterstützen diese Kommunikation mit Oracle, aber mit Java ist sie z.B. formvollendet möglich. Diese Auslagerung von Prozeduren in die Datenbank hat den grundlegenden Vorteil, das man eine komplette (Web-)Anwendung u.a. in die beiden groben Bereiche DB-Anwendungen und Nicht-DBAnwendungen aufspalten kann. Konkret gesagt: alles, was sich irgendwie mit DB-Ergebnissen und ihrer Verarbeitung auf Eingabe- und Ausgabeseite beschäftigt, ist in kleinen Programmen in der Datenbank untergebracht. Wenn man dann nur noch von außen die Verbindung zur Datenbank herstellt und die entsprechenden Programme aufruft oder automatisch ablaufen lässt, kann man sehr leicht die Programmiersprache auf der anderen Seite ändern. In diesem Augenblick genügt es, wenn man für alle die DB betreffenden Programmabschnitte mit der anderen Programmiersprache lediglich die kleinen Programme noch einmal aufruft oder wie vorher die Abfrage absendet. Eine Migration wird so also wesentlich vereinfacht. ¾ Ein weiterer Vorteil durch die Einbettung geeigneter Programmstrukturen in das DBS, wenn man sich überlegt, dass dort evtl. sensible Programmstrukturen wie z.B. die Verarbeitung von Fehlern oder das Sicherheitsmanagement gespeichert werden können. So wird die Möglichkeit erschwert, an auf dem Server liegenden Quelltexte für die jeweiligen Programmabläufe zu kommen und sie einfach herunterzuladen. ¾ Zusätzlich ergibt sich eine größere Benutzerfreundlichkeit, da kein Serververkehr besteht, wenn innerhalb der Datenbank Programme ablaufen, die ansonsten nur über eine erneute (mehrfache) DB-Anfrage zu realisieren wären.
11.2 Programmstrukturen gestalten Nach diesen einführenden und konzeptuellen Überlegungen drehen sich die nächsten Skripte um die Bausteine der Programme: Variablen und Kontrollstrukturen, mit denen wir bereits einige kleinere Aufgabe lösen. Beachten Sie insbesondere den Sprachreichtum und die Vielfalt, um Variablen für ein Programm festzulegen. Die beiden Abschnitte orientieren sich dabei am grundlegenden Aufbau eines Programms (oder PL/SQL-Blocks), das aus drei Teilen besteht: ¾ DECLARE – Abschnitt für die Variablendeklaration, wobei es sehr unterschiedliche Möglichkeiten gibt, Variablen und Cursor festzulegen ¾ PROCEDURE – Abschnitt, der den eigentlichen Anweisungsblock bildet und Variablen und Cursor verarbeitet ¾ EXCEPTION – Abschnitt, der optional mehrere Male in einem Anweisungsblock definiert werden kann, um Fehler bzw. Ausnahmen abzufangen, die sonst zu einem kompletten Programmende geführt hätten.
SQL
233
ORACLE
UND
P L / SQ L
Diese Grundstruktur wird Sie nicht überraschen, da sie in anderen Programmiersprachen gleich ist. Allerdings leitet man in PL/SQL wie in älteren Sprachen die beiden Bereiche durch verschiedene Schlüsselwörter ein. Für eine bessere Lesbarkeit bei steigender Zeilenzahl, kann man insbesondere Beginn und Ende durch BEGIN und END deutlich hervorheben. Verpflichtend sind sie in jedem Fall für den Anweisungsblock. Eine typische Struktur hätte also folgende Form, wobei mit – - ein einzeiliger Kommentar eingeleitet wird. BEGIN – - optionale Kennung für Blockbeginn DECLARE – - optionale Kennung der Variablendeklaration BEGIN – - obligatorische Kennung des Anweisungsblocks EXCEPTION – - optionale Kennung der Ausnahmenbehandlung END – - obligatorischer Abschluss des Anweisungsblocks END -- obligatorischer Abschluss des gesamten Blocks
11.2.1
Deklarationen im DECLARE-Abschnitt
Die allgemeine Syntax für die Variablendeklaration hat folgende Form: variablenname datentyp [[NOT NULL] {:= | DEFAULT} wert]; Beachten Sie die nächsten Punkte zur korrekten Verwendung dieser allgemeinen Syntax: ¾ Der Variablenname wird gefolgt von seinem Datentyp, der evtl. um eine Längenangabe ergänzt werden kann. ¾ Für die optionale Wertzuweisung verwendet man typischerweise den Zuweisungsoperator := oder alternativ den Begriff DEFAULT. Muss eine Variable stets einen Wert besitzen, so kann man zusätzlich noch NOT NULL vorgeben, um diese Eigenschaft zu definieren. Es kann im Laufe eines Programms geschehen, dass eine Variable keinen Wert mehr besitzt, weil eine Zuweisung ihr keinen Wert übermittelt hat. Dies kann damit berücksichtigt werden. ¾ Ein gültiger Variablenname darf höchstens eine Länge von 30 Zeichen ohne Leerzeichen und Tabulatoren umfassen. ¾ Verwendbare Zeichen rekrutieren sich aus den Buchstaben, Zahlen, dem Unterstrich, dem Dollarzeichen und dem Rauten-Zeichen. Dabei muss der Name mit einem Buchstaben beginnen und darf natürlich kein reserviertes Wort enthalten. Neben den Variablen können Sie auch Konstanten definieren, deren Wert im Programmablauf nicht mehr änderbar und daher konstant ist. Für eine Konstante existiert folgende allgemeine Syntax, um sie zu deklarieren: konstantenname datentyp CONSTANT := wert; Mit den folgenden Schritten durchlaufen Sie die verschiedenen Möglichkeiten, Variablen zu deklarieren. Beachten Sie dabei, dass diese Quelltexte keine Programme darstellen, da sie nicht vollständig sind, und deswegen Fehlermeldungen verursachen. Sie werden im nächsten Abschnitt sehen, wie Sie Textmeldungen z.B. zur Programmkontrolle ausgeben können. Mit diesem Wissen können Sie die nächsten Halb-Programme ergänzen und ansatzweise testen. 1. Die einfache Variablendeklaration kann also auch ohne eine erste Wertzuweisung erfolgen und beschränkt sich daher nur auf einen Namen und den Datentyp. DECLARE
234
SQL
ORACLE
UND
P L / SQ L
teilnstadt char(10); teilnnachname char(30); kursnr number(10); heute date; 2. Variablen lassen sich dagegen auch sofort mit einem Wert belegen, wobei dieser der Nennung des Datentyps und dem Zuweisungsoperator folgt. Zeichenkette umschließen Sie dabei mit Hochkommata. Zahlen oder (System-)Variablen (wie hier das aktuelle Datum) verwenden Sie dagegen ohne Hochkommata. DECLARE teilnstadt char :="Willingen"; teilnnachname char :="Schmidtler"; kursnr number :=20117; heute date :=sysdate; 3. Ein Cursor (Zeiger) stellt einen weiteren Variablentyp dar, der allerdings keinen einzelnen Wert speichert, sondern dagegen auf eine Zeile in einer Ergebnisrelation verweist. Mit einem Cursor ist es möglich, eine unbestimmt große Abfragemenge zeilenweise zu durchlaufen und zu verarbeiten. Die Definition erfolgt über die allgemeine Syntax: DECLARE CURSOR cursorname IS abfrage Um also einen Zeiger für alle Kurse mit einem Preis unter 800 Euro zu definieren, verwenden Sie: DECLARE cursor Kurse_Cursor is select kursnr, titel, preis, dauer from kurse where preis<800; 4. Manchmal können sich Datentypen komplett ändern oder in ihrer Länge variieren. Dann ist es ärgerlich, wenn man die Datentypänderungen im Datenmodell auch in allen Programmen einzeln korrigieren muss, da hier eine große Fehlerquelle liegt, wenn die automatische Typkonvertierung aktiviert wird oder Teile der Daten abgeschnitten werden. Insbesondere also für Variablen, die ihre Informationen direkt aus der DB beziehen, kann man über das Attribut %type direkt den Datentyp aus der Datenbank übernehmen: DECLARE variablennamen%TYPE Um also Variablen für eine Abfrage aus der Tabelle kurse zu deklarieren, deren Datentypen exakt mit denen der Tabelle übereinstimmen sollen, setzen Sie die automatische Typableitung ein: DECLARE Kursnummer kurse.kursnr%type; Kurstitel
kurse.titel%type;
Kurspreis
kurse.preis%type;
Kursdauer
kurse.dauer%type;
SQL
235
ORACLE
UND
P L / SQ L
5. Die zuvor beschriebene Typableitung für einzeln Variablen ist ebenfalls für Cursor verwendbar. Um also der Datensatzvariable, die aus einem Zeiger abgeleitet wird, die exakt richtigen Datentypen zuzuweisen, greift man auf das Attribut %ROWTYPE mit folgender allgemeiner Syntax zurück: DECLARE CURSOR cursorname IS abfrage variablenname cursorname%ROWTYPE Für den in einem vorherigen Schritt erstellten Zeiger erstellen Sie eine Datensatzvariable, indem Sie an die Cursordefinition den Namen der Datensatzvariablen anhängen und die Datentypen durch Aufruf des Cursornamens mit %ROWTYPE verwenden. DECLARE cursor Kurse_Cursor is select kursnr, titel, preis, dauer from kurse where preis<800; Kurse_Ergebnis Kurse_Cursor%rowtype; Wenn Sie einen Ergebnismenge mit Hilfe eines Cursors durchlaufen wollen, benötigen Sie eine Schleife und eine Zählervariable, die so lange eine weitere Zeile durchsucht, bis die maximale Anzahl der betroffenen Zeilen erreicht ist. Für die Ermittlung der genauen Anzahl betroffener Datensätze gibt es das Attribut %ROWCOUNT, das diese Zahl in eine neue Variable schreibt. Die allgemeine Syntax hat dabei folgende Form: DECLARE CURSOR cursorname IS abfrage variablenname := cursorname%ROWCOUNT Um im gerade angelegten Cursor die Anzahl der betroffenen Datensätze in eine Variable wie Kurse_Betroffen abzuspeichern DECLARE cursor Kurse_Cursor is select kursnr, titel, preis, dauer from kurse where preis<800; Kurse_Betroffen := Kurse_Cursor%rowcount; Numerische Da- Zeichenketten tentypen
Zeit und Datum
Binäre Datentypen
¾ DEC
¾ CHAR
¾ DATE
¾ BLOB
¾ DECIMAL
¾ NCHAR
¾ INTERVAL DAY TO SEC¾ BFILE
¾ FLOAT
¾ VARCHAR2 and VARCHAR
¾ INTERVAL YEAR TO MO¾ RAW
¾ INTEGER
¾ NVARCHAR2
¾ TIMESTAMP
¾ SMALLINT
¾ CLOB
¾ NUMBER
¾ NCLOB
¾ LONG RAW
¾ LONG
236
SQL
ORACLE
UND
P L / SQ L
Tab.1: Datentypen in Oracle
11.2.2
Ausgaben im Programmablauf
Im Programmablauf können Sie Ausgaben im Ausgabefenster ausgeben. Dies ist gerade für die Programmkontrolle oder Fehlersuche (Was ist zu welchem Zeitpunkt in welcher Variable gespeichert?) wichtig. Evtl. müssen Sie die Ausgabe zunächst mit set serveroutput on aktivieren. Verantwortlich für Ausgaben ist das Paket dbms_output, die verschiedene Prozeduren für die Speicherung von Nachrichten in den Textpuffer bereit stellt. Dabei werden die Namen der einzelnen Prozeduren einfach an den Paketnamen angehängt. 1. Die Ausgaben können nur im Ausgabeblock ausgeführt werden, sodass Sie die einzelnen Ausgaben komplett mit BEGIN und END umschließen müssen. Folgende Varianten existieren für die Speicherung in den Textpuffer: ¾ put_line : speichert eine komplette neue Zeile ab ¾ put : schreibt in die vorhandene Zeile, schließt sie aber nicht ab ¾ new_line : erzeugt eine neue, leere Zeile bzw. schließt eine Zeile ab Den Unterschied zwischen put_line und put sehen Sie an den Ausgaben von Hallo Welt und Hallo Mond im Verborgenen. Während Hallo Welt komplett in die erste, neue Zeile geschrieben wird, wird der Gruß für den Mond in zwei Hälfte geteilt, wobei die erste Hälfte die Zeile nicht abschließt. Dies ist insbesondere für Ausgaben sinnvoll, die räumlich im Programm auseinander liegen, aber aus inhaltlichen Gründen in eine Zeile geschrieben werden sollen. set serveroutput on BEGIN dbms_output.put_line('Hallo Welt'); dbms_output.put('Hallo Mond '); dbms_output.put_line('im Verborgenen'); dbms_output.new_line; dbms_output.put_line('Hallo Sonne'); END; 2. Gerade für die Ausgabe von Variablenwerten, die zusätzlich mit anderen Texten verbunden sind, müssen Sie beachten, dass ¾ die Variable ohne Hochkommata aufgerufen und daher ihr Wert und nicht der Variablenname als Wort ausgegeben wird, ¾ die Verknüpfung von zwei Variablen oder über die beiden senkrechten Striche || erfolgt und ¾ Leerzeichen nur innerhalb einer Textausgabe berücksichtigt werden können. In folgendem kurzen Beispielprogramm deklarieren Sie zunächst die Variablen, in die nachher Werte aus einer Abfrage gespeichert werden. Diese Werte geben Sie dann in drei einzelnen
SQL
237
ORACLE
UND
P L / SQ L
Zeilen zusammen mit weiteren Informationen wie einem Titel oder einer Maßeinheit sowie passenden Leerzeichen aus. DECLARE Kurstitel kurse.titel%type; Preis
kurse.preis%type;
Dauer
kurse.dauer%type;
BEGIN SELECT titel, preis, dauer INTO Kurstitel, Preis, Dauer FROM
kurse
WHERE
kursnr=20127;
dbms_output.put_line('Kurs:' || Kurstitel); dbms_output.put_line('Preis: ' || Preis || ' Euro'); dbms_output.put_line(Dauer || ' Tage'); END;
11.2.3
Weitere Formen der Wertzuweisungen
Wie Sie einer Variablen direkt bei der Deklaration einen Wert zuweisen, haben Sie im ersten Abschnitt in allen Varianten gesehen. Zwei weitere Möglichkeiten existieren für eine Zuweisung im Anweisungsblock, wobei Sie gerade schon gesehen haben, wie man Abfragewerte in einer Variable speichert. 1. Um Werte aus einer Abfrage direkt in eine Variable zu speichern, müssen Sie zunächst die benötigte Variable definieren, einen geeigneten Datentyp auswählen, der mit der abzurufenden Information übereinstimmt oder ein gewünschtes Format besitzt, und dann die Variable direkt nach der SELECT – Anweisung mit dem Schlüsselwort INTO aufrufen. Dabei beachten Sie folgende allgemeine Syntax SELECT spalte1 [, spalte2 [, FUNCTION(spalte3)]] INTO
variable1 [, variable2 [, variable3]]
In diesem Beispiel soll die Durchschnittsdauer der Kurse in eine eigene Variable gespeichert und später weiterverarbeitet und ausgegeben werden. DECLARE Durchschnittsdauer number; BEGIN SELECT AVG(dauer) INTO
Durchschnittsdauer
FROM
kurse;
dbms_output.put_line ('Durchschnitt: ' || Durchschnittsdauer); END;
238
SQL
ORACLE
UND
P L / SQ L
2. Eine weitere Möglichkeit dürfte Ihnen bereits aus anderen Programmiersprachen geläufig sein: Verwendung von Werten aus Variablen für die Zuweisung eines Werts einer weiteren Variablen. Neben der einfachen Wertübergabe kann man zusätzlich Werte addieren, subtrahieren, multiplizieren oder dividieren durch die Operatoren +, -, * und /. In folgendem Beispiel ruft man zunächst einzeln die Werte für die durchschnittliche Dauer und den durchschnittlichen Preis aus der Kurstabelle ab, gibt sie jeweils aus und berechnet dann auf runde EuroBeträge genau den durchschnittlichen Tagespreis, indem die Variablen Durchschnittspreis und Durchschnittsdauer mit einer Division verknüpft werden. DECLARE Durchschnittsdauer number; Durchschnittspreis number; Tagespreis decimal; BEGIN SELECT AVG(dauer) INTO
Durchschnittsdauer
FROM kurse; dbms_output.put_line('Durchschnittsdauer: '|| Durchschnittsdauer); SELECT AVG(preis) INTO
Durchschnittspreis
FROM kurse; dbms_output.put_line('Durchschnittspreis: '|| Durchschnittspreis); Tagespreis := Durchschnittspreis / Durchschnittsdauer; dbms_output.put_line ('Tagespreis: '|| Tagespreis); END;
11.2.4
Verzweigungen und Ausnahmen erstellen
Auch in PL/SQL existieren natürlich verschiedene Möglichkeiten, auf eine oder mehrere Bedingungen zu reagieren und dementsprechend verschiedene Fälle zu konstruieren. Die folgende Tabelle zeigt die drei typischen Situationen, wobei es natürlich in der dritten allgemeinen Syntax beliebig viele ELSIF – Anweisungen geben könnte. Je nachdem, welche Bedingung erfüllt ist, wird nur der Anweisungsblock dieser erfüllten Bedingung ausgeführt. Einen Standardfall geben Sie über ELSE vor, der daher keine Bedingung erhalten kann. eine Bedingung
zwei Bedingungen
mehrere Bedingungen
IF Bedingung
IF Bedingung
IF Bedingung1
THEN Anweisungen; END IF;
SQL
THEN Anweisungen1; ELSE Anweisungen2;
THEN Anweisungen1; ELSIF Bedingung2
239
ORACLE
UND
P L / SQ L
END IF;
THEN Anweisungen2; ELSE Anweisungen3; END IF;
Tab.1: Verzweigungsmöglichkeiten 1. Im folgenden Beispiel speichert man die Kursbuchungen von Herrn Schmidtler in eine Variable Buchungen_Anzahl. Diese wird dann in drei Bedingungen darauf überprüft, zu welcher Teilnehmer-Kategorie er zu zählen ist. Die einzelnen Anweisungsblöcke bestehen dabei lediglich aus einfachen Ausgaben der Teilnehmer-Kategorie. DECLARE Buchungen_Anzahl integer; BEGIN select count(buchungsnr) into
Buchungen_Anzahl
from
buchungen natural join teilnehmer
where
teilnnachname='Schmidtler';
IF Buchungen_Anzahl < 2 THEN dbms_output.put_line('mittelmäßiger TN'); ELSIF Buchungen_Anzahl >= 2 AND Buchungen_Anzahl <5 THEN dbms_output.put_line('guter TN'); ELSE dbms_output.put_line('sehr guter TN'); END IF; END; 2. Eine weitere Möglichkeit, Fallunterscheidungen mit genau übereinstimmenden Fällen zu konstruieren, die sich leichter lesen lassen als mehrere ELSIF – Anweisungen in Folge, stellt die CASE – Konstruktion dar. Dabei wird die gesamte Falluntersuchung folgendermaßen gebildet: CASE fallname { WHEN bedingung1 THEN {anweisungen1;} ... },... [ ELSE {anweisungen_x}... ] END CASE; Folgende Punkte gilt es zu beachten: ¾ Das Schlüsselwort CASE umschließt die gesamte Konstruktion. ¾ Die einzelnen Bedingungen leitet WHEN ein, wobei man für jeden Fall entsprechende Anweisungen vorgeben muss. ¾ Alternativ kann ein Standardfall über ELSE vorgegeben werden. Das nächste Beispiel greift das vorherige noch einmal auf und wandelt es mit einer StatusBetrachtung so ab, dass bis zu drei Kursbesuche einem speziellen Status entsprechen, und mehr als drei Kursbesuche (Standardfall) einen spezieller Gold-Status darstellen. DECLARE
240
SQL
ORACLE
UND
P L / SQ L
Status integer; BEGIN select count(buchungsnr) into
Status
from
buchungen natural join teilnehmer
where
teilnnachname='Schmidtler';
CASE Status WHEN '1' THEN dbms_output.put_line('TN-Status 1'); WHEN '2' THEN dbms_output.put_line('TN-Status 2'); WHEN '3' THEN dbms_output.put_line('TN-Status 3'); ELSE dbms_output.put_line('TN Status Gold'); END CASE; END; 3. Ein besonders wichtige Art von Fallunterscheidungen stellen Ausnahmen dar, also unerwünschte Ereignisse im Programmablauf, auf die man mit einer selbst vorgegebenen Aktion reagieren kann. Dies verhindert bspw. die automatische Ausführung einer AusnahmeBehandlung durch eine DBS-Fehlermeldung. Ein sinnvoller Einsatz setzt lediglich voraus, dass man typische oder systematisch auftretende Problemfälle bei der Programmplanung erkennt und dann durch eine Ausnahme berücksichtigt. In allgemeiner Form kann man im Laufe eines Anweisungsblocks auch mehrere Fälle - wie ausführlich bei den Verzweigungen gezeigt - berücksichtigen. Ausnahmen behandeln
Ausnahmen auslösen
EXCEPTION
DECLARE
WHEN ausnahmebedingung1
ausnahmenname EXCEPTION;
THEN anweisungen1; | [WHEN ausnahmebedingung2
BEGIN IF bedingung THEN
THEN anweisungen2; ] | [WHEN OTHERS THEN anweisungen3;]
RAISE ausnahmenname; END IF; EXCEPTION WHEN ausnahmenname THEN anweisungen; END;
Tab.2: Ausnahmen behandeln und auslösen Bei Berechnungen kann es geschehen, dass durch dividiert wird, was nicht definiert ist. Für diesen Fall existiert eine spezielle, eingebaute Fehlermeldung, die man allerdings über die Funktion zero_divide auch vermeiden und durch eine eigene Fehlerbehandlung ersetzen kann. Im folgenden Beispiel berechnet man der Reihe nach die Werte –10/3, -10/2, -10/1 und 10/0, was schließlich die geänderte Ausgabe hervorruft. DECLARE
SQL
241
ORACLE
x
number := -3;
y
number := 10;
z
number;
UND
P L / SQ L
BEGIN WHILE x < 3 LOOP z := y/x; EXCEPTION WHEN zero_divide THEN dbms_output.put_line('streng verboten'); dbms_output.put_line('aktueller Wert: ' || x); x := x + 1; END LOOP; END;
11.2.5
Schleifen konstruieren
Mit Schleifen lassen sich Aktionen beliebig oft wiederholen. Ihre Terminierung kann entweder mit dem Erreichen eines vorgegebenen Zähler-Wertes oder dem Erreichen eines bestimmten Zustandes zusammenfallen. Insbesondere bei der Behandlung einer Ergebnismenge, die Zeile für Zeile mit dem gleichen Verarbeitungsmodus behandelt werden soll, wird eine Endlos-Schleife eingesetzt, deren Bearbeitung genau dann stoppt, wenn das Ende der Ergebnismenge erreicht ist. Wir werden Ihnen im folgenden eine Schleifenkonstruktion vorführen, die für eine bestimmte Anzahl neuer Teilnehmer Buchungen vornimmt. Sie weist ihnen eine Teilnehmernummer zu und trägt sie in die Tabelle buchungen ein. Das Schlüsselwort für Schleifen ist stets LOOP. 1. Zunächst erstellen Sie die einzelnen Variablen, wobei lediglich die Kursnummer, die Anzahl der neuen Teilnehmer und die Zählervariable für die spätere Schleife initialisiert werden. DECLARE Max_Buchungsnr
integer;
Max_Teilnnr
integer;
Neue_Teilnehmer integer := 5; Kursnr
integer := 50232;
i
integer := 0;
2. Dann rufen Sie die aktuellen Höchststände für die Buchungsnummer und die Teilnehmernummer aus der Tabelle buchungen ab und speichern sie in die einzelnen Variablen. Berechnen Sie hiernach jeweils die folgende, neue Buchungs- und Teilnehmernummer. Beide stellen für den gesamten Buchungsvorgang die jeweils ersten Zahlen dar. BEGIN -- lade höchste Buchungsnr select max(buchungsnr) into
242
Max_Buchungsnr
SQL
ORACLE
from
UND
P L / SQ L
buchungen;
dbms_output.put_line('Derzeitige Max Buchungsnr.: ' || Max_Buchungsnr); -- berechne neue Start-Buchungsnr Max_Buchungsnr := Max_Buchungsnr +1; dbms_output.put_line('Start Buchungsnr.: ' || Max_Buchungsnr); -- lade höchste Teilnehmernr select max(teilnnr) into
Max_Teilnnr
from
buchungen;
dbms_output.put_line('Derzeitige Max Teilnnr.: ' || Max_Teilnnr); -- berechne neue Start-Teilnehmernr Max_Teilnnr := Max_Teilnnr + 1; dbms_output.put_line('Start Teilnnr.: ' || Max_Teilnnr); 3. Zum Schluss führen Sie den gesamten Buchungsvorgang mit einer einzigen Schleife aus. Die Anzahl der durchzuführenden Buchungssätze ist in der Zählervariable gespeichert, die mit jedem Schleifendurchgang um 1 erhöht wird. Dies gilt ebenso für die weiteren Buchungs- und Teilnehmernummern. Zur Kontrolle geben Sie vor der Inkrementation der einzelnen Variablen noch den gesamten Buchungssatz aus. -- führe Buchungen durch WHILE i < Neue_Teilnehmer LOOP insert into buchungen values (Max_Buchungsnr, Max_Teilnnr, Kursnr); dbms_output.put_line('OK: ' || Max_Buchungsnr || ', ' || Max_Teilnnr || ', ' || Kursnr); Max_Teilnnr := Max_Teilnnr + 1; Max_Buchungsnr := Max_Buchungsnr +1; i := i+1; END LOOP; END;
11.3 Cursor-Behandlung Eine Abfrage wird so mit einem Cursor durchsucht, dass man auf die einzelnen Ergebniszeilen der Reihe nach zugreifen kann. Dabei wird dieser sequentielle Zugriff durch die Schleifenstruktur bestimmt. Als Grundkonzept existieren vier unterschiedliche Befehle, die Sie stets bei der CursorBehandlung einsetzen müssen:
SQL
243
ORACLE
UND
P L / SQ L
¾ DECLARE : deklariert einen Cursor mit seinem Namen und der zugehörigen Abfrage ¾ OPEN : öffnet den Cursor für seine Bearbeitung ¾ FETCH : spricht die einzelne Datenzeile an, auf die der Cursor aktuell zeigt ¾ CLOSE : schließt den Cursor nach Beendigung des Anweisungsblocks Für die Konstruktion der Schleifenbedingung stehen verschiedene Statusvariablen zur Verfügung, deren Werte man bei der Arbeit mit dem Cursor abrufen kann: Statusvariable
Beschreibung
%found
liefert den Wert TRUE zurück, wenn der zuvor erfolgte fetch – Vorgang einen Datensatz lieferte
%isopen
liefert den Wert TRUE zurück, wenn der Cursor erfolgreich geöffnet ist
%notfound
liefert den Wert TRUE zurück, wenn der zuvor erfolgte fetch – Versuch nicht erfolgreich war
%rowcount
liefert die Zahl der durch den Cursor bearbeiteten Datensätze zurück
Tab.3: Statusvariablen bei der CursorBehandlung 1. Zunächst deklarieren Sie verschiedene Variablen und den Cursor, der Kursinformationen aus der Tabelle Kurse abruft, die im Grafik-Bereich vorhanden sind. DECLARE Kursnummer kurse.kursnr%type; Kurstitel
kurse.titel%type;
Kurspreis
kurse.preis%type;
cursor Kurse_Cursor is select kursnr, titel, preis, dauer from kurse where bereich='Grafik'; 2. Dann durchlaufen Sie mit Hilfe einer einfachen Endlos-Schleife die gesamte gefundene Datenmenge, wobei Sie mit Hilfe des Statusvariable %notfound und dem Befehl EXIT die Schleife abbrechen, sobald das Ende der Datensatzmenge erreicht ist. BEGIN open Kurse_Cursor; LOOP fetch Kurse_Cursor into Kursnummer, Kurstitel, Kurspreis; dbms_output.put_line(Kursnummer || Kurstitel || Kurspreis); EXIT WHEN Kurse_Cursor%notfound; END LOOP; close Kurse_Cursor; END;
244
SQL
ORACLE
UND
P L / SQ L
Eine Vereinfachung hält die FOR – Schleife bereit, mit der man sich das explizite Öffnen, Schließen und Ansprechen des einzelnen Datensatzes sparen kann. Sie stellt automatisch eine Zählervariable zur Verfügung und zählt solange um 1 nach oben, bis der letzte Datensatz erreicht ist. Diese Konstruktion eignet sich also besonders, um eine komplette Ergebnismenge zu durchlaufen. BEGIN FOR Kursnummer, Kurstitel, Kurspreis, Kursdauer IN Kurse_Cursor LOOP dbms_output.put_line(Kursnummer || Kurstitel || Kurspreis); END LOOP; END;
11.3.1 Zusammenfassung 9 PL/SQL unterscheidet drei Arten von Programmierkonzepten: Prozeduren (eigenständige Programme), Funktionen (Programme, die z.B. einen Rückgabewert erzeugen und Hilfsaufgaben übernehmen) und Trigger (Programme, die auf DB-Zustände und Ereignisse bspw. bei Transaktionen reagieren). Pakete fassen Funktionen und Prozeduren zusammen. 9 Programmstrukturen lassen sich in drei Bereiche aufteilen: den Deklarationsabschnitt, den eigentlichen Anweisungsblock und evtl. eingearbeitete Ausnahmebehandlungsblöcke. 9 Mit einem Cursor kann die Ergebnismenge einer Abfrage durchlaufen und verarbeitet werden.
11.3.2 Übungen 1. Definieren Sie die Variablen Seminarort mit dem Wert Duisburg, Seminarzentrum mit dem Wert Alter Bahnhof sowie Kursnummer und Datum. 2. Erstellen Sie einen Cursor namens Termine_Ddorf für alle Termine, die in Düsseldorf stattfinden. 3. Entwickeln Sie eine Ausgabe , die überprüft, ob zufällig genau 25, 50, 25 oder 100 Termine in Dortmund vorliegen. Geben Sie entsprechende Statusmeldungen aus. 4. Zählen Sie die Anzahl der Kursnehmen, die die Draht Gründling GmbH (untnr=1) gebucht hat und geben Sie sie aus.
SQL
245
ORACLE
246
UND
P L / SQ L
SQL
ORACLE
UND
P L / SQ L
12 Lösungen
SQL
247
LÖSUNGEN
248
SQL
LÖSUNGEN
12 Lösungen Wir haben uns sehr bemüht, Aufgaben zu finden, die einerseits den gelernten Stoff pro Projekt gut widerspiegeln und andererseits in den Lösungshinweisen leicht darüber hinausgehende Informationen zu geben. Nehmen Sie Aufgaben und Lösungen also auch als weitere Beispiele und nicht nur als Anhängsel an den restlichen Text wahr.
Modul 1 - Grundlagen relationaler Datenbanken 1. Das DB-Schema finden Sie in nebenstehender Abbildung. Wie bereits bei der Herleitung der Normalenformen besprochen, dient die Tabelle ZEITEN dazu, die Verbindung zwischen den Mitarbeitern und den Projekten einzurichten. In einem ERDiagramm hätte man dazu eine n:mBeziehung namens „nimmt teil“ verwendet. Typischerweise wird eine solche Beziehung als Tabelle gestaltet. 2. Das DB-Schema finden Sie in nebenstehender Abbildung. 3. Über die Objektanalyse findet man zunächst die Einheiten Unternehmen, Teilnehmer und Kurs mit ihren jeweiligen Attributen, die teilweise bereits genannt waren. Über die Tätigkeitsanalyse dagegen findet man buchen als Tätigkeit der Teilnehmer. Im ER-Diagramm wäre hier eine „nimmt teil“- oder „bucht“-Beziehung gewesen, die über eine Beziehungstabelle aufgelöst wird. 4. Ein weiteres menschliches Objekt könnte der Dozent mit den allgemeinen Kontaktund Adressattributen sowie Preisen für verschiedene Kurse bzw. Themen sein. Sollte das Unternehmen seine Kurse in verschiedenen Gebieten anbieten, könnte man noch eine entsprechende Tabelle mit Kursorten anlegen. 5. Die Dozenten werden eine entsprechende Nummer erhalten, sodass ihre Daten nur einmal in der Tabelle DOZENTEN erfasst werden müssen. Dieser Primärschlüssel wird als Fremdschlüssel dann z.B. in die Tabelle KURSE eingetragen. Hier liegt die Gefahr einer DB-Anomalie, da bis jetzt jeder Kurs nur einen Datensatz belegt. In dem Augenblick, wo mehrere Dozenten den gleichen Kurs anbieten, was sehr wahrscheinlich ist, müssten im vorliegenden Datenmodell
SQL
249
LÖSUNGEN
sämtliche Kursinformationen wiederholt werden. Um diese Redundanzen zu vermeiden, könnte man die Beziehung zwischen Dozenten und Kursen über eine Beziehungstabelle ANGEBOTE gestalten. Hier stünden dann nur noch drei Spalten für DozNr, Kursnr und Preis. 6. Um offene Kurse mit Terminen anzubieten, muss lediglich eine Tabelle TERMINE mit TerminNr, KursNr, Beginn, Ende und evtl. anderem Preis eingerichtet werden. Soweit die Dozenten dafür schon feststehen, könnte man auch eine Spalte DozNr anlegen. 7. Wie gerade für den Dozenten sprachlich auch knapp zusammengefasst, befinden sich in allen Tabellen die typischen Teile der zusammengesetzten Datentypen Adresse und Kontakt. Insbesondere in der Tabelle UNTERNEHMEN findet man zum einen Informationen über das Unternehmen und über den Ansprechpartner in atomisierter Form. 8. Das Datenbankschema richtet sich nach den Gegebenheiten im Netz. Da der Webserver, der die Programme für die dynamischen Seiten verwaltet, durch die Einschränkungen des HTTP-Protokolls (bricht nach Übertragung der Seite die Verbindung ab), gezwungen ist, sich selbst den Besucher zu merken und z.B. den Warenkorb zuzuweisen, benötigt man explizit eine Tabelle BESUCHER. Dass statistische Auswertungen mit ihr möglich sind, ist ein interessanter Nebeneffekt. Insbesondere die beim Bestellvorgang zu speichernde Kundennummer in der Tabelle BESUCHER lässt Schlüsse zu, welche Besuchergruppe (nach Geschlecht, Alter, Wohnort, Bestellmenge usw.) letztendlich zu Kunden werden. So kann man z.B. versuchen, Besucher mit besonders geringer Wahrscheinlichkeit, Kunde zu werden, anders anzusprechen und die Seite dahin gehend optimieren.
Modul 2 - Datenbank und Tabellen anlegen und ändern 1. Diese Tabellen benötigen bei einer Neu-Anlage keine Überprüfungen auf Existenz.
Die Tabellendefinitionen finden Sie in der Datei vollkornmuehle1_ mysql.sql.
250
SQL
LÖSUNGEN
2. Der Datentyp text eignet sich besonders für die Spalten vorkenntnisse und themen, weil hier längerer Text eingetragen werden soll. Beachten Sie insbesondere die zusätzliche Bedingung auto_increment für die Verwendung in MySQL, um neuen Einträgen automatisch eine um eins größere Primärschlüsselnummer zuzuweisen.
Die Tabellendefinitionen finden Sie in der Datei semitext1_mysql.sql
3. Innerhalb der DEFAULT-Anweisung müssen Zahlen eingetragen werden, die durch das Standardtrennzeichen (Minuszeichen) anhand der Syntax jjjj-mm-tt getrennt werden. DROP TABLE IF EXISTS termine; CREATE TABLE termine ( terminnr int(10) NOT NULL, kursnr varchar(20) NOT NULL default '', Beginn date NOT NULL default '0000-00-00', Ende date NOT NULL default '0000-00-00', Ort varchar(30) NOT NULL default '', PRIMARY KEY
(Terminnr)
); 4. Folgende Befehle waren in Druckreihenfolge nötig, um die Veränderungen durchzuführen: ALTER TABLE `Songs`.`datentraeger` CHANGE `datnr` `datnr` INT(5) DEFAULT '0' NOT NULL, CHANGE `datart` `dattyp` VARCHAR(20) NOT NULL, CHANGE `datunterart` `datsubtyp` VARCHAR(20) DEFAULT NULL, DROP `teil`, ADD `datlaenge` TIME, RENAME `materialien`;
Die Tabellendefinitionen finden Sie in der Datei songs5.txt.
5. Der Wertebereich für den Datenträgeruntertyp lautet: CREATE DOMAIN datentraegeruntertyp varchar(20) default ´maxi´, CHECK ( VALUE IN (´maxi´, ´single´, ´LP´, ´5-inch´, ´3-inch´)); 6. Der Wertebereich für den Datenträgertyp lautet: CREATE DOMAIN datentraegertyp varchar(20) default ´CD´, CHECK ( VALUE IN (´vinyl´, ´CD´, ´DVD´, ´Video´,
SQL
251
LÖSUNGEN
´Cassette´, ´MiniDisc´, ´LaserDisc´, ´CD-i´, ´VideoCD´); 7. Die Tabellendefinition, die beide Domänen verwendet, lautet: DROP TABLE IF EXISTS datentraeger; CREATE TABLE datentraeger ( datnr int(4) NOT NULL default '0', veroeffnr int(4) NOT NULL default '0', dattitel varchar(150) NOT NULL default '', datart datentraegertyp, datunterart datentraegeruntertyp, verlagnr varchar(30) NOT NULL default '', packnr varchar(30) default NULL, teil varchar(4) NOT NULL default '', PRIMARY KEY
(datnr)
); 8. Die kompletten Tabellendefinitionen lauten: DROP TABLE IF EXISTS datentraeger; CREATE TABLE datentraeger ( datnr int(4) NOT NULL default '0', veroeffnr int(4) NOT NULL default '0', dattitel varchar(150) NOT NULL default '', datart datentraegertyp, datunterart datentraegeruntertyp, verlagnr varchar(30) NOT NULL default '', packnr varchar(30) default NULL, teil varchar(4) NOT NULL default '', PRIMARY KEY
(datnr),
FOREIGN KEY
(veroeffnr) REFERENCES veroeffentlichungen
); DROP TABLE IF EXISTS aufnahmen; CREATE TABLE aufnahmen ( aufnr int(4) NOT NULL default '0', songnr int(4) NOT NULL default '0', aufntitel varchar(150) NOT NULL default '', aufntyp aufnahmetyp, duettpartner varchar(20) default NULL,
252
SQL
LÖSUNGEN
aufndatum year(4) CHECK (aufndatum > 1939), PRIMARY KEY
(aufnr),
FOREIGN KEY
(songnr) REFERENCES songs)
); 9. In diesem Fall müssen Sie lediglich den Tabellennamen aufrufen. COMMENT ON TABLE datentraeger IS "ein Datenträger ist ein Mittel zur Aufnahmenkonservierung, er verwaltet Aufnahmen mit Hilfe von Veröffentlichungen" 10.Für die Kommentierung einer Spalte verwenden Sie zusätzlich auch den Tabellennamen. COMMENT ON COLUMN songs.autoren IS "ausschließliche Verwendung von Nachnamen"
Modul 3 - Daten einfügen und ändern 1. Nach Aufrufen des Tabellennamens werden die Daten in der richtigen Spaltenreihenfolge genannt, wobei die einzelnen Datensätze durch Kommata und der gesamte Befehl durch ein Semikolon abgeschlossen werden. INSERT INTO unternehmen VALUES (4, 'TONAlicht GbR', 'Niederstrahl', '86', '0358-48269-0', 'Messebau', 84569, 'Willingen', '
[email protected]', 'Konrad', 'Torweger', '0358-48269-23', 'Geschäftsleiter'), (5, 'Druckerei Setzling GmbH', 'Alte Baumgruppe', '12', '0358-87232-0', 'Druckerei', 84569, 'Willingen', '
[email protected]', 'Anton', 'Becker', '0358-87232-9', 'Innerbetriebliche Weiterbildung'), (6, 'Stadtwerke Willingen', 'Industriestraße', '1', '0358-96269-0', 'Stadt', 84569, 'Willingen', '
[email protected]', 'Gerda', 'Wenisch', '0358-96269-3', 'Innerbetriebliche Weiterbildung'); 2. Es werden lediglich die Spaltennamen aufgerufen, in die auch Daten eingefügt werden sollen. Die Reihenfolge dieser Spaltenliste muss mit der Reihenfolge in der Werteliste übereinstimmen. INSERT INTO unternehmen (untnr, untname, untstraße, unthausnr, unttelefon, untplz, untstadt, untbranche) VALUES (4, 'TONAlicht GbR', 'Niederstrahl', '86', '0358-48269-0', 'Messebau', 84569, 'Willingen'); 3. Es ist das gleiche Schema wie auch sonst anzuwenden. Normalerweise stellen allerdings die verschiedenen DBS-Hilfswerkzeuge zur Verfügung, um Textdateien über spezielle Werte leicht zu erfassen. Dabei ist immer zu berücksichtigen, welche Trennzeichen für die einzelnen Da-
SQL
253
LÖSUNGEN
tensätze zwischen den Spalten und an den Zeilenenden verwendet werden, damit das DBS die ankommenden Texte entsprechend aufteilen kann. INSERT INTO teilnehmer VALUES (1, 1, 'Heinrich', 'Schmidtler', 'Hans-Strenkel-Weg', '11', 84569, 'Willingen', '0356-86259'), (2, 1, 'Ralf', 'Ahrens', 'Krogbuschweg', '28', 84570, 'Wedelingen', '0357-62847'), (3, 1, 'Rainer', 'Ahlgrin', 'Landstraße', '6', 84571, 'Sollbach', '035852688'), (4, 1, 'Roswita', 'Bikelund', 'Schwarzenbecker Weg', '27', 84569, 'Willingen', '0356-54317'), (5, 1, 'Hans-Josef', 'Doberens', 'Ellerbreite', '2', 84570, 'Wedelingen', '0357-52186'), (6, 1, 'Martin', 'Gendner', 'Humperdinckstraße', '30', 84571, 'Sollbach', '0356-86260'); 4. Man benötigt den Standardbefehl, mit dem Tabellen geleert, aber nicht vollständig gelöscht werden. DELETE FROM termine; 5. In einer angeschlossenen WHERE – Klausel wird die Bedingung über die Spalte stadt gebildet. DELETE FROM teilnehmer WHERE stadt = 'Sollbach'; 6. Gleiches gilt für die Spalte preis der Tabelle kurse. DELETE FROM kurse WHERE preis < 250; 7. Innerhalb der WHERE – Klausel befindet sich eine SELECT – Anweisung, die zunächst überprüft, welche Kurse überhaupt laut Terminplan in Düsseldorf stattfinden. Diese sollen dann in der Tabelle kurse gelöscht werden. Dabei wird die Kursnummer als Bindeglied verwendet. DELETE FROM kurse WHERE Kursnr IN (SELECT Kursnr FROM termine WHERE Ort='Düsseldorf'); 8. Da diese Änderung alle Kurse betrifft, ist keine WHERE – Klausel notwendig. UPDATE termine SET Ort='Düsseldorf' 9. Da diese Änderungen ebenfalls für alle Datensätze gelten, müssen nur die beiden Spalten aufgerufen und die Änderungen vorgegeben werden. Die Spaltennamen wirken dabei nicht als Wörter, sondern repräsentieren den Datentyp, sodass Berechnungen möglich werden. UPDATE kurse SET Preis = Preis*1.30, Dauer= Dauer+1; 10.Die einschränkende Bedingung muss hier in der WHERE – Klausel vorgegeben werden.
254
SQL
LÖSUNGEN
UPDATE termine SET Ort='Oberhausen' WHERE kursnr = 30129; 11.Um eine unscharfe Bedingung vorgeben zu können, kann u.a. das bereits bekannte Prozentzeichen in Redezeichen Verwendung finden. Es folgt der ersten Ziffer, die eine Zwei sein soll. UPDATE termine SET Ort='Gelsenkirchen' WHERE kursnr LIKE "2%" 12.Für diese Änderung ist es zunächst notwendig herauszufinden, welche Kurse überhaupt laut der Tabelle termine in Düsseldorf stattfinden. Kurse mit diesen Kursnummern sollen dann einen um 30 Euro höheren Preis erhalten, was wie oben über die Nennung des Spaltennamens bestimmt wird. UPDATE kurse SET Preis = Preis+30 WHERE Kursnr IN (SELECT Kursnr FROM termine WHERE Ort = 'Düsseldorf');
Modul 4 - Grundstrukturen einfacher Abfragen 1. Die acht Basisoperationen lassen sich wie folgt einfach beschreiben. Die Selektion wählt anhand eines Vergleichskriteriums komplette Datensätze aus einer Relation aus. Die Projektion dagegen wählt Spalten anhand des Vergleichskriteriums aus. Die Vereinigungsmenge ist die Ergebnisrelation, die alle Datensätze zweier gleichartig strukturierter Relationen aufnimmt. Demgegenüber nimmt die Differenzmenge die Datensätze auf, die Teil der einen, aber nicht Teil der anderen Tabelle sind. Die Operationsreihenfolge ist nicht umkehrbar. Die Schnittmenge erfasst die Datensätze, welcher gleichermaßen in beiden Tabellen enthalten sind. Der Join verknüpft die beiden eingehenden Relationen aufgrund eines Gleichheitskriteriums. Die Division belässt die Datensätze der ersten eingehenden Tabelle, die als zugehörige Werte die Werte der zweiten eingehenden Tabelle aufweisen. Die Operationsreihenfolge ist nicht umkehrbar. Das Produkt hingegen kombiniert sämtliche Datensätze miteinander. 2. Dies ist die Grundstruktur der einfachen SELECT – Abfrage ohne eine einschränkende Prüfung.
SQL
255
LÖSUNGEN
SELECT titel, preis, vorkenntnisse FROM kurse 3. Die Bedingung für die Kursdauer geben Sie in der einfachen WHERE – Klausel vor. SELECT titel, preis, vorkenntnisse FROM kurse WHERE dauer>=3 4. Alternativ können Sie zwischen zweifacher Verwendung der Vergleichsoperatoren und dem Operator BETWEEN wählen. Letzterer wirkt übersichtlicher und stellt die Grenzen nah beieinander. SELECT titel, preis FROM kurse WHERE preis BETWEEN 300 AND 600 5. Ähnliche Überlegungen gelten für die zweite Variante. Während der IN – Operator die einzelnen Fälle sehr übersichtlich nebeneinander in eine Reihenfolge bringen kann, entstehen bei mehrfacher Verwendung des Operators OR zu viele Text-Bruchstücke. SELECT titel, preis FROM kurse WHERE titel IN ('Flash', 'XML', 'SQL') SELECT titel, preis FROM kurse WHERE titel = 'Flash' OR titel = 'XML' OR titel= 'SQL' 6. Zunächst wird der Mehrwertsteuerbetrag mit Hilfe eines Produkts aus dem Preis und dem Mehrwertsteuersatz als Dezimalzahl berechnet, bevor der Vergleich mit der Grenze 250 stattfindet. Die Ausgabe wird davon nicht beeinflusst, sondern ausschließlich die Aufnahme in die Ergebnisrelation. SELECT titel, preis FROM kurse WHERE preis*0.16 > 250 7. Gleiches gilt für diese Aufgabe. Zunächst müssen Sie die Erhöhung um 30 % mit 1.3 und den Bruttopreis mit 1.16 berechnen, ehe Sie den Vergleich mit der Grenze 1000 vornehmen. SELECT titel, preis, dauer FROM kurse WHERE preis*1.3*1.16 > 1000 8. Zunächst erhöhen Sie die vorhandene Dauer um einen Tag durch die Addition von 1. Dann vergleichen Sie, ob die entstehende Zahl größer als 3 wird. SELECT titel, preis, dauer FROM kurse WHERE dauer+1 > 3 9. Einige Kurse haben römische Ziffern als Kursnummer, die dem eigentlichen Titel folgen, aber nicht am Ende des Titels stehen, da meistens ein Untertitel folgt. Daher müssen Sie jeweils ein
256
SQL
LÖSUNGEN
Prozentzeichen vor und nach der römischen Zahl vorgeben, um diesen Titelaufbau zu berücksichtigen. SELECT titel, preis FROM kurse WHERE titel LIKE '%III%' 10.Da genau ein Buchstabe vor dieser Zeichenkette stehen soll, müssen Sie den Unterstrich einsetzen. Da es aber verschiedene Java-Kurse im Angebot gibt, muss zusätzlich das Prozentzeichen für die Zeichen nach av benutzt werden. SELECT titel, preis FROM kurse WHERE titel LIKE '_av%' 11.Den Buchstaben-Bereich tragen Sie in eckigen Klammern ein, die noch vor dem Prozentzeichen stehen, da ja nach diesem ersten Buchstaben beliebig viele Zeichen folgen sollen. SELECT titel, preis FROM kurse WHERE titel LIKE '[A-Z]%'
Modul 5 - Komplexe Abfragen, Unterabfragen und Funktionen 1. Von der Tabelle buchungen aus müssen die konstituierenden Beziehungen in beide Richtungen mit teilnehmer und kurse verknüpft werden. Um dann noch den richtigen Kurs zu treffen, muss PHP% abgefragt werden, da es ja verschiedene PHP-Kurse in der Tabelle gibt, die alle mit dem Wort PHP beginnen. Tatsächlich wurde aber nur der erste PHP-Kurs „PHP I“ gebucht. SELECT buchungen.buchungsnr, buchungen.kursnr, teilnehmer.teilnnachname, kurse.titel FROM buchungen, kurse, teilnehmer WHERE buchungen.kursnr=kurse.kursnr AND buchungen.teilnnr=teilnehmer.teilnnr AND kurse.titel LIKE 'PHP%' 2. Die beiden konkret vorgegebenen Kurse werden innerhalb der IN – Klausel eingetragen. Ansonsten kann man statt einer explizit angegebenen Verknüpfung in diesem Zwei-Tabellen-Fall auch den Befehl NATURAL JOIN einsetzen. SELECT buchungen.buchungsnr, buchungen.kursnr,
SQL
257
LÖSUNGEN
buchungen.teilnnr, kurse.titel FROM buchungen NATURAL JOIN kurse WHERE kurse.titel IN ('PHP I', 'SQL') 3. Im Ergebnis werden die einzelnen Teilnehmer jeweils mit allen sechs Firmen verknüpft. Dadurch ergibt sich in der Ergebnisrelation ein Muster, wie es die nebenstehende Abbildung sehr deutlich zeigt: Jeweils sechs Mal steht der Teilnehmername untereinander, während die sechs Firmennamen in der Spalte rechts daneben durchlaufen werden. Gleiches gilt für die doppelt ausgegebene Spalte untnr. Die linke gehört zur Tabelle teilnehmer, während sich die rechte aus der Tabelle unternehmen rekrutiert. SELECT teilnehmer.untnr, unternehmen.untnr, teilnnachname, untname FROM unternehmen CROSS JOIN teilnehmer 4. Die andere Struktur der Ergebnisrelation im Vergleich zum vorherigen Beispiel ergibt sich durch die andere Anordnung in der JOIN – Klausel. Hier ist wichtig, dass die beiden zu verknüpfenden Spalten noch einmal in der ON – Klausel aufgerufen werden müssen. Die anderen beiden Abfragen sind exakt gleich strukturiert, sodass lediglich die Verknüpfungsart innerhalb der FROM – Klausel gewechselt werden muss. An die letzten beiden schließt sich dann als weitere Einschränkung innerhalb der WHERE – Klausel ein LIKE – Operator an. SELECT teilnehmer.untnr, unternehmen.untnr, teilnnachname, untname INNER JOIN bezieht nur solche Zeilen in die erste Ergebnisrelation ein, die als Wert kein NULL enthalten. Daher bleiben die Datensätze an sich gleich. FROM teilnehmer INNER JOIN unternehmen ON unternehmen.untnr = teilnehmer.untnr SELECT teilnehmer.untnr, unternehmen.untnr, teilnnachname, untname FROM unternehmen LEFT OUTER JOIN teilnehmer ON teilnehmer.untnr = unternehmen.untnr WHERE teilnehmer.teilnnachname LIKE "A%" SELECT teilnehmer.untnr, unternehmen.untnr, teilnnachname, untname FROM unternehmen RIGHT OUTER JOIN teilnehmer ON teilnehmer.untnr = unternehmen.untnr
258
SQL
LÖSUNGEN
WHERE teilnehmer.teilnnachname LIKE "A%" 5. LEFT OUTER JOIN verknüpft die Zeilen der ersten Tabelle mit den zugehörigen Werten der zweiten Tabelle, wobei evtl. nicht vorhandene Werte in der zweiten Tabelle NULL gesetzt werden. RIGHT OUTER JOIN entspricht von der Funktionsweise dem LEFT OUTER JOIN. Hierbei liegt jedoch die Wertedominanz bei der eingehenden zweiten Tabelle, sodass bei einem fehlschlagenden Vergleich in der ersten Tabelle in dieser Tabelle der Wert NULL ergänzt wird. Im vorliegenden Fall gibt es keine Null-Werte in den Tabellen, sodass die Abfrageergebnisse gleich sind. 6. Es müssen für eine der betreffenden Firmen Null-Werte erzeugt werden wie z.B. mit folgendem Befehl. Eventuell müssen Sie vorher zulassen, dass überhaupt Null-Werte in der Primärschlüsselspalte eingetragen werden können. UPDATE unternehmen SET untnnr=NULL WHERE untname="TONAlicht GbR" ¾ LEFT OUTER JOIN: Die Wertedominanz liegt bei der ersten, linken eingehenden Tabelle. Das ist die Tabelle unternehmen, in der kein Treffer für den von der zweiten, rechten eingehenden Tabelle teilnehmer gefundenen Wert untnr=4 für Herrn Abseiter liegt. Deswegen wird genau der Datensatz von Herrn Abseiter ausgeblendet. ¾ RIGHT OUTER JOIN: Hier liegt die Wertedominanz bei der zweiten, rechten eingehenden Tabelle. Das ist hier die Tabelle teilnehmer. Da es insgesamt nur drei Teilnehmer gibt, die die Bedingung erfüllen, einen Nachnamen zu haben, der mit A beginnt, wird Herr Abseiter in die endgültige Ergebnisrelation aufgenommen. Da aus der Tabelle unternehmen bzgl. seiner Unternehmensnummer keine Treffer zurückgeliefert werden, erscheinen die Spalten in der endgültigen Ergebnisrelation mit dem Wert NULL. ¾ INNER JOIN: Hier werden Null-Werte von beiden Seiten aus einfach in der Ergebnisrelation ausgeblendet. Daher erscheint Herr Abseiter nicht. Er würde zudem auch nicht erscheinen, wenn statt einer NULL in der Tabelle unternehmen eine solche NULL in der Tabelle teilnehmer stünde.
SQL
259
LÖSUNGEN
Während die Funktionsweisen der einzelnen Verknüpfungsarten natürlich gleich bleiben, hängen die Ergebnisse entscheidend davon ab, in welcher Reihenfolge die Tabellen in die Abfrage eingehen und in welcher Tabelle ein Null-Wert vorhanden ist. Man könnte das oben genannte Beispiel also dahingehend ausbauen, dass alle Kombinationsmöglichkeiten durchgespielt würden.
7. Über die Verknüpfung der Tabelle teilnehmer mit sich selbst, kann man eine Untermenge bilden, die als Ergebnisrelation genau die Teilnehmer enthält, die unterschiedliche Nachnamen, aber die gleiche Hausnummer haben. Es sieht in nebenstehender Abbildung so aus, als ob die Hausnummern aufsteigend sortiert würden. Tatsächlich gilt dies nicht, soweit man die Zahlenwerte an sich betrachtet. Einstellige Hausnummern stehen z.B. weiter unten. Dies hängt mit dem Datentyp VARCHAR zusammen, der ja auch solche Hausnummern wie „7b“ abspeichern sollte. SELECT DISTINCT a.teilnnachname, a.teilnhausnr FROM teilnehmer AS a, teilnehmer AS b WHERE a.teilnhausnr = b.teilnhausnr AND a.teilnnachname <> b.teilnnachname ORDER BY a.teilnhausnr, a.teilnnachname 8. Es handelt sich einfach um die Grundstruktur der Verwendung für die Reihenzählung, wobei in der Variante ein Aliasspaltenname vergeben wird. SELECT COUNT(teilnnr) FROM teilnehmer SELECT COUNT(teilnnr) AS AnzahlDerTeilnehmer FROM teilnehmer Die Spaltenfunktion AVG wird lediglich über die Spalte dauer gelegt, was den Wert von 2.76 ergibt. Dieser kann entweder direkt in die WHERE – Klausel der Abfrage für die Tabelle kurse vorgegeben werden, oder man bindet die komplette Abfrage als Unterabfrage in die WHERE – Klausel ein. SELECT AVG(dauer) FROM kurse SELECT titel, dauer, preis FROM kurse WHERE dauer > 2.7600 SELECT titel, dauer, preis
260
SQL
LÖSUNGEN
FROM kurse WHERE dauer > (SELECT AVG(dauer) FROM kurse) 9. Für die Beantwortung muss man nicht nur die Tabelle buchungen mit den Tabellen kurse und teilnehmer verbinden, sondern sogar die Tabellen teilnehmer und unternehmen, da nur so Informationen der buchenden Unternehmen ausgegeben werden können. SELECT untname, titel, COUNT(buchungen.teilnnr) AS Kursbuchungen FROM buchungen, teilnehmer, unternehmen, kurse WHERE buchungen.teilnnr=teilnehmer.teilnnr AND unternehmen.untnr=teilnehmer.untnr AND buchungen.kursnr=kurse.kursnr GROUP BY titel ORDER BY Kursbuchungen DESC 10.Das Ergebnis der Unterabfrage ergibt sich z.B. durch die durch NOT IN umgekehrte Abfrage der stattgefundenen Kurse. Alle anderen werden dann durch NOT IN automatisch gefunden. Möchte man die Abfrage direkt vorgeben, muss man natürlich die Kursnummern der so gefundenen Kurse in eine Werteliste eintragen. Die Unterabfrage ersetzt dann genau diese Werteliste. Da es zusätzlich nicht um die Termine, sondern nur um die Kurse an sich geht, verhindert DISTINCT die Anzeige von Kursen mit mehreren Terminen. SELECT buchungen.kursnr, kurse.titel, COUNT(buchungen.kursnr) FROM buchungen NATURAL JOIN kurse GROUP BY buchungen.kursnr SELECT DISTINCT kurse.kursnr, kurse.titel, termine.ort FROM kurse NATURAL JOIN termine WHERE kurse.kursnr NOT IN (10111, 20117, 20134, 20136, 20142, 30129, 30136, 30329, 40314) SELECT DISTINCT kurse.kursnr, kurse.titel, termine.ort FROM kurse NATURAL JOIN termine WHERE kurse.kursnr NOT IN (SELECT buchungen.kursnr, kurse.titel, COUNT(buchungen.kursnr) FROM buchungen NATURAL JOIN kurse
SQL
261
LÖSUNGEN
GROUP BY buchungen.kursnr)
Modul 6 - Abfragen in virtuellen Tabellen speichern 1. Dies ist die einfache Standardform der Sicht-Erstellung, in der auch die Spaltennamen aus der zu Grunde liegenden realen Tabelle übernommen wird. Es handelt sich zudem um eine Projektionssicht, da lediglich drei Spalten komplett ausgewählt und in die Sicht übernommen werden sollen. CREATE VIEW Teilnehmer AS SELECT teilnvorname, teilnnachname, teilnstadt FROM teilnehmer 1. In dieser Variation der oben gebildeten Sicht werden die Spaltennamen der realen Tabelle durch eigene Namen ersetzt, die in einer Namensliste nach der Sicht-Bezeichnung eingetragen werden. CREATE VIEW Teilnehmer (Vorname, Nachname, Wohnort) AS SELECT teilnvorname, teilnnachname, teilnstadt FROM teilnehmer 1. Diese Sicht beinhaltet eine Unterabfrage, die den Durchschnittspreis von 807.,20 Euro an die WHERE – Klausel zurückliefert. Wegen der Unterabfrage wäre eine solche Sicht nicht für eine Aktualisierungsabfrage geeignet. CREATE VIEW Kursbesuche (Titel, Dauer, Preis) AS SELECT titel, dauer, preis FROM kurse WHERE preis > (SELECT AVG(preis) FROM kurse)
262
SQL
LÖSUNGEN
2. Der Durchschnittspreis für einen Tag errechnet sich direkt im Spaltenaufruf, was bei dieser Sicht auch der einzig interessante Punkt ist. CREATE VIEW Tagespreise (Kursnr, Titel, Tagespreis) AS SELECT kursnr, titel, preis/dauer FROM kurse ORDER BY bereich 3. Diese Sicht benötigt – wie immer bei der Tabelle buchungen – eine Verknüpfung mit der Tabelle teilnehmer. CREATE VIEW Kursbesuche (Teilnehmernummer, Vorname, Nachname) AS SELECT buchungen.teilnnr, teilnvorname, teilnnachname FROM buchungen NATURAL JOIN teilnehmer WHERE kursnr=50232 4. Die Sicht wird einfach mit all ihren Spalten über den Asteristikus aufgerufen, wobei innerhalb der WHERE – Klausel zusätzlich die Einschränkung für die Dauer vorgegeben wird. CREATE VIEW Grafikkurse AS SELECT titel, preis, dauer FROM kurse WHERE bereich="Grafik" SELECT * FROM Grafikkurse WHERE dauer>3 5. Da ja die drei erscheinenden Datenzeilen (an denen Sie auch erahnen können, dass wir in MS Excel die Auto-Auffüllfunktion in einigen Spalten der Datenbank benutzt haben) in dieser Form wegen der Aggregatfunktion gar nicht in der Datenbank existieren, sondern eigens erzeugt werden, eignet sich diese Sicht überhaupt nicht für Aktualisierungsanfragen. CREATE VIEW Orte AS SELECT teilnstadt, COUNT(teilnstadt) FROM teilnehmer GROUP BY teilnstadt 6. In die oben erstellte Sicht fügen Sie die Daten mit der gewöhnlichen INSERT INTO – Syntax ein. Problematisch wird es insbesondere durch die fehlende Kursnummer, die in der Sicht zwar nicht erscheint, aber innerhalb der Definition der realen Tabellen sogar mit NOT NULL definiert wurde. Dieser Befehl wird also eine vernichtende Fehlermeldung generieren.
SQL
263
LÖSUNGEN
INSERT INTO Grafikkurse VALUES ('Auto-CAD', 1050, 4) 7. Zunächst können die Photoshop-Kurse nur gelöscht werden, wenn der LIKE – Operator eingesetzt wird. Ohne WITH CHECK OPTION werden sämtliche drei Kurse in der realen Tabelle gelöscht. Hat man dagegen zuvor diese Option vorgegeben, so kann der Befehl nicht ausgeführt werden, da die Kurse aufgrund ihrer Zuordnung zum Grafik-Bereich nicht mehr in der Sicht auftauchen würden. Genau das verhindert WITH CHECK OPTION. DELETE FROM Grafikkurse WHERE titel LIKE 'Photo%' 8. Die Preiserhöhung lässt sich leicht durch die Multiplikation innerhalb der SET – Anweisung erreichen. Hier gibt es keine Schwierigkeiten mit der Ausführung des Befehls wie in der letzten Aufgabe. Da überhaupt keine weiteren Suchkriterien verwendet werden, wandert kein Tupel aus der Sicht heraus, sodass auch bei WITH CHECK OPTION die Änderung ausgeführt würde. UPDATE Grafikkurse SET preis=preis*1.3
Modul 7 - Zugriffskontrolle durch Benutzer, Rechte und Rollen 1. Hier genügt die Grundform, um einen Benutzer anzulegen, da Sie ja keine Rechte vergeben. CREATE USER HeidiStern IDENTIFIED BY 842953 2. In diesem Fall treten zusätzlich zur Grundform noch die Zeilen hinzu, mit der (in Oracle zumindest) die Namen des Speicherplatzes und die MB-Zahlen für die verschiedenen Tabellenplätze festgelegt werden können. CREATE USER HeidiStern IDENTIFIED BY 842953 DEFAULT TABLESPACE kursplanung_hs QUOTA 20M ON kursplanung_hs TEMPORARY TABLESPACE kursplanung_hs_temp QUOTA 20M ON kursplanung_hs_temp 3. In diesem Fall variiert man die Grundform lediglich mit dem Befehl ALTER und hängt das neue Passwort an den Befehl. ALTER USER HeidiStern IDENTIFIED BY karlsruhe 4. Da Sie alle Rechte vergeben, ersparen Sie sich den Rechte- und Spaltenaufruf. Durch die Option PUBLIC sprechen Sie sämtliche Benutzer gleichzeitig an. GRANT ALL PRIVILEGES ON TABLE kurse TO PUBLIC 5. In diesem Fall genügt der einfache Befehlsaufruf in der Rechteliste, da keine weitere Spalteneinschränkung notwendig ist. GRANT UPDATE, SELECT, DELETE ON kurse TO HeidiStern
264
SQL
LÖSUNGEN
6. Sobald sich die Rechte explizit auf einzelne Spalten beziehen und damit andere Spalten automatisch ausgeschlossen werden sollen, fügen Sie einfach die Spaltenliste an jeden Befehl an, der modifiziert werden soll. GRANT SELECT DELETE INSERT (kursnr, titel, beginn, ende) UPDATE (titel, beginn, ende, ort) ON TABLE termine TO HeidiStern 7. Die Rechteliste verkürzen Sie lediglich mit Hilfe einer Befehlsliste, da ja nicht einzelne Spaltenrechte entfernt werden sollen, sondern der gesamte Befehl. REVOKE UPDATE, SELECT, DELETE ON kurse FROM HeidiStern 8. Da Sie sämtliche Rechte von allen Benutzern löschen möchten, ergibt sich die gleiche Struktur wie im obigen, umgekehrten Fall. REVOKE ALL PRIVILEGES ON kurse FROM PUBLIC 9. Da Rollen kein Kennwort benötigen (nur optional anbieten), genügt die ganz simple CREATE Anweisung. CREATE ROLE Dozent 10.Die Rechte für die Rolle Dozent erstellen Sie analog zu den oben festgelegten Rechten für die Benutzer, indem Sie die einzelnen Befehle auflisten und wahlweise mit Spaltenlisten für die einzelnen Tabellen versehen. GRANT SELECT DELETE INSERT (titel, themen, vorkenntnisse, dauer) ON kurse SELECT DELETE UPDATE (kursnr, beginn, ende) ON termine TO Dozent 11.Gesetzt den Fall, Sie haben für uns zwei Benutzer angelegt (bzw. setzen das hier gedanklich voraus), rufen Sie die Rolle auf und weisen Sie mit TO den entsprechenden Benutzernamen zu. GRANT Dozent TO MarcoSkulschus, MarcusWiederstein
Modul 8 - MySQL, MS SQL Server und Oracle 1. Starten Sie die Eingabeaufforderung Ihrer Windows-Version und geben Folgendes ein: C:\mysql\bin\mysql. Diese Eingabe spiegelt den Installationspfad von MySQL wider. In
SQL
265
LÖSUNGEN
dem Ordner befindet sich der Unterordner bin, in dem sich die Startdatei von MySQL namens mysql befindet. Um alle Datenbanken aufzulisten, geben Sie SHOW DATABASES; ein. Um eine spezielle DB zu verwenden, geben Sie danach USE dbname; ein. 2. Verwenden Sie entweder direkt SQL in der Eingabeaufforderung, in der Sie die Befehle mit einem Semikolon beenden müssen, oder ein Werkzeug wie MySQL Front. 3. Sie finden unter Start/Programme/Oracle-OroHome92/Configuration and Migration Tools/Database Configuration Assistant einen – wie der Name schon vermuten lässt – hilfreichen Assistenten für die gestellte Aufgabe. 4. Zunächst starten Sie hier das SQLPlus Worksheet. Sie finden es unter Start/Programme/ Oracle-OraHome92 / Application Development/SQLPlus Worksheet. Nun folgt ein Anmeldefenster. Melden Sie sich hier mit dem Benutzernamen system, dem Kennwort Oracle, dem Dienst SemiTex an (also den Informationen, die Sie zuvor festgelegt haben). In das Anmelden &als – Feld Wählen Sie bitte den SYSDBA aus. Um SQL-Quelltext auszuführen, klicken Sie auf die Blitz-Schaltfläche. 5. Entweder wird der Treiber bereits mitgeliefert oder Sie müssen ihn sich vom Hersteller aus dem Internet besorgen. Es gibt Treiber für die unterschiedlichen Betriebssysteme. Den ODBC- Treiber können Sie in der Systemsteuerung konfigurieren. Unter Windows 2000 finden Sie ihn beispielsweise in Systemsteuerung / Verwaltung. Wenn Sie dort doppelklicken, finden Sie die Einstellmöglichkeiten von ODBC unter Windows. Sie finden die Benutzer-DSN, die System-DSN und die Datei-DSN, welche Sie für die Datenbank und die Verbindung einstellen müssen. 6. Wählen Sie Datei / Externe Daten / Tabellen verknüpfen. MS Access fragt nun nach einem Speicherort. Wählen Sie in der Abfrage des Speicherortes den Dateityp ODBC Databases(). Sie gelangen dann automatisch in eine weitere Auswahl, wo Sie die Computerdatenquelle auswählen. Für die Systemdatenquelle und den geeigneten Treiber geben Sie dann in einem Formular die gewünschten Informationen vor. 7. Die ODBC- Architektur besteht aus vier Schichten: Applikationsschicht (z.B. ein PHP- Skript), Treiber- Manager (Windows ODBC- Manager), ODBC- Treiber (z.B. MySQL – ODBC- Treiber für Windows), Datenquelle (MySQL- Server).
Modul 9 - MS SQL Server und Transact SQL 1. Der Datentyp kann nur float sein, da Berechnungen über die Division bei allen Zahlen Dezimalkommazahlen als Ergebnis hervorrufen. Um die Variable mit einem Wert zu füllen, genügt die einfache Berechnung des Durchschnittswertes der Spalte preis mit der Funktion avg. declare @durchschnittspreis float select
@durchschnittspreis = avg(preis) from kurse
go Wenn Sie keine Abfrage verwenden, um die Variable mit einem Wert zu füllen, ermitteln Sie über eine ähnliche Abfrage den aktuellen Wert des Durchschnittspreises und ersetzen die obige Abfrage durch diesen ermittelten Wert. declare @durchschnittspreis float select
266
@durchschnittspreis = 807.2000
SQL
LÖSUNGEN
go 2. Die vorgegebene Grenze ist der auf die nächste Hunderterstelle aufgerundete tatsächliche Tagespreis der Tabelle kurse. Über die Division beider Durchschnitte der Spalten preis und dauer erhalten Sie den Gesamttagespreis des Kursangebots. select avg(preis)/avg(dauer) as Tagespreis from kurse select preis, titel from kurse where preis > 292.463768 select preis, titel from kurse where preis < 292.463768 select count(preis) from kurse where preis > 292.463768 Das gesuchte Programm enthält zunächst eine Variablendeklaration und eine automatische Wertzuweisung, die den bereits oben ermittelten Tagespreis analog berechnet. Innerhalb der if – Klausel greift man dann auf den in der Variable @tagespreis gespeicherten Wert zurück und vergleicht ihn mit der gesetzten Grenze von 300 Euro. declare @tagespreis float select
@tagespreis = avg(preis)/avg(dauer) from kurse
if (@tagespreis > 300) begin print 'Der Durchschnittspreis liegt über 300 Euro.' end else begin print 'Der Durchschnittspreis liegt unter 300 Euro.' end go 3. Die beiden benötigten Abfragen unterscheiden sich hauptsächlich in der Tatsache, dass zum einen das gesamte Ergebnis und zum anderen nur die Reihenanzahl abgerufen wird. Um zu überprüfen, ob überhaupt Buchungen erfolgt sind, benötigt man den Operator exists direkt nach der if – Klausel. Wird hier der Wert WAHR zurückgeliefert, läuft eine ähnliche Abfrage im Anweisungsblock der if – Klausel ab, um die Anzahl der Buchungen zu ermitteln. Nebenstehende Abbildung zeigt, dass tatsächlich Kurse aus den gesuchten Bereichen stattfanden und dass für sie insgesamt 54 Buchungssätze erfolgten. if exists (select titel, buchungen.kursnr, buchungen.buchungsnr from buchungen natural join kurse where kurse.bereich in ("Grafik", "Webdesign")) begin
SQL
267
LÖSUNGEN
declare @buchungenanzahl int select
@buchungenanzahl = count(*)
from buchungen natural join kurse where kurse.bereich in ("Grafik", "Webdesign") print @buchungenanzahl end else begin print 'Noch keine Buchungen für Grafik oder Webdesign.' end go 4. Die Zählvariable @i erhält zu Beginn den Wert 1. Für die Entwicklung der Schleife haben Sie bzgl. der Bedingung in der while – Klausel zwei Möglichkeiten. Entweder fragen Sie ab, ob der Wert kleiner gleich 23 ist, oder sie fragen ab, ob der Wert kleiner 24 ist. Da 23 die letzte Zahl ist, die ausgegeben werden soll, muss sie in beiden Fällen die Bedingung erfüllen. declare @i int select
@i = 1
while (@i <= 23) begin print @i select @i = @i + 2 end print 'Stopp!' 5. Eine wirtschaftsprüferische “Analyse” der Buchungen der Firma SemiTex ergibt, dass nur einmal der Kurs mit der Nummer 20239 stattgefunden hat. Die Buchungen liegen zwischen den Buchungsnummern 23 und 33 für insgesamt 11 Teilnehmer, die zudem auch die ersten Teilnehmer waren, die überhaupt Kurse buchten. Daher haben sie Teilnehmernummern von 1 bis 11. Die Kursnummer wird direkt vorgegeben und muss nicht abgefragt werden. Ebenso ist die höchste Buchungsnummer nicht interessant, da sie als fortlaufende Nummer von der Anzahl der Teilnehmer abhängt. Diese Überlegungen werden nachher im eigentlichen Anweisungsblock interessant.
268
SQL
LÖSUNGEN
Die eingehenden Informationen aus der Aufgabenstellung transformiert man zuerst in Variablen und ihre Werte um. declare @ErsteBuchungsNr int select
@ErsteBuchungsNr = 23
declare @KursnNr int select
@KursNr = 20239
declare @TNAnzahl int select
@TNAnzahl = 11
declare @i int select
@i = 0
Interessant am Programmablauf ist, dass zunächst aus dem zu löschenden Buchungssatz die Teilnehmernummer abgerufen wird. Danach löscht das Programm den Datensatz mit der bereits vorgegebenen Buchungsnummer. Dieser Prozess läuft nun bei jedem Durchlauf für jede neue Buchungsnummer ab. Als Ausgabeinformation gibt es einmal die Teilnehmernummer und am Schluss des gesamten Programms eine allgemeine Bestätigung. while (@i<=@TNAnzahl) begin declare @TeilnehmerNr int select
@TeilnehmerNr = teilnnr from buchungen where buchungsnr = @ErsteBuchungsNr
print
'@TeilnehmerNr ausgebucht'
delete from buchungen where buchungsnr = @ErsteBuchungsNr select @ErsteBuchungsNr = @ErsteBuchungsNr + 1 select @i = @i + 1 end print 'Alle Buchungen für @Kursnr gelöscht.' 6. Im Anweisungsblock der Schleife ändert sich nichts. Für die Verwendung der Prozedur sind nun Parameter für die erste Buchungsnummer, die Anzahl der auszubuchenden Teilnehmer und die Kursnummer wichtig. create procedure BuchungenLoeschen (@ErsteBuchungsNr int, @TNAnzahl int, @KursNr int) as declare @i int select
@i = 0
while (@i<=@TNAnzahl) begin declare @TeilnehmerNr int select
SQL
@TeilnehmerNr = teilnnr from buchungen
269
LÖSUNGEN
where buchungsnr = @ErsteBuchungsNr print
'@TeilnehmerNr ausgebucht'
delete from buchungen where buchungsnr = @ErsteBuchungsNr select @ErsteBuchungsNr = @ErsteBuchungsNr + 1 select @i = @i + 1 end print 'Alle Buchungen für @Kursnr gelöscht.' go execute BuchungenLoeschen @ErsteBuchungsNr=23, TNAnzahl=11, @KursNr=20239 go
Modul 10 – Oracle und PL/SQL 1. Hier verwenden Sie die unterschiedlichen Formen der Variablendeklaration mit und ohne vorheriger Wertzuweisung. Bei beiden Formen dürfen Sie natürlich nicht den Datentyp vergessen. DECLARE Seminarort char :='Duisburg'; Seminarzentrum char :='Alter Bahnhof'; Kursnr number; Datum date; 2. Der Cursor benötigt bei seiner Deklaration umgehend eine Abfragemenge, die ihn beschreibt. DECLARE cursor Termine_Ddorf is select * from termine where ort='Düsseldorf'; 3. Da die Variable Status erst durch die Abfrage mit einem Wert, nämlich der Anzahl der Kurse in Dortmund, gefüllt wird, wird sie zunächst ohne Wertzuweisung deklariert. Im Anweisungsblock verwenden Sie dann die Fallunterscheidungen mit CASE, um auf die speziellen Terminanzahlen mit einer passenden Ausgabe zu reagieren. DECLARE Status integer; BEGIN select count(ort) into
270
Status
SQL
LÖSUNGEN
from
termine
where
ort='Dortmund';
CASE Status WHEN '25'
THEN dbms_output.put_line('Status 1');
WHEN '50'
THEN dbms_output.put_line('Status 2');
WHEN '75'
THEN dbms_output.put_line('Status 3');
WHEN '100' THEN dbms_output.put_line('Status 4'); END CASE; END; 4. Das einzig Schwierige ist hier die Abfrage. Ansonsten deklarieren Sie nur eine neue Variable, in der sie das Abfrageergebnis speichern. DECLARE Anzahl number; BEGIN select count(distinct titel) into Anzahl from kurse, teilnehmer, buchungen, unternehmen where buchungen.kursnr=kurse.kursnr and teilnehmer.untnr=unternehmen.untnr and teilnehmer.teilnnr=buchungen.teilnnr and unternehmen.untnr=1; dbms_output.put_line('Kurse: ' || Anzahl); END;
SQL
271
LÖSUNGEN
13 Glossar
272
SQL
GLOSSAR
SQL
273
GLOSSAR
13 Glossar Um den vorhandenen Platz gut auszunutzen, haben wir das Glossar auch zu einer Befehlsreferenz ausgebaut. Erklärungen und Hinweise zu DB-Objekten schließen mit der allgemeinen Syntax ab. Sie finden diese Zusammenstellungen nur teilweise im Text, wenn sie umfangreicher Natur sind. Kurze Syntaxübersichten haben wir dagegen nur in diesen Glossar aufgenommen, um den Lesefluss nicht allzu sehr in den einzelnen Projekten zu unterbrechen.
13.1
DB-Lexikon
Abfrage Im gemeinsprachlichen Fall bezeichnet man mit diesem Begriff einen Abruf von Datensätzen bzgl. eines oder mehrerer Suchkriterien. Die einfache Abfrage benutzt nur eine Tabelle, die komplexe Abfrage dagegen mehrere, die über die Primärschlüssel-Fremdschlüssel-Beziehung verknüpft sind. Unterabfragen sind eingebettete Abfragen in anderen Abragen oder Anweisungen. Aggregatfunktionen Aggregat- oder Spaltenfunktionen wie SUM, MAX, MIN, AVG oder COUNT führen kleine statistische oder mathematische Berechnungen an einer Spalte durch. Alias-Name Der Alias-Name oder auch der Synonym-Name ist ein „Spitzname“ für eine Tabelle, mit der sie leichter anzusprechen sein soll. Anomalie Datenbank-Anomalien beschreiben ungewollten Daten- und Informationsverlust aufgrund eines ungünstig (meist nicht normalisierten) Datenmodells. Sie treten beim Abfragen, Einfügen, Aktualisieren und Löschen auf. Atomisiert Atomisiert sind Attribute genau dann, wenn sie nicht weiter aufgeteilt werden können. Attribut Ein einzelnes Feld oder eine einzelne Spalte heißt Attribut der Tabelle. Benutzer Benutzer repräsentieren natürliche oder fiktive Personen, die Zugriff auf die Daten oder das Datenmodell erhalten. Benutzergruppen Anwender haben eine externe Sicht auf die Datenbank und greifen mit speziell konfigurierten Programmen auf die Datenbank zu. Ein Zugriff kann dabei über eine Abfrage oder über Dateneingabe erfolgen. / Änderungen wie das Entfernen von Tabellen oder ihre Vergrößerung führt der Administrator aus. Er ist in dieser Hinsicht für die Weiterentwicklung und den Erhalt der Datenbank verantwortlich und betreut sie mit speziellen Hilfsmitteln. / Der Datenbankentwickler programmiert die Datenbank, entwirft die Daten- und Rechtestruktur. Benutzerrollen werden auch als Rollen bezeichnet. Benutzergruppen kann man Berechtigungen vergeben und dann Benutzer diesen Benutzergruppen zuweisen. So ist die Benutzerverwaltung einfacher.
274
SQL
GLOSSAR
Beziehungstypen 1:1 - Eineindeutig: Jedem Objekt vom Typ A ist genau ein Objekt vom Typ B zugeordnet. / Funktional - 1:n: Jedes Objekt vom Typ A steht mit beliebig vielen Objekten vom Typ B in Beziehung. Dagegen steht ein Objekt vom Typ B höchstens mit einem Objekt vom Typ A in Beziehung. / Komplex - n:m: Beliebig viele Objekte vom Typ A stehen mit beliebig Objekten vom Typ B in Beziehung und umgekehrt. Check Die CHECK - Klausel ist eine als DB-Regel bezeichnete Bedingung, die für einen in der bedingung angegebenen Zustand prüft, ob der Eintrag überhaupt sinnvoll ist. Collate Mit COLLATE ist eine spezielle Sortierfunktion gemeint, die über die CREATE COLLATION – Anweisung für unterschiedliche Sprachen eingerichtet werden kann. In einer solchen COLLATION könnt man also bspw. festlegen, dass Groß- vor Kleinbuchstaben sortiert werden sollen: ´A´ < ´B´ <... < ´Z´ < ´a´ < ´b´ < ... < ´z´ oder dass innerhalb eines Buchstabens zunächst die Großschreibung angezeigt werden soll: ´A´ < ´a´. Constraint siehe Einschränkung Datenbank Datenbank heißt der Speicherort auf einem physikalischen Datenträger wie CD-ROM, DVD, Festplatte usw. strukturierter Daten. Auf dieser Ebene unterscheidet man auch einen Basisbereich, der die tatsächlichen Daten enthält und einen Systemkatalog (engl. Data Dictionary) mit Informationen über die logische Struktur der gesamten Datenbank. Datenbanksystem Datenbanksystem heißt eine Struktur, die aus Datenbank und Datenbankmanagementsystem besteht. Der korrekte Oberbegriff für die Datenbank mit ihren Daten und das Datenbankmanagementsystem mit Verwaltungsfunktionen ist Datenbanksystem. Datenbankmanagementsystem Datenbankmanagementsystem (engl. Data Base Management System) heißt die Komponente eines DBS, das Datenverwaltung und Datensicherheit bereitstellt. Es bildet die Schnittstelle zwischen der Datenbank und der Kommunikationsschnittstelle zum Benutzer. Datenformat Die Eigenschaft Datenformat speichert die Ausgabestruktur von Daten wie z.B. das Währungsoder Datumsformat mit entsprechenden Unterkategorien. Datentyp Der Datentyp dürfte die bekannteste Weise sein, mit der Daten beschrieben werden können. Er ordnet Informationen in bestimmte Kategorien, für die jeweils unterschiedliche Verarbeitungsmöglichkeiten bestehen. Sie lassen sich semantisch in elementare (Vorname, Nachname) und zusammengesetzte (Name) unterteilen. Eine andere Unterteilung erfolgt nach dem Speicherformat wie Zahltypen, Texttypen und logische Daten. Delete Löscht komplette Datensätze anhand eines Suchkriteriums. Drei-Sichten-Architektur (ANSI / PARC) Interne Sicht: Direkt auf Datenbankebene beschreibt diese Sichtweise den Blick auf die Datenorganisation und die Art und Weise, wie die Datensätze auf einem geeigneten Speichermedium ab-
SQL
275
GLOSSAR
gelegt werden. / Konzeptionelle Sicht: Schaut man aus dieser Perspektive auf eine Datenbank, tritt das Datenmodell hervor. Die in der Realität gefundenen Objekte erhalten in der Konzeption bzw. im Datenmodell bestimmte Eigenschaften, die mit den Eigenschaften in der Wirklichkeit übereinstimmen. / Externe Sicht: Benutzer können von außen mit Hilfe von vorbereiteten oder eigenen Abfragen Datensätze suchen und ändern. Dabei kann man entweder direkt SQL-Befehle benutzen oder verschiedene Hilfsmittel (Stichwörter, Auswahllisten, Berichte oder eine Profisuche). Duplikate Doppelte Datensätze in Tabellen oder Abfrageergebnissen bezeichnet man als Duplikate oder Duplikatzeilen. Einschränkung Einschränkungen für Spalten und Tabellen (Constraints) sind Bedingungen, die von den Daten erfüllt sein müssen, wenn sie in einer Tabelle eingetragen werden sollen. Damit wird die so genannte referenzielle Integrität der Datenstruktur eingerichtet. Default Mit dem Standardwert kennzeichnet man solche Werte, die einzufügen sind, wenn keine Werte in den Datensatz eingetragen wurden. Diese Anweisung überschreibt zusätzlich die DEFAULTEinstellung einer Domäne. Domäne Wertebereiche (Domänen) können für eine Spalte vorgegeben werden, wobei nur die in diesem Wertebereich eingetragenen Werte in die Spalte aufgenommen werden. Elementare funktionale Abhängigkeit Zwei Attribute eines Objekts sind dann elementar funktional voneinander abhängig, wenn neben dem Schlüssel kein weiteres Attribut existiert, das das Attribut A bestimmt. Entity-Relationship-Modell Seit 1976 wird das von P.P. Chen vorgeschlagene Entity-Relationship-Modell (ER-Modell oder ERM) für eine erste Annäherung verwendet, dessen Vorteile in der grafischen Darstellung und der mathematischen Verständlichkeit liegen. Es besteht aus den Elementen Entity, Entity-Typ, Relationship und Attribut. Funktionale Abhängigkeit Für die funktionale Abhängigkeit gilt, dass zwei Attribute eines Objekts dann funktional voneinander abhängen, wenn zu jedem Wert von A nur ein Wert von B gehört. Grad Die Breite der Tabelle / die Anzahl der Spalten oder Felder heißt Grad der Relation. Kardinalität Kardinalität bedeutet die Höhe / Länge der Relation / Tabelle. Kurzaufnahme Snapshots stellen einmalige Abfragen dar, die zusammen mit ihrem Ergebnis gespeichert werden. Man ruft sie wie eine Abfrage einer realen Tabelle auf und kann weitere Einschränkungen vorgeben. Index Ein Index erleichtert die Abfrage von Tabellen durch eine spezielle Datensortierung in einer IndexTabelle, wobei diese Sortierung aufgrund einer für Abfragen wichtige Spalte hin optimiert ist. Insert
276
SQL
GLOSSAR
Fügt Datensätze in eine Tabelle ein. Normalenform Für die 1. Normalenform gilt, dass sie einen Schlüssel besitzt und alle Attribute atomisiert sind. / Gemäß Definition ist ein Objekt in 2. Normalenform, wenn es der in 1. Normalenform ist und die funktionalen Abhängigkeiten zwischen Schlüssel und den anderen Attributen elementar ist. / Damit ein Datenmodell in der 3. Normalenform ist, muss es zunächst in der 2. Normalenform sein und die Eigenschaft besitzen, dass die funktionalen Abhängigkeiten zwischen dem Schlüssel und den anderen Attributen direkt ist. Normalisierung Durch den Normalisierungsprozess soll ein Datenmodell mit folgenden Eigenschaften erreicht werden: Der Aufwand für die Weiterentwicklung der Anwenderprogramme soll gesenkt werden. / Die einzelnen Datenstrukturen sind logisch soweit wie möglich entflochten, sodass die Daten möglichst flexibel verwaltet werden können und Änderungen sowohl bei einzelnen Objekten als auch in der Anwendungssoftware leicht durchführbar bleiben. / Eine fast redundanzfreie Speicherung von Daten verkleinert den Speicherplatz und nutzt Rechenzeit besser aus. Null NULL repräsentiert einen leeren Wert, also ein nicht ausgefülltes Datenfeld. ODBC ODBC (Open Database Connectivity) ist eine universelle Schnittstelle für Datenbanken von der Firma Microsoft und hält sich an den SQL-Standard. ODBC liefert damit eine Schnittstelle für Anwendungen, die es zum Beispiel ermöglicht, eine Reihe von Clients auf die Ressourcen der Datenquelle zuzugreifen. Bei den Clients kann es sich um Benutzer, aber auch Anwendungen handeln. Prädikate Die Ergebnismenge der Unterabfrage prüfen verschiedene quantifizierte Prädikate. Primärschlüssel Der Primärschlüssel stellt für eine gesamte Spalte eine eindeutige Zuordnungsmöglichkeit für einen Datensatz. Sind alle anderen Werte in einem Tupel auch gleich, über den Primärschlüssel kann man einen Datensatz eindeutig referenzieren. Rechte Rechte stellen Erlaubnisse für DB-Operationen dar, die an Benutzer für Tabellen und Spalten vergeben werden können. Redundanz Ein Datenmodell weist dann Redundanzen auf, wenn gleiche Informationen mehrfach auftreten. Mit Hilfe der Normalisierung soll genau dies durch entsprechende Tabellen verhindert werden. Relation Die gesamte Tabelle heißt Relation. Relationale Datenmodell Das RDM (Relationale Datenmodell) beruht auf der Überführung der einzelnen Objekte im ERModell in Tabellen, die über die Primärschlüssel, die in der anderen Tabelle Sekundärschlüssel sind, in Beziehung stehen. Dieses Datenmodell wurde von E.F.Codd 1970 entwickelt und bildet die Grundlage für relationale Datenbanksysteme. In diesem Zusammenhang wird ein Datenmodell mit nur einer einzigen Tabelle und sämtlichen Informationen als Universal Relation bezeichnet. Relationale Algebra
SQL
277
GLOSSAR
Die Relationenalgebra stellt auf der Mengenlehre beruhende Rechenvorschriften zur Verfügung, um Tabellen und ihre Daten miteinander zu verknüpfen bzw. Daten abzufragen. Rolle Rollen stellen bei Benutzern häufig auftretende oder geplante Rechtestrukturen dar, die so zusammengefasst und als Bündel den Benutzern zugewiesen werden. Semantisches Modell Ein semantisches Modell versucht, die Objekte der Realität möglichst genau zu erfassen und so eine Basis für die endgültig zu erstellende Datenbank zu liefern. Im Idealfall entsteht ein Text, der bereits alle Objekte, Beziehungen und Attribute nennt. Die Entwicklung des semantischen Modells stellt die erste analytische Phase dar. Sicht Eine Sicht ist eine virtuelle Tabelle, die eine Abfrage in Form des Relationenschemas speichert und dieses bei Aufrufen ausführt. Ihr Aufruf erfolgt wie die Abfrage einer realen Tabelle und kann auch weitere Einschränkungen enthalten. Aktualisierungsanfragen können auch über Sichten realisiert werden. Sekundärschlüssel Der Sekundärschlüssel in Tabelle A ist der Primärschlüssel in Tabelle B. Über die Primärschlüssel-Fremdschlüssel-Beziehung (wobei Fremdschlüssel der Sekundärschlüssel ist) stehen zwei Tabellen miteinander in Beziehung. Select Fragt Daten aus einer oder mehreren Tabellen anhand eines Suchkriteriums ab. Dieser Befehl kann mit Gruppierungen, Sortierungen und Aggregatfunktionen kombiniert werden. SQL Structured Query Language (strukturierte Abfragesprache): Sprache für die Definition von DBObjekten, Abfrage von Datensätzen und Zugriffskontrolle. Man die Befehle in drei Klassen einteilen: DCL (Data Control Language), DML (Data Manipulation Language) und DDL (Data Definition Language). Tabelle Man unterscheidet reale, virtuelle und temporäre Tabellen sowie Ergebnistabellen. Reale Tabellen speichern die Datensätze und die Struktur ständig, während virtuelle Tabellen lediglich ein Relationenschema in Form von DB-Operationen speichern, mit denen sie die Daten aus der DB beschaffen. Ergebnistabellen enthalten sowohl Struktur als auch Daten, werden aber komplett entfernt, sobald sie nicht mehr benötigt werden. Transaktion Eine Transaktion sind zusammenhängende Handlungen innerhalb der Datenbank, die den DBInhalt von einem konsistenten in einen anderen konsistenten Zustand überführen. Tupel Ein Datensatz der Relation / Tabelle nennt sich Tupel. Update Aktualisiert und ändert bestehende Datensätze anhand eines Suchkriteriums. Universal Relation Die Universal Relation ist eine Tabelle mit allen Spalten des Datenmodells und allen Datensätzen, wobei durch die fehlende Normalisierung entsprechend viele Redundanzen auftreten.
278
SQL
GLOSSAR
Wertebereich Ein Wertebereich entspricht der Domäne und ist eine abgeschlossene Menge an möglichen Werten für ein Feld. Where Mit der WHERE – Klausel können Eigenschaften von Daten für DB-Abfragen und Aktualisierungen vorgegeben werden. Verschiedene Operatoren für Vergleiche (<, = oder LIKE , IN), Verknüpfungen (AND, OR) oder Berechnungen (+, /) stehen zur Verfügung. Zugriffskontrolle Zum Schutz der Datenbank lassen sich verschiedene Schutzmöglichkeiten unterscheiden: direkt in der Datenbank implementierter Benutzer, Anmeldung beim Start eines Computers oder eines Programms (Datenbank berücksichtigt, dass sich der Benutzer bereits in das Betriebssystem eingeloggt hat, und akzeptiert diese erfolgreiche Anmeldung nachher auch für den Zugang zur DB) Sichten, Rechte und Rollen.
13.2
Standard-SQL-Befehlsreferenz
ALIAS CREATE {SYNONYM | ALIAS} synonymname FOR tabellenname DROP {SYNONYM | ALIAS} synonymname CASE CASE WHEN bedingung1 THEN ergebnis1 WHEN bedingung2 THEN ergebnis2 [ELSE ergebnis3] END COMMENT COMMENT ON {[TABLE | COLUMN]} DB-objektname IS kommentar Datenbank CREATE DATABASE dbname DROP DATABASE dbname DELETE DELETE FROM tabellename |WHERE suchbedingung |WHERE suchbedingung IN SELECT – Anweisung GRANT GRANT {ALL PRIVILEGES
SQL
279
GLOSSAR
| SELECT | DELETE | {INSERT [(spalte1 [, spalte2,...])} | {UPDATE [(spalte1 [, spalte2,...])} | {REFERENCES [(spalte1 [, spalte2,...])} }[, ...] ON [TABLE] tabellenname TO {benutzer1 [, benutzer2, ...]} | PUBLIC [WITH GRANT OPTION] REVOKE [GRANT OPTION FOR] recht [, ...] ON tabelle FROM {benutzer1 [, benutzer2, ...]} | PUBLIC {CASCADE | RESTRICT} CONSTRAINT CREATE CONSTRAINT einschränkungsname bedingung [[INITIALLY DEFERRED | INITALLY IMMEDIATE] [NOT] DEFERRABLE] DROP CONSTRAINT einschränkungsname {CASCADE | RESTRICT} DOMAIN CREATE DOMAIN domänenname [AS] datentyp [DEFAULT voreinstellung] [[einschränkung]] CHECK (bedingung) [[INITIALLY DEFERRED | INITIALLY IMMEDIATE] [[NOT] DEFERRABLE] ] ] [COLLATE collationname] SNAPSHOT CREATE SHNAPSHOT kurzaufnahmenname [{spalte1, spalte2,...] AS abfrage INDEX CREATE [UNIQUE] INDEX indexname ON tabellenname {(spalte1[, spalte2,…])} INSERT INSERT INTO tabellenname
280
SQL
GLOSSAR
[(spalte1 [, spalte2, ...])] {VALUES (1wert1 [, 1wert2, ...)} |{[VALUES] (2wert1 [, 2wert2, ...)} |SELECT-Anweisung NULL IS [NOT] NULL Prädikate WHERE ... vergleichsoperator [ANY | ALL | SOME] unterabfrage WHERE ... vergleichsoperator [UNIQUE] unterabfrage WHERE ... vergleichsoperator [[NOT] EXISTS] unterabfrage Primärschlüssel PRIMARY KEY
(spalte1)
ROLE {ALTER | CREATE} ROLE rollenname [NOT IDENTIFIED |{IDENTIFIED BY kennwort | EXTERNALLY}] DROP ROLE rollenname VIEW CREATE VIEW sichtname [{spalte1, spalte2,...] AS abfrage [WITH [CASCADED | LOCAL] CHECK OPTION] SELECT SELECT [ALL | DISTINCT] * | {spalte1 [, spalte2, ...]} FROM tabellennamen [WHERE suchbedingung] [ORDER BY [spalte1 [, spalte2, ...]] [ASC | DESC]] [GROUP BY [spalte1 [, spalte2, ...]] [ASC | DESC]] [HAVING gruppensuchbedingung] FOREIGN KEY
(spaltenname) REFERENCES (tabellenname)
Tabelle CREATE TABLE tabellenname ({spaltenname {domäne | datentyp} [spalteneinschränkung] [DEFAULT standardwert]
SQL
281
GLOSSAR
| tabelleneinschränkung }, ... ) ALTER TABLE tabellenname {ADD spaltenname datentyp} |{ALTER | CHANGE spaltenname_alt spaltenname_neu datentyp [(laenge)] |{DEFAULT wert | DROP DEFAULT} |{DROP spaltenname {RESTRICT | CASCADE} |{RENAME tabellenname_neu} |{ADD tabelleneinschränkung} |{DROP CONSTRAINT einschränkung {RESTRICT | CASCADE}} DROP TABLE [IF EXISTS] tabellenname Die beiden Schlüsselwörter RESTRICT und CASCADE modifizieren die Löschaktion, wenn weitere Objekte wie Sichten (views) und Einschränkungen für Tabellen oder weitere Objekte (assertion) vorhanden sind. In diesen Fällen verhindert RESTRICT das Löschen, um die Funktionsweise der anderen Objekte nicht zu beeinflussen, während CASCADE alle Objekte löscht. USER {ALTER | CREATE} USER benutzer IDENTIFIED {BY kennwort | EXTERNALLY} {[DEFAULT TABLESPACE tabellenbereich] |[TEMPORARY TABLESPACE tabellenbereich] [QUOTA {Integer [K|M] | UNLIMITED} ON tabellenbereich]} [PROFILE profil] [DEFAULT ROLE { rolle [, rolle] ... | ALL [EXCEPT rolle [, rolle] ...] | NONE}] REVOKE [GRANT OPTION FOR] recht [, ...] ON tabelle FROM {benutzer1 [, benutzer2, ...]} | PUBLIC {CASCADE | RESTRICT} DROP USER benutzer [CASCADE] UPDATE UPDATE tabellenname SET spalte1 = {wert | NULL | DEFAULT} [, spalte2 = {wert | NULL | DEFAULT}...] [WHERE suchbedingung [SELECT-Anweisung] ]
282
SQL