DML (1) – Daten abfragen

Aus Wikibooks
Zur Navigation springen Zur Suche springen

Seitentitel: Einführung in SQL: DML (1) - Daten abfragen
(Einführung in SQL: 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]

Aufgabe

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.

Aufgabe

So erhält man die Namensliste aller Fahrzeughersteller:

SELECT Name FROM Fahrzeughersteller;
Aufgabe

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]

Aufgabe

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.

Aufgabe

Beispielsweise sollen alle Hersteller angezeigt werden, die ihren Sitz in Schweden oder Frankreich haben:

SELECT * FROM Fahrzeughersteller
 WHERE ( Land = 'Schweden' ) OR ( Land = 'Frankreich' );
Auf die Klammern kann hier verzichtet werden.

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.

Aufgabe

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.

Aufgabe

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.

Aufgabe

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.

Aufgabe

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:

Aufgabe

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;
Crystal Clear app terminal.png Ausgabe
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ösungen

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;