Einführung in SQL Udo Kelter 27.11.2013 Zusammenfassung dieses Lehrmoduls Dieses Lehrmodul führt in die elementaren Kommandos von SQL ein. Ein Schwerpunkt liegt auf den Möglichkeiten zur Formulierung von Abfragen. Weiter werden Möglichkeiten zur Definition und Änderung von Schemata gezeigt. Einleitend wird ein Abriß der historischen Entwicklung und der wichtigsten Varianten von SQL gegeben. Vorausgesetzte Lehrmodule: obligatorisch: – Datenverwaltungssysteme – Das relationale Datenbankmodell Stoffumfang in Vorlesungsdoppelstunden: 1 1.3 Einführung in SQL 2 Inhaltsverzeichnis 1 Einführung 3 2 Abfragen 2.1 Grundform . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Nachbildung der Operationen der relationalen Algebra in SQL 2.3 Gruppierungen und Aggregationen . . . . . . . . . . . . . . . 4 4 6 10 3 Änderungsoperationen 3.1 Erzeugen von Tupeln . . . . . . . . . . . . . . . . . . . . . . . 3.2 Löschen von Tupeln . . . . . . . . . . . . . . . . . . . . . . . 3.3 Ändern von Tupeln . . . . . . . . . . . . . . . . . . . . . . . . 14 14 15 17 4 Nullwerte 17 5 Schema-Operationen 5.1 Definition von Relationen . . . . . . . . . . . 5.1.1 Attributdefinitionen . . . . . . . . . . 5.1.2 Definition von Integritätsbedingungen 5.2 Änderung der Definition einer Relation . . . . 5.3 Sichten . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 20 20 21 24 25 Literatur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Glossar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25 26 26 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c 2013 Udo Kelter Stand: 27.11.2013 Dieser Text darf für nichtkommerzielle Nutzungen als Ganzes und unverändert in elektronischer oder gedruckter Form beliebig weitergegeben werden und in WWW-Seiten, CDs und Datenbanken aufgenommen werden. Jede andere Nutzung, insb. die Veränderung und Überführung in andere Formate, bedarf der expliziten Genehmigung. Die jeweils aktuellste Version ist über http://kltr.de erreichbar. Einführung in SQL 1 3 Einführung SQL ist die mit Abstand wichtigste Sprache für relationale Systeme. SQL umfaßt Kommandos zur Abfrage und Manipulation von Daten und Schemata, ferner diverse Administrationsfunktionen. Im Laufe der Zeit ist der Funktionsumfang von SQL ganz erheblich angewachsen, und es existieren mehrere Varianten der Standards. Historie. Der Ursprung von SQL geht auf das System/R zurück. System/R war ein Prototyp eines relationalen DBMS, das im Zeitraum von 1971 - 1981 bei der IBM für deren Mainframes entwickelt wurde. Der Name der Sprache war seinerzeit noch SEQUEL (“Structured English Query Language”). Später wurde sie umgetauft in “Structured Query Language”, heute liest man die Abkürzung SQL meist als “Standard Query Language”. 1981 war eine erste kommerzielle Implementierung von SQL durch die IBM verfügbar (SQL/Data System). Später folgten weitere Implementierungen, einerseits durch die IBM (DB2, QMF), andererseits durch mehrere konkurrierende Unternehmen, u.a. Oracle, Informix und Sybase. Aus Sicht von Anwendern ist eine Standardisierung der Sprache sehr wünschenswert, denn nur dann, wenn unterschiedliche Hersteller Implementierungen der gleichen Sprachdefinition anbieten, ist ein Wechsel zwischen konkurrierenden Produkten möglich und kann ein offener Markt entstehen. Dementsprechend wurden zunächst durch das ANSI bzw. später die ISO mehrere Versionen von SQL standardisiert. Die erste Version wurde unter den Namen SQL1 bzw. SQL86 im Jahre 1986 verabschiedet. 1989 folgte ein sogenanntes Addendum-1; der neue Standard wird auch als SQL89 bezeichnet. 1992 folgte die Version SQL2 bzw. SQL92. Die ersten Standards deckten nur einen Kern an Funktionen ab; Folge hiervon war, daß in der Praxis viele implementierungsspezifische Erweiterungen notwendig waren, so daß die unterschiedlichen Implementierungen doch nicht wirklich kompatibel bzw. austauschbar waren. Erst SQL92 hatte einen relativ vollständigen Funktionsumfang, dieser wurde allerdings von praktisch keinem Produkt exakt implementiert. c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 4 Ende der 90er Jahre ist eine neue Version namens SQL3 durch die ISO publiziert worden. Der Funktionsumfang von SQL3 kann in erster Näherung als unendlich bezeichnet werden, möglicherweise gibt es keine einzelne Person, die die Spezifikationen komplett gelesen hat. In diesem einführenden Lehrmodul beschränken wir uns natürlich auf die wichtigsten Funktionalitäten. Daß SQL sich als wichtigste relationale Sprache durchgesetzt hat, liegt übrigens weniger an seinen sprachlichen bzw. technischen Qualitäten, sondern eher an der Macht seiner Anbieter. In der Tat wurde SQL wegen diverser Mängel von bekannten Datenbankforschern heftig kritisiert. Dies hat jedoch nichts am Erfolg von SQL ändern können. SQL definiert sowohl eine “interaktive” Sprache (durch Kommandos wie CREATE TABLE oder SELECT ) als auch ein Programm-API (durch Kommandos wie DECLARE CURSOR , OPEN , FETCH usw.) Wir gehen in diesem Lehrmodul nur auf die interaktive Sprache ein. Bei den folgenden Beispielen verwenden wir Großbuchstaben für die Schlüsselworte (Kleinbuchstaben sind auch zulässig). 2 2.1 Abfragen Grundform Eine Abfrage in SQL hat folgende Grundstruktur: SELECT A1, ...., An FROM r1, ...., rm WHERE P Man fängt beim Lesen am besten mit der 2. Klausel, der FROM -Klausel an. Dort ist angegeben, welche Relationen die Grundlage der Abfrage bilden. In der Begriffswelt der relationalen Algebra bedeutet die Angabe mehrerer Relationen, daß deren Kreuzprodukt gebildet wird. Als nächstes sollte man die WHERE -Klausel lesen, sofern sie vorhanden ist (sie ist optional). Sie enthält ein Prädikat, das sich auf die Relationen beziehen muß, die in der FROM -Klausel angegeben sind. In der Begriffswelt der relationalen Algebra spezifiziert die WHERE -Klausel c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 5 eine Selektion. Wenn die WHERE -Klausel fehlt, wird nicht selektiert, der Vorgabewert für P ist sozusagen true . Die SELECT -Klausel sollte man zum Schluß lesen. Angegeben ist dort eine Liste von Attributen, die im Resultat auftreten. Die SELECT Klausel gibt also den Relationentyp des Ergebnisses an. Sie entspricht einer Projektion auf die angegebenen Attribute; entgegen ihrem Namen stellt sie keine Selektion dar1 . Durch Angabe von * werden alle Attribute der angegebenen Relationen ausgegeben, d.h. es findet keine echte Projektion statt. Übersetzt man die obige Grundform einer SQL-Abfrage also in die relationale Algebra, ergibt sich folgender Ausdruck: π A1,....,An (σP ( r1 × . . . × rm )) Mit anderen Worten kombiniert die Grundform einer SQL-Abfrage ein Kreuzprodukt, eine Selektion und eine Projektion. Duplikateliminierung. Der vorstehende Ausdruck in der relationalen Algebra ist in einem Punkt allerdings nicht äquivalent zur SQLAbfrage: bei der SQL-Abfrage werden Duplikate normalerweise nicht eliminiert. In der relationalen Algebra findet wegen des Rückgriffs auf die Mengenlehre immer implizit eine Duplikateliminierung statt. Wenn eine Duplikateliminierung gewünscht wird, muß zusätzlich das Schlüsselwort DISTINCT in der SELECT -Klausel angegeben werden. Die Duplikate werden nach der Projektion eliminiert. Wir verwenden i.f. die schon aus [RDBM] bekannten Tabellen kunden und lieferungen (s. Bild 1). Die Abfrage SELECT DISTINCT Wohnort FROM kunden gibt dann drei Tupel aus, und zwar gerade die drei verschiedenen auftretenden Ortsnamen. Ohne DISTINCT würden 5 Tupel ausgegeben. Es gibt gute Gründe, Duplikate nicht automatisch zu eliminieren. Die Eliminierung erfordert praktisch eine Sortierung, also eine 1 Die bisher erwähnten erheblichen linguistischen Mängel sollten schon ein gewisses Maß an Evidenz für die erwähnte massive Kritik an SQL liefern. c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 6 bei großen Datenmengen sehr aufwendige Operation. Ferner werden durch die Duplikateliminierung bestimmte Zähl- und Aggregationsoperatoren beeinflußt. Tabelle: kunden Kundennummer Kundenname 177177 Meier, Anne 177180 Büdenbender, Christa 185432 Stötzel, Gyula 167425 Schneider, Peter 171876 Litt, Michael Tabelle: lieferungen Datum Wert Kundennummer 00-08-12 2730.00 167425 00-08-14 427.50 167425 00-08-02 1233.00 171876 Wohnort Weidenau Siegen Siegen Netphen Siegen Lager Mitte Nord West Kreditlimit 2000.00 9000.00 4000.00 14000.00 0.00 Lieferadresse Bahnhofstr. 5 Luisenstr. 13 Bergstr. 33 Abbildung 1: Beispieltabellen 2.2 Nachbildung der Operationen der relationalen Algebra in SQL Wie wir oben schon gesehen haben, stellt die Grundform einer Abfrage in SQL eine Kombination mehrerer Operationen der relationalen Algebra dar. Umgekehrt können alle Operationen der relationalen Algebra wie in Tabelle 2 angegeben in SQL nachgebildet werden. Zu Tabelle 2 ist anzumerken: In der Selektion können die einfachen Vergleichsoperatoren = , <> (ungleich), < , > , <= und >= sowie diverse andere Vergleichsoperatoren verwendet werden. Bei den Vergleichen mit numerischen Werten können auch arithmetische Ausdrücke gebildet werden, bei Zeichenketten können in Konstanten folgende Sonderzeichen benutzt werden: für ein beliebiges Zeichen c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL σA=a (r) σA=B (r) πA1 ,...,An (r) r∪s r∩s r−s r×s r1s r[AΘB]s SELECT DISTINCT SELECT DISTINCT SELECT DISTINCT SELECT DISTINCT UNION SELECT DISTINCT SELECT DISTINCT INTERSECT SELECT DISTINCT SELECT DISTINCT EXCEPT SELECT DISTINCT SELECT DISTINCT SELECT DISTINCT SELECT DISTINCT 7 * FROM r WHERE A = a * FROM r WHERE A = B A1 , ..., An FROM r * FROM r * FROM s * FROM r * FROM s * FROM r * * * * FROM FROM FROM FROM s r, s r NATURAL JOIN s r, s WHERE r.A Θ s.B oder SELECT DISTINCT * FROM r JOIN s ON r.A Θ s.B Abbildung 2: Umsetzung von Operationen der relationalen Algebra in SQL % für mehrere beliebige Zeichen Als Vergleichsoperator ist dabei LIKE bzw. NOT LIKE zu benutzen. Elementare Vergleiche können mit den Booleschen Operatoren AND , OR und NOT verknüpft werden. Bei den Mengenoperatoren ist bei der in der Tabelle angegebenen Form Voraussetzung, daß beide Relationen die gleiche Zahl von Attributen haben und die Folge der Wertebereiche der Attribute gleich ist (die Namen der Attribute spielen dagegen keine Rolle). Es gibt Varianten der Mengenoperationen, bei denen die Felder nicht anhand ihrer Position, sondern ihres Namens verglichen werden. Anzugeben ist hier eine Sequenz von Attributnamen; beide Relationen werden dann zuerst auf diesen Relationentyp projiziert, danach wird die Mengenoperation ausgeführt. c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 8 Bei der Vereinigung werden Duplikate eliminiert; will man dies verhindern, muß man den Operator UNION ALL verwenden. Der Operator NATURAL JOIN für den natürlichen Verbund ist erst seit SQL2 verfügbar. Ansonsten kann der natürliche Verbund natürlich auch “von Hand” wie folgt nachgebildet werden: SELECT DISTINCT r.A1, .., r.Ak, B1, .., Bm, C1, .., Cn FROM r, s WHERE r.A1=s.A1 AND ... AND r.Ak=s.Ak wenn r die Attribute A1, ..., Ak, B1, ..., Bm und s die Attribute A1, ..., Ak, C1, ..., Cn hat. In der WHERE -Klausel werden die gemeinsamen Attribute durch lange Attributnamen identifiziert. Auch in der SELECT -Klausel müssen die langen Namen verwendet werden, obwohl die Werte in beiden Relationen gleich sind. Äußere Verbunde. Der linke, rechte bzw. beidseitige äußere Verbund kann in den folgenden Notationen aufgerufen werden: SELECT * FROM r LEFT JOIN s ON verbundbedingung SELECT * FROM r RIGHT JOIN s ON verbundbedingung SELECT * FROM r FULL JOIN s ON verbundbedingung Tupelvariablen. Schon bei der relationalen Algebra haben wir das Problem identifiziert, daß bei Abfragen, die ein Kreuzprodukt einer Relation mit sich selbst erfordern, die Attribute einer der Relationen oder diese Relation insgesamt umbenannt werden muß. SQL bietet als entsprechendes Konstrukt Tupelvariablen an. Als Beispiel betrachten wir die Suche nach denjenigen Kunden, die ein größeres Kreditlimit als der Kunde mit Nummer 185432 haben. Die Lösung ist: SELECT T.Kundenname FROM kunden S, kunden T WHERE S.Kundennummer = 185432 AND T.Kreditlimit > S.Kreditlimit c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 9 Umbenennung von ausgegebenen Attributen. In der SELECT Klausel kann jedes ausgegebene Attribut umbenannt werden. Beispiel: SELECT Kundenname AS Name, Wohnort AS Ort FROM kunden Genutzt werden kann diese Möglichkeit z.B. dazu, die Anzeige von Tabellen durch Standardanzeigewerkzeuge zu beeinflussen oder um ähnliche Tabellen in Mengenoperationen verarbeiten zu können. Aggregierte Werte (s. Abschnitt 2.3), die zunächst keinen Namen haben, können so benannt werden. Geschachtelte Abfragen. Die Abarbeitung einer SQL-Abfrage kann man sich so vorstellen, daß für jede Kombination der Tupel in den Eingaberelationen die Bedingung in der WHERE -Klausel geprüft wird; falls die Kombination der Eingabetupel die Bedingung erfüllt, werden die in der SELECT -Klausel angegebenen Attribute ausgegeben. Für eine bestimmte Kombination der Eingabetupel kann auch eine innere Abfrage gebildet werden wie im folgenden Beispiel: SELECT * FROM kunden WHERE Kreditlimit > 10000 AND Kundennummer IN (SELECT Kundennummer FROM lieferungen WHERE Betrag > 2000) Es werden hier diejenigen Kunden angezeigt, deren Kreditlimit größer als 10000 ist und die schon einmal eine Lieferung im Wert von über 2000 EUR bekommen haben. Der Operator IN prüft dabei, ob ein angegebenes Tupel in der angegebenen Relation enthalten ist. Das Attribut Kundennummer steht dabei für ein Tupel mit einem Attribut. Der Operator NOT IN steht für den Test auf Nicht-Enthaltensein. Es sind auch längere Tupel möglich, dann sind die Attribute in spitzen Klammern durch Komma getrennt aufzulisten, wie in folgendem Schema: c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 10 WHERE < A1, A2, ... > IN (SELECT A1, A2, .... FROM .... WHERE .... ) SOME- und ALL-Operatoren. Eine allgemeinere Version des Tests auf Enthaltensein stellen die SOME-Operatoren dar. Der Operator > SOME testet, ob der angegebene Wert größer als irgendein Tupel in der angegebenen Relation ist. Analog arbeiten weitere SOMEOperatoren für ≥, <, ≤, =, 6=. Analog zu den SOME-Operatoren gibt es entsprechende ALL-Operatoren, bei denen geprüft wird, ob alle Werte in der angegebenen Relation größer, kleiner usw. als der Vergleichswert sind. Sortierung der Ausgabetabelle. Mithilfe der ORDER BY -Klausel kann die Ausgabetabelle nach einem oder mehreren Attributen sortiert werden. Pro Attribut kann eine aufsteigende (Schlüsselwort ASC ; Vorgabe) oder fallende (Schlüsselwort DESC ) Sortierreihenfolge gewählt werden. Beispiel: SELECT * FROM lieferungen ORDER BY Kundennummer ASC, Datum DESC Die Attribute, nach denen sortiert wird, müssen ausgegebene Attribute gemäß der SELECT -Klausel sein. 2.3 Gruppierungen und Aggregationen Vielfach will man die Tupel einer Relation anhand bestimmter Attributwerte gruppieren und die so entstehenden Gruppen zählen oder bestimmte Attributwerte innerhalb der Gruppe aufsummieren. Hierzu ein Beispiel: wir möchten für unsere Beispieldatenbank für jeden Kunden folgendes wissen: – die Anzahl der Lieferungen, die an ihn gegangen sind, und – den Gesamtwert der Lieferungen Gesucht ist also eine Abfrage, die eine Relation mit drei Spalten liefert: den Kundennamen (oder die Nummer) und die beiden vorstehenden Angaben. c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 11 Die Zahl der Lieferungen an einen bestimmten Kunden ist gerade die Zahl der lieferungen-Tupel, die sich auf diesen Kunden beziehen. Wenn X die Kundennummer eines Kunden ist, dann könnten wir diese Tupelmenge mit der Abfrage SELECT * FROM lieferungen WHERE Kundennummer = X bestimmen. Man könnte nun auf die Idee kommen, irgendwie in einer Schleife alle auftretenden Kundennummern zu durchlaufen, jedesmal diese Abfrage zu starten und die Ergebnismenge zu zählen bzw. die Werte im Attribut Betrag aufzusummieren und die Ergebnistabelle zeilenweisen irgendwie zusammenzusetzen. Das ist eine typische prodedurale Denkweise; würden die Daten als Java-Laufzeitobjekte vorliegen und müßten wir ein imperatives Programm schreiben, das die gewünschten Angaben berechnet, wäre diese Denkweise durchaus in Ordnung. In relationalen Sprachen ist diese Denkweise ein typischer Anfängerfehler und zum Scheitern verurteilt: relationale Sprachen sind nichtprozedural, Schleifen sind nicht vorgesehen und werden sinngemäß durch andere Konstrukte ersetzt. In der Tat können die oben erwähnten Zählungen und Summierungen überhaupt nicht mit den Mitteln der relationalen Algebra oder äquivalenter Sprachkonstrukte in SQL realisiert werden. SQL bietet aber mit der GROUP BY-Klausel und weiteren Sprachkonstrukten eine Lösungsmöglichkeit. Unsere Aufgabe können wir in SQL wie folgt lösen: SELECT Kundennummer, COUNT(*), SUM(Betrag) FROM lieferungen GROUP BY Kundennummer Die GROUP BY-Klausel verändert die Bedeutung der SELECTAnweisung wie folgt: 1. Zunächst werden wie üblich Kreuzprodukte bzw. Verbunde gebildet, sofern mehrere Relationen in der FROM-Klausel angegeben sind, und die resultierenden Tupel gemäß der WHERE-Klausel, sofern vorhanden, selektiert. 2. Die verbleibenden Tupel werden in Gruppen eingeteilt. Das Attribut, das in der GROUP BY-Klausel angegeben wird, wird i.f. Grupc 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 12 pierungsattribut genannt. Für jeden Wert X, der im Gruppierungsattribut auftritt, wird eine Gruppe gebildet. Zu dieser Gruppe gehören alle Tupel, die den Wert X im Gruppierungsattribut haben. In unserem Beispiel wird also für jede auftretende Kundennummer eine Gruppe gebildet, die gerade die Lieferungstupel mit dieser Kundennummer enthält. Wenn mehrere Gruppierungsattribute angegeben werden, wird analog zu jeder Kombination von Werten in den Gruppierungsattributen eine Gruppe gebildet. 3. Für jede Gruppe (und nicht etwa für jedes Eingabetupel!) wird genau ein Tupel ausgegeben. Als Ausgabeattribute bzw. -Werte sind erlaubt: – Gruppierungsattribute - deren Wert ist nach Konstruktion bei allen Tupeln in der Gruppe gleich; Attribute, die keine Gruppierungsattribute sind, sind dagegen nicht zulässig, denn deren Wert kann in der Gruppe verschieden sein, d.h. es ist unklar, welcher der auftretenden Werte ausgegeben werden soll; – Aggregationsoperatoren Die Liste der Aggregationsoperatoren ist: COUNT: Anzahl AVG: Durchschnitt MIN: Minimum MAX: Maximum SUM: Summe Bei den numerischen Aggregationsoperatoren (alle außer COUNT) ist als Argument ein numerisches Attribut anzugeben. In die angegebene Operation werden alle Attributwerte einbezogen, die nicht NULL sind. Der Operator COUNT zählt die Tupel; als Argument muß entweder ein Attribut angegeben werden, dann zählt COUNT die Tupel, bei denen dieses Attribut nicht NULL ist, oder * , dann zählt COUNT alle Tupel. In unserer obigen Musterlösung erzeugt also COUNT (*) die Zahl der Lieferungen eines Kunden und SUM(Betrag) den Gesamtwert aller Lieferungen. c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 13 Sofern die GROUP BY -Klausel fehlt und trotzdem in der SELECTKlausel ein Aggregationsoperator benutzt wird, bildet die ganze Relation eine einzige Gruppe. So kann z.B. durch die Abfrage SELECT count(*) FROM r die Zahl der Tupel der Relation r gezählt werden. Da pro Gruppe nur ein Tupel ausgegeben wird, wird hier nur eine einzige Zahl ausgegeben. Aggregation und Verbunde. Wenn wir im obigen Beispiel nicht nur die Kundennummer, sondern auch die Kundennamen ausgeben wollen, müssen wir einen Verbund mit der Relation kunden bilden und die Lösung wie folgt modifizieren: SELECT lieferungen.Kundennummer, Kundenname, COUNT(*), SUM(Betrag) FROM lieferungen NATURAL JOIN kunden GROUP BY lieferungen.Kundennummer, Kundenname Zunächst unmotiviert wirkt hier, daß auch das Attribut Kundenname als Gruppierungsattribut angegeben wird. Die Gruppen werden durch dieses zusätzliche Attribut nicht kleiner, weil innerhalb jeder Gruppe der Kundenname gleich ist. Dieses Wissen fehlt dem SQL-Prozessor aber im allgemeinen Fall, daher müssen alle auszugebenden Attribute in der GROUP BY -Klausel angegeben werden. Es sei noch darauf hingewiesen, daß die obige Musterlösung für diejenigen Kunden, die noch keine Lieferung bekommen haben, gar kein Tupel enthält, also auch kein Tupel, das in der 3. und 4. Spalte eine Null enthält. Sind derartige Ausgabetupel für die “leeren Gruppen” gewünscht, muß der natürliche Verbund durch einen äußeren Verbund (im vorliegenden Fall reicht der rechte äußere Verbund) ersetzt werden, ferner COUNT(*) durch COUNT(Kundenname) , damit die Tupel, die durch den äußeren Verbund mit Nullerwerten erzeugt werden, nicht mitgezählt werden. Bedingungen mit aggregierten Werten. Angenommen, wir suchen die Kunden, die schon im Wert von über 10.000 EUR gekauft haben. Die Summe der bisherigen Käufe können wir zwar in der SELECT c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 14 Klausel mit SUM(Betrag) ausgeben, nicht hingegen in der WHERE Klausel für Selektionsbedingungen ausnutzen. Wie schon erwähnt wird die WHERE -Klausel vor der Gruppierung ausgewertet; Aggregationsoperatoren können daher in der WHERE -Klausel nie auftreten. Um die ausgegebenen Tupel, die jeweils einer Gruppe entsprechen, zu selektieren (und nicht etwa die Eingabetupel), bietet SQL die HAVING -Klausel an: SELECT FROM GROUP BY HAVING Kundennummer, SUM(Betrag) lieferungen Kundennummer SUM(Betrag) > 10000 Schachtelungen von Aggregationsoperatoren. Diese sind nicht erlaubt, stattdessen muß auf eine Ersatzkonstruktion ausgewichen werden. Wenn wir z.B. den oder die Kunden mit dem maximalen Gesamtumsatz suchen, können wir nicht HAVING SUM(Betrag) = MAX(SUM(Betrag)) als Bedingung angeben. Stattdessen muß eine eingeschachtelte Abfrage benutzt werden: SELECT Kundennummer, SUM(Betrag) FROM lieferungen GROUP BY Kundennummer HAVING SUM(Betrag) >= ALL (SELECT SUM(Betrag) FROM lieferungen GROUP BY Kundennummer) 3 3.1 Änderungsoperationen Erzeugen von Tupeln Tupel können mit dem INSERT-Kommando erzeugt werden, z.B.: INSERT INTO kunden VALUES (131415, "Groll, Renate", "Bamberg", 12000) c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 15 In der VALUES-Klausel müssen die Attributwerte des zu erzeugenden Tupels in der Reihenfolge gemäß der Definition des Relationentyps angeordnet sein. Alternativ kann die Reihenfolge der Attribute auch explizit bestimmt werden: INSERT INTO kunden (Kundenname, Wohnort, Kundennummer, Kreditlimit) VALUES ("Groll, Renate", "Bamberg", 131415, 12000 ) Es ist auch möglich, nur eine Teilmenge der Attribute anzugeben. Für die fehlenden Attribute werden Nullwerte oder Vorgabewerte eingesetzt; dies kann bei der Definition des Relationentyps festgelegt werden. Eine Variante des INSERT-Kommandos ermöglicht es, Tupel, die aus anderen Relationen als Ergebnis einer Abfrage bestimmt worden sind, einzufügen, also zu kopieren. Beispiel: INSERT INTO lieferungen (Kundennummer, Lieferadresse, Betrag, Datum) SELECT Kundennummer, Wohnort, 100, 24.12.2000 FROM kunden WHERE Kreditlimit > 10000 Dieses Kommando fügt in die Relation lieferungen für alle Kunden, die ein Kreditlimit von über 10000 EUR haben, eine Weihnachtslieferung im Wert von 100 EUR ein. 3.2 Löschen von Tupeln Die Grundform des Löschkommandos ist DELETE FROM r WHERE B Dabei ist B eine Bedingung wie bei der SELECT-Anweisung. Der Effekt der Anweisung besteht darin, daß die Tupel, die die Bedingung B erfüllen, in der Relation r gelöscht werden. Wenn die WHERE-Klausel fehlt, werden alle Tupel gelöscht, die anschließend leere Relation besteht weiter. In der FROM-Klausel kann immer nur eine Relation angec 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 16 geben werden. Wenn man in mehreren Relationen Tupel löschen will, muß man pro Relation ein eigenes Löschkommando ausführen. Einige Beispiele: – Löschen des Kunden mit Kundennummer 131415: DELETE FROM kunden WHERE Kundennummer = 131415 – Löschen aller Lieferungen an den Kunden mit Kundennummer 131415 DELETE FROM lieferungen WHERE Kundennummer = 131415 – Löschen aller Kunden, die noch keine Lieferung bekommen haben DELETE FROM kunden WHERE 0 = (SELECT COUNT (*) FROM lieferungen WHERE kunden.Kundennummer = lieferungen.Kundennummer ) Probleme können bei eingeschachtelten SELECT-Anweisungen auftreten. Betrachten wir hierzu folgendes Beispiel: DELETE FROM kunden WHERE Kreditlimit < (SELECT AVG(Kreditlimit) FROM kunden ) Dieses Kommando soll diejenigen Kunden löschen, deren Kreditlimit unter dem durchschnittlichen Kreditlimit liegt. Wenn man nun alle Tupel der Relation der Reihe nach durchläuft und jedesmal die innere SELECT-Anweisung neu berechnet, werden zu viele Tupel gelöscht: wenn die ersten Tupel mit kleinem Kreditlimit gelöscht worden sind, steigt das durchschnittliche Kreditlimit an, so daß bei späteren Auswertungen der Löschbedingung ein höherer Vergleichswert benutzt wird. Eine Lösung des Problems kann darin bestehen, Tupel während der Abarbeitung des DELETE-Kommandos nicht wirklich zu löschen, c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 17 sondern nur als zu löschend zu markieren und die tatsächliche Löschung erst am Ende, also nach Auswertung aller inneren SELECTAnweisungen, vorzunehmen. Eine andere, einfachere Lösung besteht darin, solche Löschkommandos gar nicht zuzulassen. 3.3 Ändern von Tupeln Mit Hilfe des UPDATE-Kommandos kann man einzelne Attributwerte ändern. Die restlichen Attribute der betroffenen Tupel bleiben unverändert. Als Beispiel betrachten wir die Erhöhung der Kreditlimits aller Siegener Kunden um 50 %: UPDATE kunden SET Kreditlimit = Kreditlimit * 1.5 WHERE Wohnort = "Siegen" In der WHERE-Klausel sind eingeschachtelte SELECT-Anweisungen erlaubt, allerdings dürfen sich diese nicht auf die Relation, die gerade geändert wird, beziehen. 4 Nullwerte Wenn man beim Einfügen von Tupeln nur eine Teilmenge aller Attribute angibt und bei den übrigen Attributen keine Vorgabewerte definiert sind, erhalten diese als Wert den Nullwert. Das gleiche passiert, wenn Tupel über Sichten, die als Projektion definiert sind (s. Abschnitt 5.3), eingefügt werden. Neben diesen technischen Gründen ist eine weitere Ursache für Nullwerte, daß die tatsächlichen Werte (noch) nicht bekannt oder anwendbar sind. Betrachten wir hierzu das Attribut Kreditlimit der Relation kunden: – Manche unserer Kunden sind Laufkundschaft; sie bezahlen immer bar. Das Attribut Kreditlimit ist für sie sinnlos. – Für Kunden, die beantragen, bei uns auf Kredit kaufen zu können, holen wir zuerst eine Bankauskunft ein. Solange die Bankauskunft nicht vorliegt, kann das Kreditlimit nicht festgelegt werden. Angenommen, wir hätten ein weiteres Attribut DatumBankauskunft, c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 18 das das Datum der Bankauskunft enthält. Solange hier kein Datum steht, wäre das Attribut Kreditlimit nicht anwendbar. – Selbst nach Vorliegen der (positiven) Bankauskunft muß erst der Chef das Kreditlimit konkret festlegen; solange er dies nicht getan hat, ist der Kunde zwar kreditwürdig, aber sein Kreditlimit noch unbekannt. Man könnte in allen vorstehenden Fällen den Wert des Attributs Kreditlimit auf 0,00 setzen, allerdings wären die drei vorstehenden Fälle und der vierte Fall, daß bei dem Kunden trotz positiver Bankauskunft das Kreditlimit vorerst auf 0,00 gesetzt wird, nicht unterscheidbar. Um die vorstehenden Fälle sauber unterscheiden zu können, bräuchte man eigentlich drei verschiedene Nullwerte. Eigentlich müßte man eher von Nichtanwendbarkeits- oder Unbekannt-Werten (oder -Anzeigen) reden, dies sind keine wirklichen Werte aus dem Wertebereich der Attribute. SQL unterstützt genau einen Nullwert. Man muß somit alle eigentlich unterschiedlichen Nichtanwendbarkeits- oder Unbekannt-Werte auf diesen einen Nullwert abbilden, verliert also Information. Nullwerte sind daher und aus anderen Gründen problematisch. Der Nullwert kann mit dem Schlüsselwort NULL explizit gesetzt werden. Beispiel: INSERT INTO kunden VALUES (131415, "Groll, Renate", "Bamberg", NULL) Wenn zwei Tupel in einem Attribut beide den Wert NULL haben, bedeutet das nicht, daß beide den gleichen Wert in diesem Attribut haben. Der Wert ist in diesem Fall schlicht unbekannt, mit sehr hoher Wahrscheinlichkeit aber verschieden. Das gleiche gilt bei einem Vergleich mit einer Konstanten. Das Resultat eines Vergleichs mit einem Nullwert wird daher so definiert, daß immer ein negatives Ergebnis geliefert wird. Eigentlich ist das falsch, eigentlich kann man das Resultat gar nicht exakt bestimmen, weil man den oder die Vergleichswerte gar nicht kennt. Die negativen Vergleichsresultate führen zu unerwarteten Effekten. Bei der folgenden Abfrage c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 19 SELECT * FROM r WHERE A > 0 OR A <= 0 ist die Bedingung in der WHERE-Klausel mathematisch gesehen eine Tautologie, und man könnte glauben, es würde somit die gesamte Relation r zurückgeliefert. Dies trifft nicht zu, die Tupel, bei denen der Wert von A NULL ist, fehlen im Ergebnis. Ob der Nullwert vorliegt, kann wie folgt getestet werden: SELECT * FROM r WHERE A IS NULL Analog testet IS NOT NULL , ob kein Nullwert vorliegt. Bei den Aggregationsoperatoren außer COUNT zählen Tupel, die bei dem relevanten Attribut den Wert NULL haben, überhaupt nicht mit, d.h. der aggregierte Wert wird auf Basis der übrigen Tupel gebildet. Der wirkliche aggregierte Wert ist natürlich unbekannt, der angegebene ist wahrscheinlich der richtige oder er liegt nahe beim richtigen Wert. Wenn man sich dieses Sachverhalts oder der Anwesenheit der Nullwerte nicht bewußt ist, können die ausgegebenen Zahlen falsch interpretiert werden. 5 Schema-Operationen Ein Schema in SQL umfaßt Angaben aus mehreren Bereichen, neben der Definition von Relationen und Sichten z.B. auch Angaben zur Autorisierung. Wir gehen hier nur auf die Definition von Relationen und Sichten ein. Eine Relation wird in SQL als Tabelle (table) bezeichnet, ein Attribut als (Tabellen-) Spalte (column) und ein Tupel als Zeile (row). In einer Datenbank kann es mehrere Schemata geben; diese werden im Katalog verwaltet. Bestimmte Teile der Schemata, z.B. Bereichsdefinitionen, können in mehreren Schemata eines Katalogs wiederverwendet werden. Bei den folgenden Syntaxdefinitionen verwenden wir Großbuchstaben für die Schlüsselworte (Kleinschreibung ist auch zulässig) und Kleinbuchstaben für die nichtterminalen Bezeichner. c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 5.1 20 Definition von Relationen Tabellen werden mit dem Kommando CREATE TABLE erzeugt. Vereinfacht (ohne Berücksichtigung diverser Optionen) hat es folgenden Aufbau: CREATE TABLE table-name ( list-of-table-elements ) Als Beispiel betrachten wir die Definition unserer Relation kunden: CREATE TABLE kunden ( Kundennummer DECIMAL(6) NOT NULL, Kundenname CHAR(20), Wohnort CHAR(15), Kreditlimit DECIMAL(9,2), PRIMARY KEY (Kundennummer) ) Ein Element der Tabellendefinition ist eine Attributdefinition oder eine Integritätsbedingung. Die Definition unserer Relation kunden enthält vier Attributdefinitionen und eine Integritätsbedingung. Die einzelnen Elemente werden durch ein Komma voneinander getrennt. 5.1.1 Attributdefinitionen Im obigen Beispiel ist zu jedem Attributnamen ein Wertebereich angegeben. Die Denkwelt für diese Wertebereichs- bzw. Typangaben orientiert sich eher an Programmiersprachen wie COBOL als an Pascal oder C. Dies ist kein Zufall, da diese Sprachen bei betrieblichen Anwendungen als Gastsprachen nach wie vor dominieren. Als Datentypen stehen u.a. zur Verfügung: CHAR(l ) oder CHARACTER (l ): Zeichenkette mit der festen Länge l VARCHAR(l ) oder CHARACTER VARYING (l ): Zeichenkette mit einer variablen Länge, maximal aber l Zeichen DEC(l,m) oder DECIMAL (l,m): Dezimalzahlen mit l Stellen vor dem Komma und m Stellen hinter dem Komma c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 21 INT oder INTEGER, SMALLINT FLOAT, REAL, DOUBLE PRECISION: diverse Fließkomma-Formate DATE, TIME, INTERVAL u.a.: diverse Formate für Datum und Uhrzeit Die Angabe NOT NULL schließt Nullwerte bei diesem Attribut aus. Durch eine Angabe DEFAULT wert kann ein Vorgabewert spezifiziert werden. Als Vorgabewert kann auch NULL spezifiziert werden. Ein einzelner Wertebereich kann auch explizit mit einem Namen versehen werden und dann in verschiedenen Relationen benutzt werden. Als Beispiel führen wir dies für das Attribut Kundennummer durch: CREATE DOMAIN Kundennummertyp AS DECIMAL(6) NOT NULL; CREATE TABLE kunden ( Kundennummer Kundennummertyp, ..... ) Die Definition eines Attributs innerhalb der Definition einer Tabelle hat insg. folgende Struktur: column-name { data-type | domain } [ DEFAULT { wert | NULL } ] [ list-of-column-constraints ] 5.1.2 Definition von Integritätsbedingungen SQL bietet sehr umfangreiche Konzepte zur Integritätssicherung. Wir stellen hier nur Möglichkeiten zur Definition von Schlüsseln vor. Identifizierungsschlüssel. gabe Eine Attributmenge kann durch die An- UNIQUE ( list-of-column-names ) als Identifizierungsschlüssel definiert werden. Sofern diese Attributmenge einelementig ist, kann die Schlüsseleigenschaft auch direkt bei c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 22 der Attributdefinition durch das Schlüsselwort UNIQUE angegeben werden. Sofern ein Identifizierungsschlüssel angegeben ist, muß auch ein Primärschlüssel angegeben werden. Nullwerte sind in Identifizierungsschlüsseln erlaubt. Es kann sogar mehrere Tupel geben, die den Wert NULL in einem oder mehreren Attributen des Identifizierungsschlüssels haben. Es wird hier unterstellt, daß die wirklichen Werte alle verschieden sind. Primärschlüssel. Eine Attributmenge kann durch die Angabe PRIMARY KEY ( list-of-column-names ) als Primärschlüssel definiert werden; implizit wird die Attributmenge damit gleichzeitig als Identifizierungsschlüssel definiert. Es kann mehrere Identifizierungsschlüssel, aber nur einen Primärschlüssel geben (vgl. [RDBM]). Wie schon erwähnt ist die Spezifikation eines Primärschlüssels eine Frage, die in der 3-Ebenen-Schema-Architektur dem internen Schema zuzuordnen ist. M.a.W. werden hier Angaben zum konzeptuellen und zum internen Schema der Datenbank vermengt. In den Attributen eines Primärschlüssels sind Nullwerte nicht erlaubt. Fremdschlüssel. Ein Fremdschlüssel wird wie folgt angegeben: FOREIGN KEY ( list-of-column-names ) REFERENCES table-name [ ( list-of-column-names ) ] In unserer Relation lieferungen war z.B. das Attribut Kundennummer ein Fremdschlüssel für das Attribut Kundennummer in der Relation kunden. In SQL wird dies wie folgt notiert: CREATE TABLE lieferungen ( Kundennummer Kundennummertyp, ..... FOREIGN KEY ( Kundennummer ) REFERENCES kunden; ); c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 23 Die Liste der Attributnamen hinter dem Schlüsselwort REFERENCES braucht nur dann angegeben zu werden, wenn dort Attribute mit anderen Namen referenziert werden sollen. Bei einer einelementigen Attributmenge kann die Fremdschlüsseleigenschaft auch innerhalb der Attributdefinition angegeben werden, z.B.: CREATE TABLE lieferungen ( Kundennummer Kundennummertyp REFERENCES kunden, ..... ); Nach dem Einrichten eines Fremdschlüssels verhindert das DBMS “defekte Referenzen”, also Wertekombinationen in den Fremdschlüsselattributen in der referenzierenden Relation, die in der referenzierten Relation nicht auftreten. Eine Einfüge- oder Änderungsoperation in der referenzierenden Relation, die zu einer defekten Referenz führen würde, wird vom DBMS mit einer Fehlermeldung abgebrochen. Defekte Referenzen können auch durch Löschungen oder Änderungen in der referenzierten Relation entstehen; hier sind verschiedene Reaktionen sinnvoll und durch zusätzliche Optionen in der FOREIGN KEY-Klausel wählbar. Bei einer Löschung gibt es folgende Optionen: 1. NO ACTION: Der Löschversuch wird abgelehnt, das Tupel nicht gelöscht. Dies ist die Voreinstellung. Bei allen folgenden Alternativen wird das zu löschende Tupel tatsächlich gelöscht. 2. CASCADE: Alle Tupel in der referenzierenden Tabelle, die das gelöschte Tupel referenzieren, werden ebenfalls gelöscht. Würde man also in der Relation kunden ein Kundentupel löschen, würden implizit auch alle Lieferungstupel für diesen Kunden in der Relation lieferungen gelöscht. Die implizit gelöschten Tupel könnten ihrerseits Ziel von Referenzen aus einer dritten Relation sein. Beispielsweise könnten wir eine weitere Relation haben, die zu jeder Lieferung die einzelnen gelieferten Posten angibt und die einen Fremdschlüssel auf ein zusätzliches Attribut Lieferscheinnummer in lieferungen enthält. Wenn dieser Fremdschlüssel ebenfalls mit der Option CASCADE anc 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 24 gegeben wäre, würden beim Löschen eines Kunden auch alle Lieferposten aller seiner Lieferungen gelöscht werden. 3. SET NULL: In der referenzierenden Tabelle werden die entstehenden defekten Referenzen auf NULL gesetzt. Diese Option ist nur zulässig, wenn die Attribute des Fremdschlüssels nicht als NOT NULL definiert sind. 4. SET DEFAULT: In der referenzierenden Tabelle werden die Attribute in den entstehenden defekten Referenzen auf ihren jeweiligen Vorgabewert gesetzt. Diese Option ist nur zulässig, wenn für diese Attribute Vorgabewerte definiert worden sind. Mit dem Schlüsselwort ON DELETE kann das gewünschte Verhalten bei Löschungen angegeben werden. Beispiel: CREATE TABLE lieferungen ( Kundennummer Kundennummertyp, ..... FOREIGN KEY ( Kundennummer ) REFERENCES kunden ON DELETE CASCADE ); Das Verhalten bei Änderungen muß separat angegeben werden, und zwar mit dem Schlüsselwort ON UPDATE. Die wählbaren Alternativen sind die gleichen wie bei Löschungen, allerdings bekommt CASCADE eine andere Bedeutung: Alle Tupel in der referenzierenden Tabelle, die das geänderte Tupel referenzieren, werden passend mitgeändert, so daß die damit ausgedrückte Beziehung erhalten bleibt. 5.2 Änderung der Definition einer Relation Nachdem eine Relation einmal erzeugt und mit Daten gefüllt worden ist, können auch noch nachträglich Details der Definition geändert werden. Hierzu dient das ALTER -Kommando: ALTER TABLE table-name { ADD [column] column-name data-type | ALTER [column] column-name { DROP DEFAULT | SET default-definition } c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 25 | ADD [CONSTRAINT constraint-name] { UNIQUE ( list-of-column-names ) | PRIMARY KEY ( list-of-column-names ) | FOREIGN KEY ( list-of-column-names ) REFERENCES table-name [ ( .... ) ] | ..... } | DROP CONSTRAINT constraint-name } Mit dem DROP -Kommando können Domänen, Tabellen, Sichten und ganze Schemata gelöscht werden. 5.3 Sichten Eine Sicht (view) (s. [DVS]) ist eine virtuelle Tabelle, die aus anderen Tabellen abgeleitet ist. Tabellen, die keine Sichten sind, nennen wir auch Basistabellen. Im Gegensatz zu einer Basistabelle ist eine Sicht nicht physisch gespeichert, sondern wird bei jeder Benutzung dynamisch berechnet. Definiert wird eine Sicht mit dem CREATE VIEW Kommando: CREATE VIEW view-name [ ( list-of-column-names ) ] AS select-expression Die Sicht wird hauptsächlich durch eine Abfrage (die SELECT-expression ) bestimmt. In dieser Abfrage können wiederum Sichten in der FROM-Klausel benutzt werden. Literatur [DVS] Kelter, U.: Lehrmodul “Datenverwaltungssysteme”; 2005 [RDBM] Kelter, U.: Lehrmodul “Das relationale Datenbankmodell”; 2002 c 2013 Udo Kelter Stand: 27.11.2013 Einführung in SQL 26 Glossar Aggregation (im Kontext von SQL): Ausgabe auf Basis von Gruppen von Tupeln; je eine Gruppe bilden die Tupel, die in den sog. Gruppierungsattributen gleiche Werte haben; ausgegeben wird pro Gruppe nur ein Tupel, dessen Attribute können sein: a. Gruppierungsattribute, b. über die Gruppe aggregierte Werte, insb. Zählungen und für ein bestimmtes Attribut Summe, Minimum, Maximum und Durchschnitt der Werte, die in der Gruppe auftreten Katalog: Teil der Datenbank, in dem die Schemata repräsentiert werden Nullwert: spezieller Wert eines Attributs, der ausdrückt, daß der Wert nicht angegeben werden kann, z.B. weil der wirkliche Wert (noch) nicht bekannt ist, das Attribut bei diesem Tupel nicht sinnvoll anwendbar ist oder sonstige Gründe vorliegen Sicht (im Kontext von SQL) (view ): virtuelle Tabelle, die mittels einer Abfrage definiert wird SQL: von der ISO und anderen Standardisierungsinstitutionen in mehreren Varianten definierte Sprache für relationale Datenbanken c 2013 Udo Kelter Stand: 27.11.2013 Index Aggregation, 10, 26 Bedingungen, 13 COUNT, 11 CREATE DOMAIN-Kommando, 21 CREATE TABLE-Kommando, 20 CREATE VIEW-Kommando, 25 DATE, 21 DEC, 20 DEFAULT, 21 DELETE-Kommando, 15 DISTINCT, 5 DROP-Kommando, 25 FLOAT, 21 FOREIGN KEY, 22 FROM-Klausel, 4 GROUP BY-Klausel, 11 HAVING-Klausel, 14 INSERT-Kommando, 14 INT, 21 IS NULL, 19 LIKE, 7 MAX, 11 MIN, 11 NATURAL JOIN, 8 NO ACTION, 23 NOT, 7, 9, 19 NULL, 18 ON DELETE, 24 ON UPDATE, 24 ORDER BY, 10 PRIMARY KEY, 22 SELECT-Klausel, 5 SET DEFAULT, 24 SET NULL, 24 SOME-Operatoren, 10 SUM, 11 UNIQUE, 21 UPDATE-Kommando, 17 VALUES-Klausel, 14 Basistabelle, 25 DB2, 3 Duplikate, 5 Gruppierung, 10, 12 Katalog, 19, 26 Kreuzprodukt, 4 Nullwert, 15, 17, 26 Aggregationsoperatoren, 19 Vergleich, 18 Projektion, 5 QMF, 3 relationale Algebra, 6 Schema, 19 Änderung, 24 Schlüssel Fremdschlüssel, 22 Identifizierungsschlüssel, 21 Primärschlüssel, 22 Selektion, 5, 6 SEQUEL, 3 Sicht, 25, 26 SQL, 3, 26 ALL-Operatoren, 10 ALTER TABLE-Kommando, 24 AVG, 11 CASCADE, 23 CHAR, 20 27 Einführung in SQL 28 VARCHAR, 20 WHERE-Klausel, 4 API, 4 Attributdefinition, 20 geschachtelte Abfragen, 9, 14, 16, 17 Integritätsbedingungen, 21 interaktive Sprache, 4 Tupelvariable, 8 SQL/Data System, 3 SQL1, 3 SQL2, 3 SQL3, 4 SQL86, 3 SQL92, 3 Verbund, 8 view, 25 c 2013 Udo Kelter Stand: 27.11.2013