SQL/Abfragen
Abfragen
Die grundlegenden Befehle und Begriffe werden anhand des folgenden Beispiels erklärt:
ER-Diagramm: | ||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Relationen: |
|
|
|
|
Einfache Abfrage
SELECT *
FROM Student;
listet alle Spalten und alle Zeilen der Tabelle Student
auf.
Ergebnis:
MatrNr |
Name
|
---|---|
26120 |
Fichte
|
25403 |
Jonas
|
27103 |
Fauler
|
Abfrage mit Spaltenauswahl (,
)
SELECT VorlNr,
Titel
FROM Vorlesung;
listet die Spalten VorlNr
und Titel
aller Zeilen der Tabelle Vorlesung
auf.
Ergebnis:
VorlNr |
Titel
|
---|---|
5001 |
ET
|
5022 |
IT
|
5045 |
DB
|
Abfrage mit eindeutigen Werten (DISTINCT
)
SELECT DISTINCT MatrNr
FROM hoert;
listet nur unterschiedliche Einträge der Spalte MatrNr
aus der Tabelle hoert
auf. Dies zeigt die Matrikelnummern aller Studenten, die mindestens eine Vorlesung hören, wobei mehrfach auftretende Matrikelnummern nur einmal ausgegeben werden.
Ergebnis:
MatrNr
|
---|
25403
|
26120
|
Abfrage mit Umbenennung (AS
)
SELECT MatrNr AS Matrikelnummer,
Name
FROM Student;
listet die Spalten MatrNr
und Name aller Zeilen der Tabelle Student
auf. MatrNr
wird beim Anzeigeergebnis als Matrikelnummer aufgeführt.
Ergebnis:
Matrikelnummer |
Name
|
---|---|
26120 |
Fichte
|
25403 |
Jonas
|
27103 |
Fauler
|
Abfrage mit Filter (WHERE
)
SELECT VorlNr,
Titel
FROM Vorlesung
WHERE Titel = 'ET';
listet VorlNr
und Titel
aller derjenigen Zeilen der Tabelle Vorlesung
auf, deren Titel ET
ist.
Die solchermaßen strukturierte, häufig verwendete Anweisung wird nach den Anfangsbuchstaben auch als „SFW-Block“ bezeichnet.
Ergebnis:
VorlNr |
Titel
|
---|---|
5001 |
ET
|
Abfrage mit Filter nach Inhalt (WHERE ... LIKE ...
)
SELECT Name
FROM Student
WHERE Name LIKE 'F%';
listet die Namen aller Studenten auf, deren Name mit F
beginnt (im Beispiel: Fichte
und Fauler
).
LIKE
kann mit verschiedenen Platzhaltern verwendet werden: _
steht für ein einzelnes beliebiges Zeichen, %
steht für eine beliebige Zeichenfolge. Manche Datenbanksysteme bieten weitere solche Wildcard-Zeichen an, etwa für Zeichenmengen.
Ergebnis:
Name
|
---|
Fichte
|
Fauler
|
Abfrage mit Filter und Sortierung (ORDER BY
)
SELECT Vorname,
Name,
StrasseNr,
Plz,
Ort
FROM Student
WHERE Plz = '20095'
ORDER BY Name;
listet Vorname
, Name
, StrasseNr
, Plz
und Ort
aller Studenten aus dem angegebenen Postleitzahlbereich aufsteigend sortiert nach Name
auf.
Abfrage mit verknüpften Tabellen (,
und INNER JOIN
)
SELECT Vorlesung.VorlNr,
Vorlesung.Titel,
Professor.PersNr,
Professor.Name
FROM Professor,
Vorlesung
WHERE Professor.PersNr = Vorlesung.PersNr;
Die Aufzählung hinter FROM
legt die Datenquellen fest: an dieser Stelle können mithilfe sogenannter JOIN
s mehrere Tabellen miteinander verknüpft werden, sodass Daten aus verschiedenen Tabellen zusammengeführt und angezeigt werden.
In diesem Beispiel wird ein „innerer natürlicher Verbund“ (NATURAL INNER JOIN
) verwendet: Alle Datensätze aus den Tabellen Professor
und Vorlesung
, die den gleichen Wert im Feld PersNr
haben. Professor
en ohne Vorlesung
und Vorlesung
en ohne Professor
werden damit nicht angezeigt.
Dies ist äquivalent zu:
SELECT Vorlesung.VorlNr,
Vorlesung.Titel,
Professor.PersNr,
Professor.Name
FROM Professor
INNER JOIN Vorlesung
ON Professor.PersNr = Vorlesung.PersNr;
Vorsicht: Nicht alle Implementierungen verstehen beide Schreibweisen, die Oracle-Schreibweise FROM Professor, Vorlesung
gilt als veraltet und ist weniger verbreitet. Sie entspricht auch nicht dem ANSI-Standard und sollte deshalb vermieden werden. Aus historischen Gründen ist sie jedoch noch häufig anzutreffen.
Tabellen können nicht nur über Schlüsselfelder, sondern über beliebige Felder miteinander verknüpft werden, wie das folgende, fachlich unsinnige Beispiel zeigt:
SELECT Vorlesung.Titel,
Professor.Name
FROM Professor,
Vorlesung
WHERE Professor.Name <> Vorlesung.Titel
Das Ergebnis erhält die Kombinationen aller Professor
en und aller Vorlesung
en, wo der Name des Professor
s vom Titel der Vorlesung
abweicht – das sind einfach alle (keine Vorlesung
heißt wie ein Professor
):
Titel |
Name
|
---|---|
ET |
Tesla
|
ET |
Wirth
|
ET |
Urlauber
|
IT |
Tesla
|
IT |
Wirth
|
IT |
Urlauber
|
DB |
Tesla
|
DB |
Wirth
|
DB |
Urlauber
|
Linker äußerer Verbund (LEFT OUTER JOIN
)
SELECT Professor.PersNr,
Professor.Name,
Vorlesung.VorlNr,
Vorlesung.Titel
FROM Professor
LEFT OUTER JOIN Vorlesung
ON Professor.PersNr = Vorlesung.PersNr;
ergibt alle Datensätze der Tabelle Professor
verbunden mit den Datensätzen der Tabelle Vorlesung
, die den jeweils gleichen Wert im Feld PersNr
haben. Professor
en ohne Vorlesung sind enthalten, die Vorlesung
sspalten im Ergebnis haben dann den Wert NULL
. Vorlesung
en ohne Professor
sind nicht enthalten.
Die folgende Abfrage liefert nur diejenigen Datensätze, zu denen kein passender Datensatz im linken äußeren Verbund existiert (alle Professor
en, die keine Vorlesung
en halten):
SELECT Professor.PersNr,
Professor.Name
FROM Professor
LEFT OUTER JOIN Vorlesung
ON Professor.PersNr = Vorlesung.PersNr
WHERE Vorlesung.PersNr IS NULL;
Das Gleiche kann mittels einer Unterabfrage erreicht werden:
SELECT Professor.PersNr,
Professor.Name
FROM Professor
WHERE NOT EXISTS (SELECT *
FROM Vorlesung
WHERE PersNr = Professor.PersNr);
Gruppierung mit Aggregat-Funktionen (GROUP BY
)
SELECT Professor.PersNr,
Professor.Name,
COUNT(Vorlesung.PersNr) AS Anzahl
FROM Professor
LEFT OUTER JOIN Vorlesung
ON Professor.PersNr = Vorlesung.PersNr
GROUP BY Professor.Name,
Professor.PersNr;
zählt die Anzahl der Vorlesungen
pro Professor
mit Hilfe der Aggregat-Funktion COUNT
.
Bemerkung: COUNT(Professor.PersNr)
oder COUNT(*)
wären falsch (NULL
-Werte sollen nicht mitgezählt werden).
Zusammenfassung eines SELECT
Zusammengefasst kann man die wichtigsten Elemente einer SQL-SELECT
-Abfrage etwa so beschreiben:
SELECT [DISTINCT] Auswahlliste [AS Spaltenalias]
FROM Quelle [ [AS] Tabellenalias], evtl. mit JOIN-Verknüpfungen
[WHERE Where-Klausel]
[GROUP BY ein oder mehrere Group-by-Attribute]
[HAVING Having-Klausel]
[ORDER BY ein oder mehrere Sortierungsattribute mit [ASC|DESC]];
Erläuterung:
DISTINCT
: Gibt an, dass aus der Ergebnisrelation gleiche Ergebnistupel entfernt werden sollen. Es wird also jeder Datensatz nur einmal ausgegeben, auch wenn er mehrfach in der Tabelle vorkommt. Sonst liefert SQL eine Multimenge zurück.- Auswahlliste: Bestimmt, welche Spalten der Quelle auszugeben sind (
*
für alle) und ob Aggregatsfunktionen anzuwenden sind. Wie bei allen anderen Aufzählungen werden die einzelnen Elemente mit Komma (,
) voneinander getrennt. - Quelle: Gibt an, wo die Daten herkommen. Es können Relationen und Sichten angegeben werden und miteinander als kartesisches Produkt oder als Verbund (
JOIN
, ab SQL-92) verknüpft werden. Mit der zusätzlichen Angabe eines Namens können Relationen für die Abfrage umbenannt werden (vgl. Beispiele). WHERE
-Klausel: bestimmt Bedingungen, auch Filter genannt, unter denen die Daten ausgegeben werden sollen. In SQL ist hier auch die Angabe von Unterabfragen möglich, so dass SQL streng relational vollständig wird.GROUP BY
-Attribut: Legt fest, ob unterschiedliche Werte als einzelne Zeilen ausgegeben werden sollen (GROUP BY
= Gruppierung) oder aber die Feldwerte der Zeilen durch Aggregationen wie Addition (SUM
), Durchschnitt (AVG
), Minimum (MIN
), Maximum (MAX
) zu einem Ergebniswert zusammengefasst werden, der sich auf die Gruppierung bezieht.Having
-Klausel: Ist wie dieWHERE
-Klausel, nur dass sich die angegebene Bedingung auf das Ergebnis einer Aggregationsfunktion bezieht, zum BeispielHAVING SUM (Betrag) > 0
.- Sortierungsattribut: nach
ORDER BY
werden Attribute angegeben, nach denen sortiert werden soll. Die Standardvoreinstellung istASC
, das bedeutet aufsteigende Sortierung,DESC
ist absteigende Sortierung.
Mengenoperatoren können auf mehrere SELECT
-Abfragen angewandt werden, die gleich viele Attribute haben und bei denen die Datentypen der Attribute übereinstimmen:
UNION
: Vereinigt die Ergebnismengen. In einigen Implementierungen werden mehrfach vorkommende Ergebnistupel wie beiDISTINCT
entfernt, ohne dassUNION DISTINCT
geschrieben werden muss beziehungsweise darf.UNION ALL
: Vereinigt die Ergebnismengen. Mehrfach vorkommende Ergebnistupel bleiben erhalten. Einige Implementierungen interpretieren aberUNION
wieUNION ALL
und verstehen dasALL
möglicherweise nicht und geben eine Fehlermeldung aus.EXCEPT
: Liefert die Tupel, die in einer ersten, jedoch nicht in einer zweiten Ergebnismenge enthalten sind. Mehrfach vorkommende Ergebnistupel werden entfernt.MINUS:
Ein analoger Operator wieEXCEPT
, der von manchen SQL-Dialekten alternativ benutzt wird.INTERSECT
: Liefert die Schnittmenge zweier Ergebnismengen. Mehrfach vorkommende Ergebnistupel werden entfernt.