Grundlagen von SQL Prof. Dr. Stefan Böcker – SQL: Grundlagen von SQL Grundlegende Eigenschaften von SQL ! Natürlichsprachlich ! Deklarativ ! Mengenorientiert Prof. Dr. Stefan Böcker – SQL: Grundlagen von SQL Abstraktion In SQL-Anweisungen steht die Frage „Was?“ und nicht die Frage „Wie?“ im Mittelpunkt. So ist auch ein hohes Maß an Datenunabhängigkeit gesichert. SQL-Anweisungen können vom RDBMS ohne Eingriff des Anwenders ausgeführt werden: „... it is likely that more SQL programs are executed in parallel than in any other programming language. However, most SQL programmers do not write explicitly parallel code ...“ Prof. Dr. Stefan Böcker – SQL: Grundlagen von SQL Abschlossenheit Die select-Anweisung ist abgeschlossen: Der Operand und das Ergebnis sind beide Tabellen. Somit ist auch der folgende Code syntaktisch korrekt create table personen( id int generated always as identity primary key, name varchar(20), freund char(1) check (freund in ('J','N')) ); select name from (select id, name from personen where freund='J‘) Prof. Dr. Stefan Böcker – SQL: Grundlagen von SQL Die Bestandteile von SQL Data Data Definition Language (DDL): Anweisungen, die mit create, drop und alter eingeleitet werden. Data Control Language (DCL): Die Anweisungen grant und revoke vergeben und entziehen Rechte Data Manipulation Language (DML): Die Anweisungen update, delete, insert und select. Prof. Dr. Stefan Böcker – SQL: Grundlagen von SQL Die update-Anweisung update personen set name = upper(name) where freund = 'J' Prof. Dr. Stefan Böcker – SQL: Grundlagen von SQL Die delete-Anweisung delete from personen where freund!='J' Prof. Dr. Stefan Böcker – SQL: Grundlagen von SQL Die insert-Anweisung insert into personen(name, freund) values ('Tick', 'N'),('Trick', 'N'),('Track', 'N‘) insert into freunde select id, name from personen where freund ='J‘; Prof. Dr. Stefan Böcker – SQL: Grundlagen von SQL Die insert-Anweisung Die letzte Variante ermöglicht eine rasche Erzeugung von Massendaten: create table big( id int generated always as identity primary key, name varchar(20) ); insert into big(name) values('Donald'); Was passiert, wenn die folgende Anweisung mehrfach ausgeführt wird? insert into big(name) select b1.name from big b1, big b2 Prof. Dr. Stefan Böcker – SQL: Grundlagen von SQL Codds 7. Regel: Mengenorientiertes Einfügen, Ändern und Löschen von Daten Ein RDBMS muss mengenorientierte Operationen zum Einfügen, Ändern und Löschen von Daten zur Verfügung stellen. Das bedeutet, dass das RDBMS die Daten der Datenbank in Form von Mengen bereitstellt, die aus mehreren Datensätzen aus verschiedenen Tabellen zusammengesetzt sind. Insbesondere ermöglicht ein RDBMS es, derartige Mengen zu ändern, zu löschen oder einzufügen. Prof. Dr. Stefan Böcker – SQL: Grundlagen von SQL Der Standard SQL ist über die International Standards Organisation (ISO) standardisiert. Die Hersteller orientieren sich an diesem Standard. Überraschend ist es, dass es namhafte RDBMS gibt, bei denen trotzdem ! Blockkommentare unbekannt sind; ! Schlüsselworte groß geschrieben werden müssen; ! Primärschlüssel nur in Verbindung mit einem expliziten not null definiert werden können. Prof. Dr. Stefan Böcker – SQL: Grundlagen von SQL Alles klar? ! SQL ist natürlichsprachlich. ! Die SQL-Anweisungen sind deklarativ: Nicht die Frage „Wie?“, sondern die Frage „Was?“ steht im Vordergrund. ! Abfragen sind in SQL abgeschlossen. Das Ergebnis einer select-Anweisung kann in anderen SQL-Anweisungen wie eine Tabelle genutzt werden. ! Die SQL-Anweisungen werden in die drei Kategorien DDL, DCL und DML unterteilt. ! SQL ist standardisiert; die Hersteller der RDBMS orientieren sich am Standard. Prof. Dr. Stefan Böcker – SQL: Grundlagen von SQL Einfache select-Anweisungen Prof. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen Die Projektion In einer select-Anweisung können die Spaltennamen in der genannten Projektion ausgewählt werden. 10.1 Viele Möglichkeiten, um Spalten zu beschreiben Tabelle 10.2: Ergebnis der Abfrage aus Listing 10.1 select titel, preis from alben titel preis Gespenster Geschichten Asterix der Gallier Asterix und Kleopatra Asterix als Legionär Die Trabantenstadt Der große Graben Der geheimnisvolle Stern Tim und der Haifischsee Das Kriminalmuseum Das Meisterwerk 1.20 2.80 2.80 3.00 3.80 5.00 null null 8.80 8.80 abhängig, mit dem wir auf die Datenbank zugreifen. In einigen S wird null als Text angezeigt, andere verwenden dazu eine leere Strich. Prof. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen Wir werden noch mit Abfragen arbeiten, in denen wir es mit Dat Tabellen zu tun haben. Dann ist es gelegentlich erforderlich, z Die Projektion Alternativ kann zusätzlich zum Spaltennamen noch der Tabellennamen qualifiziert werden. select alben.titel, alben.preis from alben Mit * werden werden verkürzt alle Spalten gewählt: select * from alben Prof. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen Mit Spalten Rechnen 174 10 Einfache selec In der Projektion können auch arithmetische Ausdrücke Die Preise in derpassiert: Datenbank bleiben unverändert, sie werden nur auftauchen. Beachten Sie, was mit null le 10.3 – erhöht dargestellt. Tabelle 10.3: Ergebnis der Abfrage aus Listing 10.4 select titel, preis*1.05 from alben titel preis * 1.05 Gespenster Geschichten Asterix der Gallier Asterix und Kleopatra Asterix als Legionär Die Trabantenstadt Der große Graben Der geheimnisvolle Stern Tim und der Haifischsee Das Kriminalmuseum Das Meisterwerk 1.2600 2.9400 2.9400 3.1500 3.9900 5.2500 null null 9.2400 9.2400 In select-Anweisungen können wir in der Projektion arithmetis verwenden. Wie wir auch dem Ergebnis der Abfrage aus Listing 1 ist das Resultat einer Operation gleich null, wenn einer der Oper Im Ergebnis sehen wir auch, dass der Text preis * 1.05 als Spa für den erhöhten Preis vom RDBMS verwendet wird. Wenn wir n Prof. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen in der folgenden Anweisung einen Spaltennamen vergeben, küm RDBMS darum. Aliasing Mit dem Schlüsselwort as können Sie Spalten und Tabellen unter einem anderen Namen ansprechen. as kann sich auch aus dem Kontext ergeben. select titel, preis*1.05 as neuerpreis from alben select a.jahr from alben a Prof. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen from alben Dubletten eliminieren Im Ergebnis (siehe Tabelle 10.5) fin Tabelle 10.5: Ergebnis der Abfrage jahr select distinct jahr from alben 1985 1986 1968 1972 1973 1974 1980 null Das Schlüsselwort distinct kan Prof. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen Dubletten eliminieren 176 select distinct reihe, jahr from alben where reihe='Asterix' In den Beispieldaten gibt es zwei Aster jektion aus Listing 10.8 berücksichtigt n Tabelle 10.6: Ergebnis der Abfrage aus L Obwohl doppelt vorhanden, ist (Asterix, 1968) nur einmal im Ergebnis vorhanden. reihe jahr Asterix Asterix Asterix Asterix 1974 1968 null 1980 10.2 In Prof. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen Datensätze mit wher den meisten Fällen brauchen wir ga dern nur einen Teil. Wir können hier – 10.2 Datensätze mit where auswählen In den meisten Fällen brauchen wir gar nicht alle Datensätze einer Tabelle, sondern nur einen Teil. Wir können hier – wie bei der Relationenalgebra – mit Selektionen (siehe etwa Abschnitt 4.5) arbeiten, für die es in der select-Anweisung die where-Komponente gibt: Prädikate Listing 10.9: Alle Alben, die 1968 erschienen sind select * select * from alben where jahr=1968 from alben In Tabelle 10.7 jahr=1968 sehen wir, dass das Ergebnis aus allen Datensätzen besteht, die where dem Prädikat jahr=1968 genügen. Tabelle 10.7: Ergebnis der Abfrage aus Listing 10.9 reihe titel band preis jahr Asterix Asterix Asterix der Gallier Asterix und Kleopatra 1 2 2.80 2.80 1968 1968 Anders als bei der Relationenalgebra müssen wir beim praktisch orientierten SQL berücksichtigen, dass das Prädikat auch den Wert null annehmen kann. Ein Datensatz gehört genau dann zum Ergebnis einer select-Anweisung, wenn das Prädikat den Wert true hat. Es folgt auch, dass wir nicht alle Datensätze erhalten, wenn wir die where-Komponente in Listing 10.9 durch where jahr != 1968 ersetzen. Hier werden nur die Datensätze gefunden, für die jahr = 1968 den Wert false hat. Die Datensätze, für die das Erscheinungsjahr unbekannt, also null ist, gehören nicht dazu. Alle Datensätze erhalten wir mit der folgenden Anweisung: Mit Hilfe von Prädikaten in der where-Komponente können Sie die Ergebnismenge einschränken. Nur Datensätze, für die das Prädikat den Wert true hat, gehören zur Ergebnismenge Prof. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen null nicht vergessen Eine ungewöhnliche Möglichkeit, alle Datensätze auszuwählen. Reicht ein einfacheres Prädikat? select * from alben where jahr=1968 or jahr!=1968 or jahr is null Prädikate können mit logischen Operatoren verknüpft werden. Prof. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen Listing 10.10: Eine ungewöhnliche Möglichkeit, alle Alben zu finden select * from alben where jahr=1968 or jahr!=1968 or jahr is null Natürlichsprachlichkeit An diesem Beispiel sehen wir, dass wir mehrere Prädikate mit logischen Operatoren wie not, and und or verknüpfen können; Prädikate, die null beinhalten, nicht mitkönnen dem Operator = formulieren dürfen.natürlicher not preis is null wir alternativ Wenn wir alle Datensätze kennen wollen, zu denen ein Preis bekannt ist, nehmen schreiben: wir dazu die folgende Abfrage: Listing 10.11: null in Prädikaten select * from alben preis is not null Daswhere Prädikat ist natürlichsprachlicher als seine – syntaktisch ebenfalls korrekte – select * from alben where preis is not null Alternative not preis is null. Die Ergebnisse finden wir in Tabelle 10.8. Tabelle 10.8: Ergebnis der Abfrage aus Listing 10.11 reihe titel band preis jahr Gespenster Geschichten Asterix Asterix Asterix Asterix Asterix Franka Franka Gespenster Geschichten Asterix der Gallier Asterix und Kleopatra Asterix als Legionär Die Trabantenstadt Der große Graben Das Kriminalmuseum Das Meisterwerk 1 1 2 10 17 25 1 2 1.20 2.80 2.80 3.00 3.80 5.00 8.80 8.80 1974 1968 1968 null 1974 1980 1985 1986 Neben können wir – auch ausschließlich Attributnamen zur FormulieProf.Literalen Dr. Stefan Böcker SQL: Einfache select-Anweisungen rung von Prädikaten nutzen: Prädikate Spaltennamen sind ebenso wie Literale in Prädikaten möglich. select * 178 from alben 10 Einfache select-Anweisungen where titel=reihe In Tabelle 10.9 sehen wir, dass unser Datenbestand nur einen Datensatz enthält, in dem die beiden Attribute titel und reihe den gleichen Wert haben. Tabelle 10.9: Ergebnis der Abfrage aus Listing 10.12 reihe titel band preis jahr Gespenster Geschichten Gespenster Geschichten 1 1.20 1974 Ein weiteres Beispiel für den Einsatz von logischen Operatoren sehen wir hier: Listing 10.13: Alle Asterixalben, die weniger als 6.0 kosten. select * fromDr. alben Prof. Stefan Böcker – SQL: Einfache select-Anweisungen where reihe='Asterix' and preis<6.00 10.3 Einige nützliche Operatoren 179 Der between-Operator So können wir anstatt Listing 10.14: Alle Alben, die zwischen 5.0 und 6.0 select * select * from alben where alben preis >= 5.00 and preis <= 10.00 from etwas einfacher mit between arbeiten:and preis <= 10.00 where preis >= 5.00 Listing 10.15: between ermöglicht natürlichsprachliche Prädikate select * select * from alben where preis between 5.00 and 10.00 from alben Daswhere Ergebnis entnehmen wir Tabelle 10.11. Die mit between formulierte Anweipreis between 5.00 and 10.00 sung ist zwar nicht kürzer, aber etwas klarer. Tabelle 10.11: Ergebnis der Abfrage aus Listing 10.15 reihe titel band preis jahr Asterix Franka Franka Der große Graben Das Kriminalmuseum Das Meisterwerk 25 1 2 5.00 8.80 8.80 1980 1985 1986 Mit dem in verbessern wir die Lesbarkeit unserer Anweisungen dageProf. Dr.Operator Stefan Böcker – SQL: Einfache select-Anweisungen gen deutlich. So können wir Der in-Operator select * from alben where reihe = 'Asterix' or reihe = 'Tim und Struppi' Ist äquivalent zu select * from alben where reihe in ('Asterix', 'Tim und Struppi') Prof. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen eingesetzt, in Kapitel 14 lernen wir Verwendungsmöglichkeiten für verschachtelte Abfragen kennen. Sehr nützlich ist auch der Mustervergleich von Texten in Prädikaten. Wenn wir uns daran erinnern, dass einer der Titel aus der Asterixreihe etwas mit einer Stadt zu tun hatte, können wir ihn leicht finden (siehe Listing 10.18). Mustervergleich Listing 10.18: Alle Alben mit stadt im Titel select * from alben* select where titel like '%stadt%' from alben Daswhere Zeichen titel % repräsentiert dem Muster '%stadt%' eine beliebige Zeichenlikein'%stadt%' kette. Dies entspricht dem Ergebnis aus Tabelle 10.13. Tabelle 10.13: Ergebnis der Abfrage aus Listing 10.18 reihe titel band preis jahr Asterix Die Trabantenstadt 17 3.80 1974 Jeder Titel, der also den Text stadt enthält, gehört somit zum Ergebnis der AbVorsicht: den like-Operator vergessen. Für frage. Gelegentlich verwendet man zwarnicht die Syntax für die Musterbeschreibung, vergisst aber den like-Operator. Wenndas das RDBMS Prädikat titel='%stadt%' lautitel='%stadt%‘ findet nur Datensätze, tet, in findet das RDBMS auchgleich nur Datensätze, in denen der Titel gleich dem Text denen der Titel dem Text %stadt% ist. %stadt% ist. Mit unseren Beispieldaten ergibt sich so ein leeres Ergebnis. Der Vergleich mit dem Muster findet nur in Verbindung mit dem Schlüsselwort like Dr. Stefan – SQL: Einfache select-Anweisungen statt.Prof. Neben demBöcker %-Zeichen gibt es noch _ als Platzhalter für ein einzelnes, beliebiges Zeichen. Wollen wir beispielsweise alle Titel finden, deren zweiter Buchstabe Mustervergleich _ ist Platzhalter für ein einzelnes, beliebiges Zeichen. Wollen wir beispielsweise alle Titel finden, deren zweiter Buchstabe ein s ist, verwenden wir das Prädikat titel like '_s%' Prof. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen Listing 10.19: Ergebnisse sortieren select distinct reihe from alben order by reihe Sortieren Das Ergebnis (siehe Tabelle 10.14) enthält die Namen der Albumreihen in alphabetisch aufsteigender Reihenfolge. Dubletten sind durch das Schlüsselwort select ausgemustert distinct worden. reihe Wie die Buchstaben angeordnet sind, ist ebendistinct sofrom wie diealben Einordnung von null vom verwendeten RDBMS abhängig. Der SQLStandard macht hierzu keine Aussage. Oftmals ist die Reihenfolge konfigurierbar. order by reihe Das alles entspricht natürlich ganz und gar nicht dem relationalen Modell: Hier sind weder Dubletten noch eine Reihenfolge vorgesehen. Tabelle 10.14: Ergebnis der Abfrage aus Listing 10.19 reihe Asterix Franka Gespenster Geschichten Tim und Struppi Selbstverständlich können wir die Daten auch in absteigenden Reihenfolge sortieren. Wir benutzen dazu das Schlüsselwort desc: Listing 10.20:Böcker Sortierung absteigender Reihenfolge Prof. Dr. Stefan – SQL:inEinfache select-Anweisungen select distinct reihe Franka Gespenster Geschichten Tim und Struppi Sortieren Selbstverständlich können wir die Daten auch in absteigenden Reihenfolge sortieren. Wir benutzen dazu das Schlüsselwort desc: Listing 10.20: Sortierung in absteigender Reihenfolge select distinct select distinct reihereihe from alben from alben order by reihe desc order by reihe desc In Tabelle 10.15 beobachten wir die umgekehrte Sortierung. Tabelle 10.15: Ergebnis der Abfrage aus Listing 10.20 reihe Tim und Struppi Gespenster Geschichten Franka Asterix Prof. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen from alben where reihe like 'Asterix%' and jahr = 1968 Alles in einen Topf In beiden Fällen bestehen die Ergebnisse aus einer Spa mit Texten. Beide Ergebnisse können jetzt zu einem ein werden: Listing 10.22: Die Vereinigung zweier Tabellen select band, titel select band, titel from alben from alben where band=1 where band=1 union union select jahr, reihe select jahr, reihe from alben where reihe like 'Asterix%' and jahr from alben Ergebnis sehen in Tabelle 10.17. where reihe like 'Asterix%'Das and jahr = wir 1968 = 1968 Tabelle 10.17: Ergebnis der Abfrage aus Listing 10.22 Was fällt am Ergebnis auf? band titel 1968 1 1 1 1 Asterix Der geheimnisvolle Stern Gespenster Geschichten Asterix der Gallier Das Kriminalmuseum Wir beobachten, dass Prof. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen die Spaltentitel für die Vereinigung von der ersten Alles in einen Topf Warum wird die folgende Anweisung zurückgewiesen? select band, titel from alben union select jahr, preis from alben Prof. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen select jahr, preis from alben Unsere Abfrage aus Listing 10.22 wirkt gekünstelt und ist sicher kein praktischer Anwendungsfall. union kann jedoch sehr hilfreich sein. Wenn wir zwei Comicsammlungen – sagen wir in den Tabellen alben_siggi und alben_barabass – haben, können wir beide zusammenlegen und die Alben trotzdem noch voneinander unterscheiden. Raffiniert Ein etwas lebensnäheres Beispiel. Listing 10.23: Zwei Comicsammlungen werden zusammengelgt select 'Siggis Album' besitzer, reihe, titel from alben_siggi select 'Siggis Album' besitzer, union all from alben_siggi select 'Barrabas Album', reihe, titel from union all alben_barabass reihe, titel select 'Barrabas Album‘ besitzer, reihe, titel Das Ergebnis sieht dann – je nach Datenbestand der Ausgangstabelle – wie in Tabelle 10.18 alben_barabass aus und kann die Grundlage für weitere interessante Auswertungen From sein. Tabelle 10.18: Ergebnis der Abfrage aus Listing 10.23 besitzer reihe titel Siggis Album Siggis Album Barrabas Album Barrabas Album ... Franka Franka Asterix Asterix Das Kriminalmuseum Das Meisterwerk Asterix der Gallier Asterix und Kleopatra band preis jahr Mit dieser Grundausstattung an Werkzeugen zum Formulieren von selectProf. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen Anweisungen können wir schon eine Menge anfangen. Möglicherweise haben die meisten Abfragen, die an ein RDBMS gerichtet werden, diese Grundform. Seine Alles klar? ! Die ausgewählten Spalten einer Tabelle werden in der select-Komponente definiert. ! Die select-Komponente kann auch arithmetische Ausdrücke und Funktionen enthalten. ! Spaltennamen sollten mit Hilfe eines Alias ihrer Tabellen qualifiziert werden. ! Mit distinct lassen sich Dubletten aus dem Ergebnis entfernen. ! Das Ergebnis kann mit Hilfe von Prädikaten in der whereKomponente eingeschränkt werden. Prof. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen Alles klar? ! Prädikate werden mit Hilfe der Booleschen Operationen and und or verknüpft. ! Operatoren wie in oder between erhöhen die Lesbarkeit der Anweisungen. ! Mit Hilfe des Operators like ist ein Musterabgleich für Texte möglich. ! Das Ergebnis einer Abfrage kann mit Hilfe von order by sortiert werden. ! Wenn die Ergebnisse von zwei Abfragen eine ähnliche Struktur haben, können sie mit union und union all vereinigt werden. Prof. Dr. Stefan Böcker – SQL: Einfache select-Anweisungen Funktionen in SQL-Anweisungen Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen Wozu Funktionen? In SQL dienen sie etwa ! der Formulierung von Integritätsregeln wie CheckConstraints, ! der Aufbereitung der Ergebnisse von selectAnweisungen oder ! der Formulierung von Prädikaten für Selektionen. Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen Skalare Funktionen skalarer Wert skalare Funktion skalarer Wert Funktionen, deren Argumente skalare (atomare) Werte sind, heißen skalare Funktionen. Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen Aggregatfunktionen skalarer Wert skalarer Wert ... Aggregatfunktion skalarer Wert skalarer Wert ! Mehrwertige Daten sind die Argumente von Aggregatfunktionen ! Ihr Ergebnis ist hingegen wieder ein skalarer Wert. Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen Eigene Funktionen Es gibt die beiden folgenden Möglichkeiten um eigene Funktionen zu definieren: ! Stored Procedures: Viele Datenbanksysteme stellen eine eigene Programmiersprache zur Verfügung, die auch als Stored Procedure Language (SPL) bezeichnet wird. Mit Hilfe dieser Sprache können eigene Funktionen definiert werden, die dann das RDBMS übersetzt und verwaltet. ! User Defined Functions (UDF): Funktionen, die bereits in einer Sprache wie C oder Java entwickelt wurden, können in das RDBMS integriert und als Funktion aus SQL-Anweisungen heraus aufgerufen werden. Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen 11.1 Funktionen zur Textverarbeitung Funktionen in Projektionen Eine einfache Funktion zur Textverarbeitung ist upper. In den beiden folgenden Beispielen für Abfragen, die wieder auf dem Datenbestand aus Tabelle 10.1 operieren, sehen wir exemplarisch, wie wir Funktionen sowohl für Projektionen als auch für Selektionen nutzen können. Listing 11.1: Funktionen können für die Projektion genutzt werden select distinct upper(reihe) select distinct upper(reihe) from alben from alben Das Ergebnis finden wir in der folgenden Tabelle. Tabelle 11.1: Ergebnis der Abfrage aus Listing 11.1 upper(reihe) GESPENSTER GESCHICHTEN ASTERIX FRANKA TIM UND STRUPPI In der nächsten Anweisung haben wir das Prädikat so formuliert, dass unabhängig von der Groß- oder Kleinschreibung alle Asterixalben ermittelt werden. Listing 11.2: Funktionen können zur Selektion genutzt werden Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen select titel Funktionen in Prädikaten 190 select titel from alben where upper(reihe)='ASTERIX' 11 Funktionen in SQL-Anweisungen Tabelle 11.2: Ergebnis der Abfrage aus Listing 11.2 titel Asterix der Gallier Asterix und Kleopatra Asterix als Legionär Die Trabantenstadt Der große Graben WirProf. haben bereits am–Anfang des Kapitels gesehen, dass die Funktion position Dr. Stefan Böcker Funktionen in SQL-Anweisungen einen Wert größer 0 liefert, wenn das zweite Argument der Funktion im ersten Asterix und Kleopatra Asterix als Legionär Die Trabantenstadt Funktionen in Prädikaten Der große Graben titelam Anfang des Kapitels gesehen, dass die Funktion positio Wirselect haben bereits einen Wert größer 0 liefert, wenn das zweite Argument der Funktion im erste from alben Argument enthalten ist. Das Ergebnis sehen wir in Listing 11.3. where 0<position(titel, 'Trabanten') Tabelle 11.3: Ergebnis der Abfrage aus Listing 11.1 titel Die Trabantenstadt Mit Hilfe des Operators like zum Mustervergleich können wir eine äquivalent aber elegantere Anweisung formulieren. Wie kann man die Anweisung äquivalent, aber einfacher select titel formulieren? from alben where reihe like '%Trabanten%' Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen titel Asterix der Gallier Asterix und Kleopatra Es müssen nicht Asterix als Legionär Die Trabantenstadt Der große Graben immer Funktionen sein select titel Wir haben bereits am Anfang des Kapitels gesehen, dass die Funktion positio from alben einen Wert größer 0 liefert, wenn das zweite Argument der Funktion im erst where titel like '%Trabanten%' Argument enthalten ist. Das Ergebnis sehen wir in Listing 11.3. Tabelle 11.3: Ergebnis der Abfrage aus Listing 11.1 titel Die Trabantenstadt Mit Hilfe des Operators like zum Mustervergleich können wir eine äquivalen aber elegantere Anweisung formulieren. select titel from alben Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen 11.2 Funktionen für Zahlen 191 Funktionen für Texte Listing 11.3: Textverkettung mit dem ||-Operator select reihe || ' Band ' || band || ': ' || titel select from alben concat(reihe, ' Band ', band, where fromreihe='Franka' alben ': ', titel ) In beiden Fällen bekommen wir das folgende Ergebnis: where reihe='Franka' Tabelle 11.4: Ergebnis der Abfrage aus Listing 11.3 (((reihe || ’ Band ’) || band) || ’: ’) || titel Franka Band 1: Das Kriminalmuseum Franka Band 2: Das Meisterwerk Eleganter ist hier der Einsatz des ||-Operators: 11.2 Funktionen für Zahlen select reihe || gehören ' Band ' || bandbekannte || ': ' || Zu den Funktionen für Zahlen selbstverständlich Vertreter austitel der Mathematik wie sin, log oder power. Bei der Arbeit mit den Datenbanken from alben von natur- oder ingenieurwissenschaftlichen Anwendungen treten diese Funktionen immer reihe='Franka' wieder mal auf. In der Praxis haben wir es aber meistens mit bewhere triebswirtschaftlich orientierten Anwendungen zu tun. Hier finden wir FunktioStefanvon Böcker – Funktionen SQL-Anweisungen nen Prof. zum Dr. Runden Zahlen vom Typindecimal: Zu den Funktionen für Zahlen gehören selbstverständlich bekannte Vertreter aus der Mathematik wie sin, log oder power. Bei der Arbeit mit den Datenbanken von natur- oder ingenieurwissenschaftlichen Anwendungen treten diese Funktionen immer wieder mal auf. In der Praxis haben wir es aber meistens mit betriebswirtschaftlich orientierten Anwendungen zu tun. Hier finden wir Funktionen zum Runden von Zahlen vom Typ decimal: Funktionen für Zahlen Listing 11.4: Runden von decimal-Zahlen select titel, round(preis,1), round(preis, 0) from alben where reihe='Asterix' select titel, round(preis,1), round(preis, 0) Wie from in Tabelle 11.5 dargestellt, werden die Titel zusammen mit den gerundeten alben Preisen angezeigt. Über das zweite Argument von round regeln wir, auf wie viele where reihe='Asterix' Stellen wir runden wollen. Positive Zahlen entsprechen den Nachkommastellen; Zahlen, die kleiner oder gleich null sind, entsprechen den Vorkommastellen. Tabelle 11.5: Ergebnis der Abfrage aus Listing 11.4 titel round(preis, 1) round(preis, 0) Asterix der Gallier Asterix und Kleopatra Asterix als Legionär Die Trabantenstadt Der große Graben 2.8 2.8 3.0 3.8 5.0 3.0 3.0 3.0 4.0 5.0 Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen Wenn einer der Operanden eines arithmetischen Ausdrucks null ist, dann ist auch das Ergebnis null. Funktionen für Zahlen Die Funktion truncate rundet nicht, sondern entfernt einfach einen Teil der Stellen einer Zahl. Die Anweisung Listing 11.5: Zahlen mit truncate abschneiden select titel,preis,truncate(preis,1),truncate(preis, 0) select titel, preis, truncate(preis,1), truncate(preis, 0) from alben from alben where where reihe='Asterix' reihe='Asterix' liefert also das Ergebnis aus Tabelle 11.6. Tabelle 11.6: Ergebnis der Abfrage aus Listing 11.5 titel preis truncate(preis, 1) truncate(preis, 0) Asterix der Gallier Asterix und Kleopatra Asterix als Legionär Die Trabantenstadt Der große Graben 2.80 2.80 3.00 3.80 5.00 2.8 2.8 3.0 3.8 5.0 2.0 2.0 3.0 3.0 5.0 Wenn wir das Ergebnis einer Funktion nur für einige explizite Werte wissen wollen, brauchen wir keine Tabelle und verzichten auf die from-Komponente: Prof. Dr. Stefan Böcker – Funktionen SQL-Anweisungen -1) select truncate(47.11, 0), in truncate(47.11, Nur Funktionen Mit den folgenden Anweisungen ist es möglich Funktionen etwa für Tests auch ohne Daten aufzurufen. select truncate(47.11, 0), truncate(47.11, -1) call truncate(47.11, 0) Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen Funktionen für Zeitangaben create table timedata( name varchar(20) primary key, d date default current_date(), t time default current_time(), ts timestamp default current_timestamp() ) ! Mit Hilfe von Funktionen wie current_date() kann das aktuelle Datum als Standardwert genutzt werden. ! Zu den Funktionen gibt es auch natürlichsprachliche Varianten wie current date. Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen d date default current_date(), t time default current_time(), ts timestamp default current_timestamp() ) Standardzeiten nutzen Die mit default markierten Standardwerte (siehe 5.14) ergeben sich dabei aus Funktionen, die uns – wie ihre Namen schon sagen – die aktuellen Zeitangaben liefern. Wir können sie sogar noch suggestiver in der Form current date, also ohne Unterstrich und Klammern, schreiben. insert into timedata values('Donald', Beim Einfügen der Daten können wir explizite Werte angeben, die von den Stan'1934-06-09','12:00:00','1934-06-09 12:00:00.0'); dardwerten abweichen: insert into timedata(name) values('Baby-Donald'); insert into timedata values('Donald','1934-06-09','12:00:00','1934-06-09 12:00:00.0'); insert into timedata(name) values('Baby-Donald'); select * from timedata select * Beim zweiten insert werden die default Werte eingefügt: from timedata Tabelle 11.7: Nützliche Datumsfuntkionen als Standardwerte name d t ts Donald Baby-Donald 1934-06-09 2011-07-09 12:00:00 07:33:07 1934-06-09 12:00:00.0 2011-07-09 07:33:07.104 WirProf. schauen weitere Anweisungen an, in denen einige Funktionen beispielhaft Dr. Stefan Böcker – Funktionen in SQL-Anweisungen verwendet werden. Weitere Datumsfunktionen An welchem Wochentag wurde Donald geboren? select dayname(d) from timedata where name='Donald' Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen Hinweis: Wenn null Argument einer skalaren Funktionen ist, dann ist ihr Ergebnis ebenfalls null. Wenn einer der Operanden eines arithmetischen Ausdrucks null ist, dann ist auch das Ergebnis null. Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen Aggregatfunktionen select avg(preis),min(preis),max(preis),sum(preis),count(preis) from alben Ihren Namen entsprechend ermitteln die Funktionen die folgenden Werte: ! avg: den Durchschnittspreis ! min: den kleinsten Preis ! max: den höchsten Preis ! sum: die Summe über alle Preise ! count: die Anzahl der Preise in der Tabelle Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen Ihren Namen entsprechend ermitteln die Funktionen die folgenden Werte: avg: den Durchschnittspreis Aggregatfunktionen min: den kleinsten Preis max: den höchsten Preis sum: die Summe über alle Preise count: die Anzahl der Preise in der Tabelle Da jede Aggregatfuntion genau einen Wert liefert, besteht das Ergebnis aus einer Zeile: Tabelle 11.9: Ergebnis der Abfrage aus Listing 11.7 avg(preis) min(preis) max(preis) sum(preis) count(preis) 4.525 1.20 8.80 36.20 8 Ein RDBMS kann sehr viele skalare Funktionen zur Verfügung stellen, die Anzahl von Aggregatfunktionen ist dagegen überschaubar. Neben den fünf aufgezählten gibt es gelegentlich noch statistische Aggregatfunktionen etwa zur Berechnung der Varianz oder der Standardabweichung. Wenn wir fällt einer einfachen Was auf? Funktionen null-Werte übergeben, ist das Ergebnis immer null. Auch bei Vergleichsoperationen wie < oder > oder arithmetischen Operationen ergibt sich null als Ergebnis. Eine Ausnahme bilden logische Operatoren wie or. Hier gilt, wie wir in Abschnitt 10.2 gesehen haben: null or true = true Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen Wir haben beobachtet, dass Funktionen und arithmetische Operationen null liefern, sobald einer der beteiligten Werte null ist. Da unsere Beispieldaten in der Hinweis: Aggregatfunktionen ignorieren null-Werte. Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen Listing 11.8: Die zwei Gesichter von count select avg(preis), sum(preis)/count(*) from alben Aggregatfunktionen und null Von der avg-Funktion werden null-Werte ignoriert. Bei der zweiten Variante zur Durchschnittsberechnung werden die null-Werte nur im Zähler ignoriert. Die Funktion so dass null hier keinerlei Relevanz zu *) zählt Datensätze, selectcount( avg(preis), sum(preis)/count(*) kommt. Diese kleinen Unterschiede mögen banal erscheinen, in der Praxis sind from alben sie aber eine nicht zu unterschätzende Fehlerquelle. Tabelle 11.10: Ergebnis der Abfrage aus Listing 11.8 avg(preis) sum(preis) / count(*) 4.525 3.62 Wenn wir nicht nur null, sondern auch Dubletten bei der Aggregatbildung igno rieren wollen, hilft uns – wie bei einem einfachen select – das Schlüsselwor Wie erklären distinct weiter:Sie sich die abweichenden Werte? select count(distinct reihe) from alben Dr. Stefan Böcker – Funktionen in SQL-Anweisungen H2Prof. findet, wie erwartet, vier verschiedene Comicreihen. Alles klar? ! Parameter von skalaren Funktionen sind atomar. ! Parameter von Aggregatfunktionen sind mehrwertig. ! In den meisten RDBMS können eigene Funktionen definiert werden. ! Der Katalog von Funktionen eines RDBMS ist herstellerspezifisch. Viele RDBMS haben ihre eigenen Funktionen. ! Skalare Funktionen liefern null als Ergebnis, wenn ein Parameter null ist. Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen Alles klar? ! Mit Funktionen zur Texverarbeitung können beispielsweise Texte verkettet oder in Groß- oder Kleinbuchstaben umgewandelt werden. ! Funktionen für Zahlen können neben den gängigen mathematischen Operationen auch Zahlen runden oder verkürzen. ! Funktionen für Zeitangaben ermöglichen eine Kalenderarithemtik. Einzelne Bestandteile einer Zeitangabe können ermittelt werden. ! Die gängigen Aggregatfunktionen sind count, sum, min, max und avg. ! Aggregatfunktionen ignorieren null-Werte. Prof. Dr. Stefan Böcker – Funktionen in SQL-Anweisungen Daten zusammenfassen Prof. Dr. Stefan Böcker – SQL: Daten zusammenfassen Eine Überraschung Wie viele Bände gibt es in jeder Reihe ? select reihe, count(band) from alben Auch wenn die Abfrage ganz plausibel erscheint, meldet H2 doch einen Fehler: Feld "REIHE" muss in der GROUP BY Liste sein Column "REIHE" must be in the GROUP BY list; Prof. Dr. Stefan Böcker – SQL: Daten zusammenfassen Gruppierungen sind richtig Wie viele Bände gibt es in jeder Reihe ? select reihe, count(band) from alben group by reihe Prof. Dr. Stefan Böcker – SQL: Daten zusammenfassen Hinweis: Wenn in der Projektion Spalten und Aggregatfunktionen auftreten, müssen alle Spalten in die group by-Komponente der Abfrage aufgenommen werden. Prof. Dr. Stefan Böcker – SQL: Daten zusammenfassen Mehre Spalte je Gruppe 12.1 Die group by-Komponente 201 Was ist der Durchschnittspreis aller Bände einer Reihe pro Listing 12.3: Für jede Reihe den Durchschnittspreis pro Jahr ermitteln Jahr? select reihe, jahr, avg(preis) from alben group by reihe, jahr select reihe, jahr, avg(preis) Das Ergebnis sehen wir in Tabelle 12.2. Interessant ist hier auch, dass die Agfrom alben gregatfunktion avg den Wert null ermittelt. Auch wenn count eigentlich null ignoriert: Für die Tim und Struppi-Alben ist kein einziger Preis bekannt, so dass group byWertreihe, jahr kein numerischer ermittelt werden kann. Tabelle 12.2: Ergebnis der Abfrage aus Listing 12.3 reihe jahr avg(preis) Asterix Asterix Franka Franka Asterix Gespenster Geschichten Tim und Struppi Tim und Struppi Asterix 1968 null 1986 1985 1974 1974 1972 1973 1980 2.8 3 8.8 8.8 3.8 1.2 null null 5 Natürlich können wir group– by auch ohne zusammenfassen Aggregatfunktionen verwenden: Prof. Dr. Stefan Böcker SQL: Daten Listing 12.4: Gruppierungen ohne Aggregatfunktion Gruppierungen ohne Aggregatfunktion select reihe, jahr from alben group by reihe, jahr 202 1 Tabelle 12.3: Ergebnis der Abfrage aus Listing 12.4 Die Wirkung ist die Gleiche wie bei select distinct reihe jahr Asterix Asterix Franka Franka Asterix Gespenster Geschichten Tim und Struppi Tim und Struppi Asterix 1968 null 1986 1985 1974 1974 1972 1973 1980 Prof. Dr. Stefan Böcker – SQL: Daten zusammenfassen Eine Spalte, die im group by auftritt, muss also nicht Be Gruppierungen ohne Eine Spalte, die im group by au on sein. So ganz ohne die Namen auch in Tabelle 12.4 sehen, auf de Projektionsspalten geschachtelten Abfragen (siehe Ka weisen. Tabelle 12.4: Ergebnis der Abfrage count(band) select count(band) from alben group by reihe 5 2 1 2 12.2 Die Diese Vorgehensweise wird im Zusammenhang mit verschachtelten Abfragen interessant werden. Prof. Dr. Stefan Böcker – SQL: Daten zusammenfassen having-Kom Wenn wir mit group by arbeiten wir bekommen. Falls uns beispiels bisher mindestens drei Alben ersc Eine weitere Überraschung Alle Reihen ermitteln, in denen mindestens drei Alben erschienen sind: select reihe, count(band) from alben where count(band)>=3 group by reihe Die Anweisung ist syntaktisch falsch und wird nicht vom RDBMS ausgeführt Prof. Dr. Stefan Böcker – SQL: Daten zusammenfassen Die having-Komponente select reihe, count(band) from alben group by reihe having count(band)>=3 reihe Asterix count(band) 5 Prof. Dr. Stefan Böcker – SQL: Daten zusammenfassen Hinweis: Prädikate, die Aggregatfunktionen enthalten, gehören zur having-Komponente und nicht zur where-Komponente einer Abfrage. Prof. Dr. Stefan Böcker – SQL: Daten zusammenfassen Selbstverständlich können auch die Spalten, nach denen wir gruppieren, ohne Aggregate in der having-Komponente stehen, doch haben sie dann die gleiche Eine having-Komponente ohne Aggregatfunktion Funktion wie in der where-Komponente. Listing 12.8: Eine having-Komponente ohne Aggregatfunktion select reihe, count(band) select reihe, count(band) from alben from groupalben by reihe havingby reihe not like '% %' group reihe having reihe not alle like '% %' Die Anweisung ermittelt Reihen, die aus nur einem Wort bestehen, zusammen mit der Anzahl der jeweils vorhandenen Bände: reihe count(band) Asterix Franka 5 2 Prof. Dr. Stefan Böcker – SQL: Daten zusammenfassen Alles klar? ! Immer wenn Spalten und Aggregatfunktionen zusammen in der Projektion auftauchen, müssen die Spalten in der group by-Komponente wiederholt werden. ! Umgekehrt müssen Spalten aus der group byKomponente nicht in der Projektion erfasst werden. ! Die Prädikate aus der where-Komponente dürfen keine Aggregatfunktionen enthalten. ! Für Prädikate mit Aggregatfunktionen ist die havingKomponente vorgesehen. Prof. Dr. Stefan Böcker – SQL: Daten zusammenfassen Datensätze verbinden Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden Mehr als eine Tabelle Die Datensätze der Beispieltabelle werden auf die zwei Tabellen reihen und alben verteilt: 208 13 Datensätze verbinden Reihen Alben Abbildung 13.1: ER-Diagramm für Comicalben und ihre zugehörigen Reihen Dem ER-Diagramm entnehmen wir auch, dass es Comicreihen geben kann, zu denen kein einziges Album erfasst ist. Beim exemplarischen Datenbestand haben wir Prof. vonDr. dieser Gebrauch gemacht: Zur Reihe „Prinz Eisenherz“ finStefanMöglichkeit Böcker – SQL: Datensätze verbinden den wir in der Tabelle 13.2 kein Album. Ansonsten ist der Datenbestand zu dem 13.1 Joins mit SQL Alle Asterix-Bände select id from reihen where name='Asterix' Das Ergebnis hat den Wert 2 Das Ergebnis besteht aus dem Wert 2. Wir ermitte Tabelle alben, deren Attribut reihe genau diese Listing 13.1: Die Asterixalben auf einen Blick select titel from alben where reihe=2 Das Ergebnis sehen wir in Tabelle 13.3. Tabelle 13.3: Ergebnis der Abfrage aus Listing 13.1 select titel from alben where reihe=2 titel Asterix der Gallier Asterix und Kleopatra Asterix als Legionär Die Trabantenstadt Der große Graben Die Vorgehensweise gestaltet sich bereits für zwe anfällig; wenn die Daten über mehr als zwei Tabe Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden schlimmer. Der Join Informationen aus zwei Tabellen können wir auch in einer einzigen Anweisung ermitteln: select reihen.name, alben.titel from alben, reihen where alben.reihe = reihen.id Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden Die Übersicht Mit Hilfe von Aliasen können wir die Anweisung übersichtlicher gestalten select r.name, a.titel from alben a, reihen r where a.reihe = r.id Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden Wozu die Bedingung? 13.1 Joins mit SQL id=1 name=Asterix 211 reihe=1 titel=Asterix der Gallier reihe=1 titel=Asterix und Kleopatra id=4 name=Franka reihe=4 titel=Das Kriminalmuseum reihe=4 titel=Das Meisterwerk Abbildung 13.2: Join mit dem Prädikat alben.reihe=reihen.id Passende Datensätze werden kombiniert Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden Praxis gelegentlich bei Anfängern, die die Join-Bedingung gar nicht oder falsch Joins ohne Join-Bedingung select a.titel from alben a, reihen r Wie sieht das Ergebnis aus? Ist dieser Join sinnvoll? Wie kann man das Ergebnis bezeichnen? Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden Hinweis: Wenn ein Join zu viele Datensätze liefert, ist die Join-Bedingung in vielen Fällen unvollständig. Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden Der where-Teil select a.titel from alben a, reihen r where a.reihe=r.id and r.name='Asterix' Die Prädikate im where-Teil haben verschiedene Qualitäten: ! Der Teil a.reihe=r.id ist die Join-Bedingung. ! Der Teil r.name='Asterix' ist ein Filter, der sich auf die Spalten einer einzelnen Tabelle bezieht. Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden Eine andere Syntax Diese verschiedenen Qualtitäten werden bei der folgenden Syntax differenziert: select a.titel from alben a inner join reihen r on a.reihe=r.id where r.name='Asterix' Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden Hinweis: Wählen Sie für Joins die Notation, die Ihnen am meisten zusagt. Es gibt keine bessere oder schlechtere Variante. Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden Outer Joins Wenn es Inner-Joins gibt, dann auch Outer-Joins: In den Beispieldaten ist die Reihe ‚Prinz Eisenherz‘ erfasst, obwohl es dazu keine Alben gibt.. Diese Reihe taucht daher im Ergebnis der folgenden Abfrage nicht auf. Select r.name, a.titel from alben a, reihen r where a.reihe=r.id Wie könnte die Alternative aussehen? Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden outer-Join? In unserem Datenbestand befinden sich die Reihe „Prinz Eisenherz“, zu der wir in unseren Beispieldaten kein Album erfasst haben. Solche Reihen ohne Album bleiben beim Inner-Join auf der Strecke und gehören nicht zum Ergebnis (siehe Tabelle 13.4). Genau dieses Problem löst der Outer-Join: Outer Joins select r.name, a.titel from reihen r left outer join alben a on r.id = a.reihe select r.name, a.titel Der folgenden Tabelle entnehmen wir, dass diesmal alle Reihen zum Ergebnis gefrom reihen r left outer join alben a hören. Wenn es zu einer Reihe kein Album gibt, werden die Attribute aus der Projektion, die zur=Tabelle alben gehören, einfach durch null ersetzt. on r.id a.reihe Tabelle 13.6: Ergebnis der Abfrage aus Listing 13.3 titel name Gespenster Geschichten Asterix Asterix Asterix Asterix Asterix Tim und Struppi Tim und Struppi Franka Franka Prinz Eisenherz Gespenster Geschichten Asterix der Gallier Asterix und Kleopatra Asterix als Legionär Die Trabantenstadt Der große Graben Der geheimnisvolle Stern Tim und der Haifischsee Das Kriminalmuseum Das Meisterwerk null DemProf. Diagramm in Böcker Abbildung 13.1 entnehmen wir, dass die Reihen zu den Alben Dr. Stefan – SQL: Datensätze verbinden in einer 1-CM-Beziehung stehen. Zu jeder Reihe kann es also Alben geben. Im- Gibt es Outer-Joins oft? ! Reihen stehen zu Alben in einer 1-CM-Beziehung. ! Zu jeder Reihe kann es also Alben geben. ! Immer dann, wenn wir solchen Beziehungen in unseren Abfragen Rechnung tragen wollen, brauchen wir den Outer-Join. Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden Hinweis: Berücksichtigen Sie stets die Möglichkeit des Outer-Joins. Er tritt häufiger als sie glauben. Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden Die Richtung Gibt es Left-Outer-Joins, dann wohl auch Right-Outer-Joins. Tatsächlich können wir Left-Outer-Joins auch äquivalent als Right-Outer-Joins formulieren. Für das Beispiel heißt das: select r.name, a.titel from alben a right outer join reihen r on a.reihe=r.id Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden Muss es immer natürlich sein? Die Joins, die wir bisher gesehen haben, sind so genannte natürliche Joins: In der Join-Bedingung wird der Primärschlüssel der einen Tabelle gleich einem Fremdschlüssel der anderen Tabelle gesetzt. Diese Art Join ist sehr weit verbreitet. Es gibt aber auch andere Möglichkeiten: Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden Die Richtung Zu jeder Reihe die Jahre ermitteln, in denen es eine Preiserhöhung gab select a2.reihe, a2.jahr from alben a1, alben a2 where a1.reihe=a2.reihe and a2.band>a1.band and a2.preis>a1.preis 13.5 Joins mit mehr als zwei Tabellen group by a2.reihe, a2.jahr Tabelle 13.7: Ergebnis der Abfrage aus Listing 13.4 reihe jahr 2 2 2 1980 1974 null Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden 215 band int not null, foreign key(reihe, band) references alben, primary key(autor, reihe, band) ) Joins über mehr als zwei Tabellen Zu jedem Album kann es jetzt Autoren geben, und jeder Autor kann, entsprechend dem ER-Diagramm aus Abbildung 13.3, Mitarbeiter an Comicalben sein. Reihen Alben Autoren AlbenAutoren Abbildung 13.3: ER-Diagramm für die Beispieltabellen select au.name, al.titel Die Beispieldaten finden wir in den Tabellen 13.8 und 13.9: from alben al, albenautoren aa, autoren au where al.reihe=aa.reihe and al.band=aa.band and au.id=aa.autor Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden Hinweis: Verwenden Sie ein ER-Diagramm als Unterstützung, um Join- Bedingungen für Joins über mehr als zwei Tabellen zu formulieren. Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden Alles klar? ! Mit einem Join werden die Datensätze von Tabellen miteinander verknüpft. Die beteiligten Tabellen werden in der from-Komponente aufgelistet. ! An einem Join sind mindestens zwei Tabellen beteiligt, jede Tabelle kann aber auch mit sich selbst verbunden werden. ! Sinnvolle Verknüpfungen sind nur möglich, wenn eine geeignete Join-Bedingung als Prädikat formuliert wird. ! Inner-Joins verbinden nur Datensätze, die der JoinBedingung genügen. ! Im Ergebnis eines Outer-Joins sind auch Datensätze enthalten, zu denen es kein passendes Gegenstück gibt. Prof. Dr. Stefan Böcker – SQL: Datensätze verbinden Geschachtelte Abfragen Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Komplexere Abfragen Wir wollen das älteste Album in der Sammlung ermitteln: Zuerst select min(jahr) from alben und dann alle Alben aus dem Jahr 1968 suchen: select titel from alben where jahr = 1968 Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Geschachtelte Abfragen Das gleiche Ergebnis liefert select titel from alben where jahr = ( select min(jahr) from alben) Diese Anweisung besteht aus ! einer inneren select-Anweisung, die das Minimum ermittelt, und ! einer äußeren select-Anweisung, die alle Alben findet, deren Erscheinungsjahr gleich diesem Minimum sind. Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Ein äquivalenter Join Mit viel Geduld findet man auch eine Lösung, die einen Join nutzt. select a1.titel from alben a1, alben a2 where a1.jahr>=a2.jahr group by a1.titel having count(distinct a2.jahr)=1 Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen So geht‘s nicht Alle Alben suchen, die im gleichen Jahr wie ein AsterixAlbum erschienen sind select titel from alben a where jahr = (select jahr from alben where reihe='Asterix') Warum weist das RDBMS die Anweisung als fehlerhaft zurück? Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Mengenorientierte Operatoren Wenn das Ergebnis der Unterabfrage aus mehreren Datensätzen besteht, muss ein mengenorientierter Operator wie in verwendet werden. select titel from alben a where jahr in (select jahr from alben where reihe='Asterix') Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Der all-Operator ... jahr >all ( select jahr from alben where reihe like '%Tim%') Der Ausdruck ist genau dann wahr, wenn der Wert von jahr größer als jeder der Werte aus dem Ergebnis der Unterabfrage ist. Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Der any-Operator ... jahr >any( select jahr from alben where reihe like '%Tim%') Der Ausdruck ist genau dann wahr, wenn der Wert von jahr größer ist als irgendein Jahr, in dem ein Album erschienen ist, dessen Reihe den Text ‚Tim‘ enthält. Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen all und any Die beiden Operatoren all und any werden stets in Verbindung mit einem der Vergleichsoperatoren <,> und = verwendet. Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Die Abfrage soll uns als Ergebnis alle Alben liefern, die nach dem neuesten Asterix-Album erschienen sind. Auf den ersten Blick mag man glauben, dass das Gleiche wie bei der folgenden Abfrage herauskommt. Eine einfache Abfrage Listing 14.7: Alben, die jünger als alle Asterix-Alben sind select titel from alben select titel where jahr > (select max(jahr) from from alben alben where jahr reihe='Asterix') where > ( max(jahr) Wenn select wir das Ergebnis dieser Abfrage in Tabelle 14.3 mit dem Datenbestand unserer Beispieltabelle 10.1 abgleichen, sehen wir, dass die Abfrage korrekte Daten from alben geliefert hat. Führen wir dagegen die scheinbar gleichwertige Abfrage aus Liswhere reihe='Asterix') ting 14.6 aus, erhalten wir eine leere Ergebnistabelle. Die beiden Abfragen sind daher nicht gleichwertig; die Syntax der Abfrage aus Listing 14.6 ist zwar korrekt, ihre Semantik muss aber falsch sein. Alben, die jünger als alle Asterix-Alben sind Tabelle 14.3: Ergebnis der Abfrage aus Listing 14.7 titel Das Kriminalmuseum Das Meisterwerk An Prof. Phänomenen wie diesem kann man lange knobeln; die Ursache ist auch hier Dr. Stefan Böcker – SQL: Geschachtelte Abfragen der Wert null. In den Beispieldaten sind vier der Asterixalben in den Jahren 1968, Ganz ähnlich select titel from alben where jahr > all ( select jahr from alben where reihe='Asterix') Was macht diese Abfrage? Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Die Analyse Die innere Abfrage select jahr from alben where reihe='Asterix‘ Liefert die Ergebnisse 1968, 1974, 1980 und null Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Ganz ähnlich Das Prädikat jahr >all (1968, 1974, 1980, null) ist äquivalent zu jahr>1968 and jahr>1974 and jahr>1980 and jahr>null Der Wahrheitswert ist null. Die Abfrage liefert also keinen Datensatz. Die beiden geschachtelten Abfragen sind also nicht äquivalent. Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Hinweis: Bedenken Sie immer, dass null in Ihrer Tabelle auftreten kann! Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Der exists-Operator Was ist die Bedeutung der folgenden natürlichsprachlichen Anweisung? select reihe, titel, jahr from alben a1 where not exists ( select * from alben a2 where a1.jahr=a2.jahr and a1.reihe=a2.reihe) Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Die Bedeutung Alle Alben ermitteln, aus deren Reihe im Erscheinungsjahr kein weiterer Band erschienen ist Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Join oder verschachtelte Abfrage? Zur Lösung eines Problems sind praktisch immer Joins und Unterabfragen möglich. select a.titel from alben a, reihen r where a.reihe=r.id and r.name='Asterix' select a.titel from alben a where reihe = (select id from reihen r where r.id=a.reihe and r.name='Asterix') Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Hinweis: Bei vielen Abfragen können wir geschachtelte Abfragen und Joins alternativ einsetzen. Keine der beiden Strategien ist grundsätzlich besser. Berücksichtigen Sie beide Varianten, und wählen Sie die klarere aus. Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Korrelierte Abfragen Vergleichen Sie den Aufbau der beiden folgenden Anweisungen select titel from alben where jahr = ( select min(jahr) from alben) select a.titel from alben a where reihe = (select id from reihen r where r.id=a.reihe and r.name='Asterix') Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Korrelierte Abfragen select titel from alben where jahr = ( select min(jahr) from alben) Das Ergebnis der inneren Abfrage ist 1968. Dieses Ergebnis muss für die gesamte Abfrage nur ein einziges Mal ermittelt werden. Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Korrelierte Abfragen select a.titel from alben a where reihe = (select id from reihen r where r.id=a.reihe and r.name='Asterix') Für jeden Datensatz der äußeren Abfrage muss die innere Abfrage erneut ausgeführt werden. Die innere Abfrage hängt von der Äußeren ab. Diese Art Abfragen werden als korreliert bezeichnet. Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Korrelierte Abfragen Im vorliegenden Fall kann die Korrelation aufgehoben werden: select titel from alben a where reihe in ( select id from reihen r and r.name='Asterix' ) Hier ist alternativ (und besser) auch ein Join möglich. Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Alles klar? ! Geschachtelte Abfragen enthalten eine Unterabfrage in der where- Bedingung. ! Wenn die Unterabfrage nur einen atomaren Wert zurückliefert, kann sie in Prädikaten genutzt werden, die mit den Vergleichsoperatoren <, > oder = definiert wurden. ! Liefert die Unterabfrage mehrere Datensätze, so müssen die Operatoren in, any, all oder exists verwendet werden. Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen Alles klar? ! Um ein atomares Ergebnis zu garantieren, werden in der Unterabfrage oft Aggregate eingesetzt. ! Eine Unterabfrage, die Spalten aus der übergeordneten Abfrage enthält, heißt „korreliert“. Die Verarbeitung einer korrelierten Abfrage ist aufwändig. ! Geschachtelte Abfragen können oft durch Joins ersetzt werden, die sich ihrerseits durch geschachtelte Abfragen ersetzen lassen. Prof. Dr. Stefan Böcker – SQL: Geschachtelte Abfragen