DML (1) – Daten abfragen
Eine Datenbank enthält eine Vielzahl von verschiedenen Daten. Abfragen dienen dazu, bestimmte Daten aus der Datenbank auszugeben. Dabei kann die Ergebnismenge entsprechend den Anforderungen eingegrenzt und genauer gesteuert werden.
Dieser Teilbereich der Data Manipulation Language (DML) behandelt den SQL-Befehl SELECT, mit dem Abfragen durchgeführt werden.
Zunächst geht es um einfache Abfragen. Vertieft wird der SELECT-Befehl unter „Abfragen für Fortgeschrittene“ behandelt, beginnend mit Ausführliche SELECT-Struktur; unten im Abschnitt Ausblick auf komplexe Abfragen gibt es Hinweise auf diese weiteren Möglichkeiten.
SELECT – Allgemeine Hinweise
[Bearbeiten]SELECT ist in der Regel der erste und wichtigste Befehl, den der SQL-Neuling kennenlernt, und das aus gutem Grund: Man kann damit keinen Schaden anrichten. Ein Fehler im Befehl führt höchstens zu einer Fehlermeldung oder dem Ausbleiben des Abfrageergebnisses, aber nicht zu Schäden am Datenbestand. Trotzdem erlaubt der Befehl das Herantasten an die wichtigsten Konzepte von DML, und die anderen Befehle müssen nicht mehr so intensiv erläutert werden.
Dieser Befehl enthält die folgenden Bestandteile („Klauseln“ genannt).
SELECT [DISTINCT | ALL] <spaltenliste> | * FROM <tabellenliste> [WHERE <bedingungsliste>] [GROUP BY <spaltenliste> ] [HAVING <bedingungsliste>] [UNION <select-ausdruck>] [ORDER BY <spaltenliste> ] ;
Die Reihenfolge der Klauseln ist fest im SQL-Standard vorgegeben. Klauseln, die in [ ] stehen, sind nicht nötig, sondern können entfallen; der Name des Befehls und die FROM-Angaben sind unbedingt erforderlich, das Semikolon als Standard empfohlen.
Die wichtigsten Teile werden in den folgenden Abschnitten erläutert.
Die folgenden Punkte verlangen dagegen vertiefte Beschäftigung mit SQL:
- GROUP BY – Daten gruppieren
- HAVING – weitere Einschränkungen
- UNION – mehrere Abfragen verbinden
Diese Punkte sowie weitere Einzelheiten zu den wichtigsten Bestandteilen werden in Ausführliche SELECT-Struktur und anderen „fortgeschrittenen“ Kapiteln behandelt.
Die Beispiele beziehen sich auf den Anfangsbestand der Beispieldatenbank; auf die Ausgabe der selektierten Datensätze wird in der Regel verzichtet. Bitte probieren Sie alle Beispiele aus und nehmen Sie verschiedene Änderungen vor, um die Auswirkungen zu erkennen.
Die einfachste Abfrage
[Bearbeiten]Gesucht wird der Inhalt der Tabelle der Fahrzeughersteller mit all ihren Spalten und Datensätzen (Zeilen).
SELECT * FROM Fahrzeughersteller;
Schauen wir uns das Beispiel etwas genauer an:
- Die beiden Begriffe SELECT und FROM sind SQL-spezifische Bezeichner.
- Fahrzeughersteller ist der Name der Tabelle, aus der die Daten selektiert und ausgegeben werden sollen.
- Das Sternchen, Asterisk genannt, ist eine Kurzfassung für „alle Spalten“.
Eingrenzen der Spalten
[Bearbeiten]Nun wollen wir nur bestimmte Spalten ausgeben, nämlich eine Liste aller Fahrzeughersteller; das Land interessiert uns dabei nicht. Dazu müssen zwischen den SQL-Bezeichnern SELECT und FROM die auszugebenden Spalten angegeben werden. Sind es mehrere, dann werden diese durch jeweils ein Komma getrennt.
So erhält man die Namensliste aller Fahrzeughersteller:
SELECT Name FROM Fahrzeughersteller;
Folgendes Beispiel gibt die beiden Spalten für Name und Land des Herstellers aus. Die Spalten werden durch Komma getrennt.
SELECT Name, Land FROM Fahrzeughersteller;
Für die Ausgabe kann eine (abweichende) Spaltenüberschrift festgelegt werden. Diese wird als Spalten-Alias bezeichnet. Der Alias kann dem Spaltennamen direkt folgen oder mit dem Bindewort AS angegeben werden. Das vorherige Beispiel kann also wie folgt mit dem Alias Hersteller für Name (ohne AS) und dem Alias Staat für Land (mit AS) versehen werden:
SELECT Name Hersteller, Land AS Staat
FROM Fahrzeughersteller;
DISTINCT – Keine doppelten Zeilen
[Bearbeiten]Gesucht wird die Liste der Herstellerländer:
SELECT Land
FROM Fahrzeughersteller;
Dabei stellen wir fest, dass je Hersteller eine Zeile ausgegeben wird. Somit erscheint beispielweise 'Deutschland' mehrmals. Damit keine doppelten Zeilen ausgegeben werden, wird DISTINCT vor den Spaltennamen in das SQL-Statement eingefügt:
SELECT DISTINCT Land
FROM Fahrzeughersteller;
Damit erscheint jedes Herstellerland nur einmal in der Liste.
Die Alternative zu DISTINCT ist übrigens das in der Syntax genannte ALL: alle Zeilen werden gewünscht, ggf. auch doppelte. Dies ist aber der Standardwert, ALL kann weggelassen werden.
Vertiefte Erläuterungen sind unter Nützliche Erweiterungen zu finden.
WHERE – Eingrenzen der Ergebnismenge
[Bearbeiten]Fast immer soll nicht der komplette Inhalt einer Tabelle ausgegeben werden. Dazu wird die Ergebnismenge mittels Bedingungen in der WHERE-Klausel eingegrenzt, welche nach dem Tabellennamen im SELECT-Befehl steht.
Eine Bedingung ist ein logischer Ausdruck, dessen Ergebnis WAHR oder FALSCH ist. In diesen logischen Ausdrücken werden die Inhalte der Spalten (vorwiegend) mit konstanten Werten verglichen. Hierbei stehen verschiedene Operatoren zur Verfügung, vor allem:
= gleich <> ungleich; seltener auch: != < kleiner als <= kleiner als oder gleich > größer als >= größer als oder gleich
Bedingungen können durch die logischen Operatoren OR und AND und die Klammern () verknüpft werden. Je komplizierter solche Verknüpfungen werden, desto sicherer ist es, die Bedingungen durch Klammern zu gliedern. Mit diesen Mitteln lässt sich die Abfrage entsprechend eingrenzen.
Beispielsweise sollen alle Hersteller angezeigt werden, die ihren Sitz in Schweden oder Frankreich haben:
SELECT * FROM Fahrzeughersteller
WHERE ( Land = 'Schweden' ) OR ( Land = 'Frankreich' );
Hinter der WHERE-Klausel kann man also eine oder mehrere (mit einem booleschen Operator verknüpft) Bedingungen einfügen. Jede einzelne besteht aus dem Namen der Spalte, deren Inhalt überprüft werden soll, und einem Wert, wobei beide mit einem Vergleichsoperator verknüpft sind.
In einer anderen Abfrage sollen alle Fahrzeughersteller angezeigt werden, die außerhalb Deutschlands sitzen. Jetzt könnte man alle anderen Fälle einzeln in der WHERE-Klausel auflisten, oder man dreht einfach den Vergleichsoperator um.
SELECT * FROM Fahrzeughersteller
WHERE Land <> 'Deutschland';
Das Gleichheitszeichen aus der oberen Abfrage wurde durch das Ungleichheitszeichen ersetzt. Dadurch werden jetzt alle Hersteller ausgegeben, deren Sitz ungleich Deutschland ist.
Vertiefte Erläuterungen sind unter WHERE-Klausel im Detail zu finden.
ORDER BY – Sortieren
[Bearbeiten]Nachdem wir nun die Zeilen und Spalten der Ergebnismenge eingrenzen können, wollen wir die Ausgabe der Zeilen sortieren. Hierfür wird die ORDER BY-Klausel genutzt. Diese ist die letzte im SQL-Befehl vor dem abschließenden Semikolon und enthält die Spalten, nach denen sortiert werden soll.
So lassen wir uns die Liste der Hersteller nach dem Namen sortiert ausgeben:
SELECT * FROM Fahrzeughersteller
ORDER BY Name;
Anstatt des Spaltennamens kann auch die Nummer der Spalte genutzt werden. Mit dem folgenden Statement erreichen wir also das gleiche Ergebnis, da Name die zweite Spalte in unserer Ausgabe ist:
SELECT * FROM Fahrzeughersteller
ORDER BY 2;
Die Angabe nach Spaltennummer ist unüblich; sie wird eigentlich höchstens dann verwendet, wenn die Spalten genau aufgeführt werden und komplizierte Angaben – z. B. Berechnete Spalten – enthalten.
Die Sortierung erfolgt standardmäßig aufsteigend; das kann auch durch ASC ausdrücklich angegeben werden. Die Sortierreihenfolge kann mit dem DESC-Bezeichner in absteigend verändert werden.
SELECT * FROM Fahrzeughersteller
ORDER BY Name DESC;
In SQL kann nicht nur nach einer Spalte sortiert werden. Es können mehrere Spalten zur Sortierung herangezogen werden. Hierbei kann für jede Spalte eine eigene Regel verwendet werden. Dabei gilt, dass die Regel zu einer folgend angegebenen Spalte der Regel zu der vorig angegebenen Spalte untergeordnet ist. Bei der Sortierung nach Land und Name wird also zuerst nach dem Land und dann je Land nach Name sortiert. Eine Neusortierung nach Name, die jene Sortierung nach Land wieder verwirft, findet also nicht statt.
Der folgende Befehl liefert die Hersteller – zuerst absteigend nach Land und dann aufsteigend sortiert nach dem Namen – zurück.
SELECT * FROM Fahrzeughersteller
ORDER BY Land DESC, Name ASC;
FROM – Mehrere Tabellen verknüpfen
[Bearbeiten]In fast allen Abfragen werden Informationen aus mehreren Tabellen zusammengefasst. Die sinnvolle Speicherung von Daten in getrennten Tabellen ist eines der Merkmale eines relationalen DBMS; deshalb müssen die Daten bei einer Abfrage nach praktischen Gesichtspunkten zusammengeführt werden.
Traditionell mit FROM und WHERE
[Bearbeiten]Beim „traditonellen“ Weg werden dazu einfach alle Tabellen in der FROM-Klausel aufgeführt und durch jeweils eine Bedingung in der WHERE-Klausel verknüpft.
Ermittle die Angaben der Mitarbeiter, deren Abteilung ihren Sitz in Dortmund oder Bochum hat.
SELECT mi.Name,
mi.Vorname,
mi.Raum,
ab.Ort
FROM Mitarbeiter mi, Abteilung ab
WHERE mi.Abteilung_ID = ab.ID
AND ab.Ort in ('Dortmund', 'Bochum')
ORDER BY mi.Name, mi.Vorname;
Es werden also Informationen aus den Tabellen Mitarbeiter (Name und Raum) sowie Abteilung (Ort) gesucht. Für die Verknüpfung der Tabellen werden folgende Bestandteile benötigt:
- In der FROM-Klausel stehen die benötigten Tabellen.
- Zur Vereinfachung wird jeder Tabelle ein Kürzel als Tabellen-Alias zugewiesen.
- In der Spaltenliste wird jede einzelne Spalte mit dem Namen der betreffenden Tabelle bzw. dem Alias verbunden. (Der Tabellenname bzw. Alias kann sehr oft weggelassen werden; aber schon wegen der Übersichtlichkeit sollte er immer benutzt werden.)
- Die WHERE-Klausel enthält die Verknüpfungsbedingung „mi.Abteilung_ID = ab.ID“ – zusätzlich zur Einschränkung nach dem Sitz der Abteilung.
Jede Tabelle in einer solchen Abfrage benötigt mindestens eine direkte Verknüpfung zu einer anderen Tabelle. Alle Tabellen müssen zumindest indirekt miteinander verknüpft sein. Falsche Verknüpfungen sind eine häufige Fehlerquelle.
Vertiefte Erläuterungen sind unter Einfache Tabellenverknüpfung zu finden.
Modern mit JOIN...ON
[Bearbeiten]Beim „modernen“ Weg wird eine Tabelle in der FROM-Klausel aufgeführt, nämlich diejenige, die als wichtigste oder „Haupttabelle“ der Abfrage angesehen wird. Eine weitere Tabelle wird durch JOIN und eine Bedingung in der ON-Klausel verknüpft.
Das obige Beispiel sieht dann so aus:
SELECT mi.Name,
mi.Vorname,
mi.Raum,
ab.Ort
FROM Mitarbeiter mi
JOIN Abteilung ab
ON mi.Abteilung_ID = ab.ID
WHERE ab.Ort in ('Dortmund', 'Bochum')
ORDER BY mi.Name, mi.Vorname;
Für die Verknüpfung der Tabellen werden folgende Bestandteile benötigt:
- In der FROM-Klausel steht eine der benötigten Tabellen.
- In der JOIN-Klausel steht jeweils eine weitere Tabelle.
- Die ON-Klausel enthält die Verknüpfungsbedingung „mi.Abteilung_ID = ab.ID“.
- Die WHERE-Klausel beschränkt sich auf die wirklich gewünschten Einschränkungen für die Ergebnismenge.
Ein Tabellen-Alias ist wiederum für alle Tabellen sinnvoll. In der Spaltenliste und auch zur Sortierung können alle Spalten aller Tabellen benutzt werden.
Vertiefte Erläuterungen sind unter Arbeiten mit JOIN zu finden.
Ausblick auf komplexe Abfragen
[Bearbeiten]Das folgende Beispiel ist erheblich umfangreicher und geht über „Anfängerbedürfnisse“ weit hinaus. Es zeigt aber sehr schön, was alles mit SQL möglich ist:
Gesucht werden die Daten der Versicherungsnehmer im Jahr 2008, und zwar die Adresse, die Höhe des Gesamtschadens und die Anzahl der Schadensfälle.
select vn.Name,
vn.Vorname,
vn.Strasse,
vn.Hausnummer as HNR,
vn.PLZ,
vn.Ort,
SUM(sf.Schadenshoehe) as Gesamtschaden,
COUNT(sf.ID) as Anzahl
from Versicherungsnehmer vn
join Versicherungsvertrag vv
on vv.Versicherungsnehmer_ID = vn.ID
join Fahrzeug fz
on fz.ID = vv.Fahrzeug_ID
join Zuordnung_SF_FZ zu
on zu.Fahrzeug_ID = fz.ID
join Schadensfall sf
on sf.ID = zu.Schadensfall_ID
where EXTRACT(YEAR from sf.Datum) = 2008
group by vn.Name, vn.Vorname, vn.Strasse, vn.Hausnummer, vn.PLZ, vn.Ort
order by Gesamtschaden, Anzahl;
NAME VORNAME STRASSE HNR PLZ ORT GESAMTSCHADEN ANZAHL
---------------------- -------- --------------- --- ----- ------------- ------------- ------
Heckel Obsthandel GmbH Gahlener Str. 40 46282 Dorsten 1.438,75 1
Antonius Bernhard Coesfelder Str. 23 45892 Gelsenkirchen 1.983,00 1
Hierbei kommen die Funktionen SUM (Summe) und COUNT (Anzahl) zum Einsatz. Diese können nur eingesetzt werden, wenn die Datenmenge richtig gruppiert wurde. Deshalb wird mit GROUP BY das Datenmaterial nach allen verbliebenen, zur Ausgabe vorgesehenen, Datenfeldern gruppiert.
Vertiefte Erläuterungen sind zu finden unter Funktionen sowie Gruppierungen.
Zusammenfassung
[Bearbeiten]In diesem Kapitel lernten wir die Grundlagen eines SELECT-Befehls kennen:
- SELECT-Befehle werden zur Abfrage von Daten aus Datenbanken genutzt.
- Die auszugebenden Spalten können festgelegt werden, indem die Liste der Spalten zwischen den Bezeichnern SELECT und FROM angegeben wird.
- Mit DISTINCT werden identische Zeilen in der Ergebnismenge nur einmal ausgegeben.
- Die Ergebnismenge wird mittels der WHERE-Klausel eingegrenzt.
- Die WHERE-Klausel enthält logische Ausdrücke. Diese können mit AND und OR verknüpft werden.
- Mittels der ORDER BY-Klausel kann die Ergebnismenge sortiert werden.
Die Reihenfolge innerhalb eines SELECT-Befehls ist zu beachten. SELECT und FROM sind hierbei Pflicht, das abschließende Semikolon als Standard empfohlen. Alle anderen Klauseln sind optional.
Übungen
[Bearbeiten]Hinweis: Der direkte Sprung zur jeweiligen Lösung funktioniert erst, wenn die Lösung sichtbar ist.
Bei den Übungen 2 ff. ist jeweils eine Abfrage zur Tabelle Abteilung zu erstellen.
Übung 1 | Pflichtangaben | Zur Lösung |
Welche Bestandteile eines SELECT-Befehls sind unbedingt erforderlich und können nicht weggelassen werden?
Übung 2 | Alle Angaben | Zur Lösung |
Geben Sie alle Informationen zu allen Abteilungen aus.
Übung 3 | Angaben mit Einschränkung | Zur Lösung |
Geben Sie alle Abteilungen aus, deren Standort Bochum ist.
Übung 4 | Angaben mit Einschränkungen | Zur Lösung |
Geben Sie alle Abteilungen aus, deren Standort Bochum oder Essen ist. Hierbei soll nur der Name der Abteilung ausgegeben werden.
Übung 5 | Abfrage mit Sortierung | Zur Lösung |
Geben Sie nur die Kurzbezeichnungen aller Abteilungen aus. Hierbei sollen die Abteilungen nach den Standorten sortiert werden.
Lösung zu Übung 1 | Pflichtangaben | Zur Übung |
SELECT, Spaltenliste oder '*', FROM, Tabellenname.
Lösung zu Übung 2 | Alle Angaben | Zur Übung |
select * from Abteilung;
Lösung zu Übung 3 | Angaben mit Einschränkung | Zur Übung |
select * from Abteilung
where Ort = 'Bochum';
Lösung zu Übung 4 | Angaben mit Einschränkungen | Zur Übung |
select Bezeichnung from Abteilung
where Ort = 'Bochum' or Ort = 'Essen';
Alternativ ist es auch so möglich:
select Bezeichnung from Abteilung
where Ort in ('Bochum', 'Essen');
Lösung zu Übung 5 | Abfrage mit Sortierung | Zur Übung |
select Kuerzel from Abteilung
order by Ort;