Einführung in SQL: WHERE-Klausel im Detail

Aus Wikibooks

Wechseln zu: Navigation, Suche


In diesem Kapitel werden die Einzelheiten der WHERE-Klausel genauer behandelt. Diese Angaben sind vor allem für den SELECT-Befehl, aber auch für UPDATE und DELETE von Bedeutung.

Die Beispiele beziehen sich auf den Anfangsbestand der Beispieldatenbank; auf die Ausgabe der selektierten Datensätze verzichte ich. Bitte probieren Sie alle Beispiele aus und nehmen Sie verschiedene Änderungen vor, um die Auswirkungen zu erkennen.

Inhaltsverzeichnis

[Bearbeiten] Allgemeine Hinweise

Die WHERE-Klausel ist (neben der Verknüpfung mehrerer Tabellen) der wichtigste Bestandteil des SELECT-Befehls: Je sorgfältiger die Auswahlbedingungen formuliert werden, desto genauer ist das Ergebnis der Abfrage.

Neben den hier erläuterten Varianten bietet jedes DBMS noch andere, z.B. STARTING WITH oder SIMILAR.

Anstelle konstanter Werte können auch passende Ausdrücke angegeben werden, z.B. Funktionen oder Unterabfragen.

Verwenden Sie bei den Beispielen möglichst immer auch die Umkehrung der Auswahl mit bzw. ohne NOT. Wie in Ausführliche SELECT-Struktur zur WHERE-Klausel angegeben, steht das NOT ggf. unmittelbar vor dem Parameter-Namen.


[Bearbeiten] Eine einzelne Bedingung

[Bearbeiten] Größenvergleich zweier Werte

Der einfachste Weg ist der direkte Vergleich zweier Werte, nämlich der Inhalt einer Spalte mit einem konstanten Wert. Dies ist möglich mit den folgenden Vergleichsoperatoren, und zwar für alle Datentypen, die verglichen werden können – Zahlen, Zeichenketten, Datumsangaben.

 =  <  >  <=  >=  <>

Beispiele:

Aufgabe

Suche einen Datensatz, bei dem der Wert in der Spalte ID gleich ist zu einem vorgegebenen Wert.

Crystal Clear app terminal.png SQL-Quelltext:

SELECT * FROM Versicherungsnehmer
 WHERE ID = 10;
Aufgabe

Suche Datensätze, bei denen der Name kleiner als 'B' ist, also mit 'A' anfängt.

Crystal Clear app terminal.png SQL-Quelltext:

SELECT * FROM Versicherungsnehmer
 WHERE Name < 'B';
Aufgabe

Suche Führerschein-Neulinge.

Führerschein-Neulinge
Crystal Clear app terminal.png SQL-Quelltext:

SELECT * FROM Versicherungsnehmer
 WHERE Fuehrerschein >= '01.01.2007';
Aufgabe

Suche Fahrzeugtypen mit kurzer Bezeichnung.

Crystal Clear app terminal.png SQL-Quelltext:

SELECT * FROM Fahrzeugtyp
 WHERE Char_Length(Bezeichnung) <= 3;

Bei diesen Vergleichen ist NOT zwar ebenfalls möglich; besser verständlich ist aber ein anderer passender Operator.


[Bearbeiten] BETWEEN AND – Werte zwischen zwei Grenzen

Mit der Bedingung BETWEEN <wert1> AND <wert2> wird direkt mit einem Bereich verglichen; die Grenzwerte gehören zum Bereich. Auch dies ist möglich für Zahlen, Zeichenketten, Datumsangaben.

Aufgabe

Suche Datensätze, bei denen die PLZ außerhalb eines Bereichs 45000...45999 liegt.

Crystal Clear app terminal.png SQL-Quelltext:

SELECT * FROM Versicherungsnehmer
 WHERE PLZ NOT BETWEEN '45000' AND '45999';


[Bearbeiten] LIKE – Ähnlichkeiten (1)

Die LIKE-Bedingung vergleicht Zeichenketten "ungenau": Der gesuchte Text soll als Wert in einer Spalte enthalten sein; dazu werden Wikipedia-logo.png Wildcards benutzt: Der Unterstrich '_' steht für ein beliebiges einzelnes Zeichen, das an der betreffenden Stelle vorkommen kann. Das Prozentzeichen '%' steht für eine beliebige Zeichenkette mit 0 oder mehr Zeichen.

Diese Bedingung wird vor allem in zwei Situationen gerne benutzt:

  • Der Suchbegriff ist sehr lang; dem Anwender soll es genügen, den Anfang einzugeben.
  • Der Suchbegriff ist nicht genau bekannt (z.B. nicht richtig lesbar).

Beispiele:

Aufgabe

Der Ortsname beginnt nicht mit 'B'; der Inhalt dahinter ist beliebig.

Crystal Clear app terminal.png SQL-Quelltext:

SELECT * FROM Versicherungsnehmer
 WHERE Ort NOT LIKE 'B%';
Aufgabe

Der Ortsname enthält irgendwo 'alt' mit beliebigem Inhalt davor und dahinter.

Crystal Clear app terminal.png SQL-Quelltext:

SELECT * FROM Versicherungsnehmer
 WHERE Ort LIKE '%alt%';
Aufgabe

Der Anfangsbuchstabe des Namens ist unklar, aber danach folgen 'ei'.

Crystal Clear app terminal.png SQL-Quelltext:

SELECT * FROM Versicherungsnehmer
 WHERE Name LIKE '_ei%';

Ein Problem haben wir, wenn eines der Wildcard-Zeichen Teil des Suchbegriffs sein soll. Dann muss dem LIKE-Parameter mitgeteilt werden, dass '%' bzw. '_' als "echtes" Zeichen zu verstehen ist. Das geschieht dadurch, dass ein spezielles Zeichen davor gesetzt wird und dieses Zeichen als Wikipedia-logo.png ESCAPE-Zeichen angegeben wird:

Aufgabe

Innerhalb der Beschreibung kommt die Zeichenfolge '10%' vor.

Crystal Clear app terminal.png SQL-Quelltext:

SELECT * FROM Schadensfall
 WHERE Beschreibung LIKE '%10\%%' ESCAPE '\';

Vergleichen Sie das Abfrageergebnis, wenn der ESCAPE-Parameter weggelassen wird oder wenn eines oder mehrere der Sonderzeichen im LIKE-Parameter fehlen.


[Bearbeiten] CONTAINS u.a. – Ähnlichkeiten (2)

Ein Problem des LIKE-Parameters ist die Verwendung der Wildcard-Zeichen '%' und '_', die man gerne vergisst oder (wie im letzten Beispiel) nicht genau genug beachtet. Deshalb gibt es verschiedene Vereinfachungen.

CONTAINS – in Firebird CONTAINING – prüft, ob eine Zeichenkette im Feldinhalt enthalten ist.

Teil der Beschreibung ist die Zeichenkette '10%'
Crystal Clear app terminal.png SQL-Quelltext:

SELECT * FROM Schadensfaelle
 WHERE Beschreibung CONTAINS '10%';

Bitte prüfen Sie in der Beschreibung Ihres DBMS, welche Möglichkeiten für Suche nach Ähnlichkeiten außerdem angeboten werden.


[Bearbeiten] IS NULL – null-Werte prüfen

Wie schon unter Relationale Datenbanken besprochen, haben NULL-Werte eine besondere Bedeutung. Mit den folgenden beiden Abfragen werden nicht alle Datensätze gefunden:

8 Mitarbeiter mit Mobil-Nummer
Crystal Clear app terminal.png SQL-Quelltext:

SELECT ID, Name, Vorname, Mobil
  FROM Mitarbeiter
 WHERE Mobil <> '';

10 Mitarbeiter ohne Mobil-Nummer
Crystal Clear app terminal.png SQL-Quelltext:

SELECT ID, Name, Vorname, Mobil
  FROM Mitarbeiter
 WHERE Mobil = '';

Nanu, es gibt doch 28 Mitarbeiter; wo sind die übrigen geblieben? Für diese Fälle gibt es mit IS NULL eine spezielle Abfrage:

10 Mitarbeiter ohne Angabe
Crystal Clear app terminal.png SQL-Quelltext:

SELECT ID, Name, Vorname, Mobil
  FROM Mitarbeiter
 WHERE Mobil IS NULL;

Der Vollständigkeit halber weise ich darauf hin, dass die folgende Abfrage tatsächlich die richtige Gegenprobe liefert:

18 Mitarbeiter mit irgendeiner Angabe (auch mit "leerer" Angabe)
Crystal Clear app terminal.png SQL-Quelltext:

SELECT ID, Name, Vorname, Mobil
  FROM Mitarbeiter
 WHERE Mobil IS NOT NULL;

Die folgende Abfrage liefert überhaupt kein Ergebnis, weil NULL eben kein Wert ist.

Crystal Clear app terminal.png SQL-Quelltext:

SELECT ID, Name, Vorname, Mobil
  FROM Mitarbeiter
 WHERE Mobil = NULL;

Es gibt keine einzelne Bedingung, die alle Datensätze ohne explizite Mobil-Angabe auf einmal angibt. Es gibt nur die Möglichkeit, die beiden Bedingungen "IS NULL" und "ist leer" zu verknüpfen:

20 Mitarbeiter ohne ausdrückliche Angabe
Crystal Clear app terminal.png SQL-Quelltext:

SELECT ID, Name, Vorname, Mobil
  FROM Mitarbeiter
 WHERE ( Mobil IS NULL ) OR ( Mobil = '' );

Beachten Sie auch bei "WHERE ... IS [NOT] NULL" die Bedeutung von NULL:

  • Bei Zeichenketten ist zu unterscheiden zwischen dem "leeren" String und dem NULL-Wert.
  • Bei Zahlen ist zu unterscheiden zwischen der Zahl "0" (null) und dem NULL-Wert.
  • Bei Datumsangaben ist zu unterscheiden zwischen einem vorhandenen Datum und dem NULL-Wert; ein Datum, das der Zahl 0 entspräche, gibt es nicht. (Man könnte allenfalls das kleinste mögliche Datum wie dem '01.01.0100' benutzen, aber dies ist bereits ein Datum.)


[Bearbeiten] IN – genauer Vergleich mit einer Liste

Der IN-Parameter vergleicht, ob der Inhalt einer Spalte in der angegebenen Liste enthalten ist. Die Liste kann mit beliebigen Datentypen arbeiten.

Aufgabe

Hole die Liste aller Fahrzeuge, deren Typen als "VW-Kleinwagen" registriert sind.

Crystal Clear app terminal.png SQL-Quelltext:

SELECT * FROM Fahrzeug
 WHERE Fahrzeugtyp_ID IN (1, 2);
Aufgabe

Suche nach einem Unfall Fahrzeuge mit einer von mehreren möglichen Farben.

Crystal Clear app terminal.png SQL-Quelltext:

SELECT * FROM Fahrzeuge
 WHERE Farbe IN ('ocker', 'gelb');

Vor allem das erste Beispiel wird sehr oft mit einer Unterabfrage versehen; vergleichen Sie dazu auch den folgenden Abschnitt zu EXISTS.

Aufgabe

Hole die Liste aller Fahrzeuge vom Typ 'Volkswagen'.

Crystal Clear app terminal.png SQL-Quelltext:

SELECT * FROM Fahrzeug
 WHERE Fahrzeugtyp_ID IN 
     ( SELECT ID FROM Fahrzeugtyp
        WHERE Hersteller_ID = 1 );

Dabei wird zuerst mit der Unterabfrage eine Liste aller Fahrzeugtypen-IDs für den Hersteller 1 (= Volkswagen) zusammengestellt; diese wird dann für den Vergleich über den IN-Parameter benutzt.


[Bearbeiten] EXISTS – schneller Vergleich mit einer Liste

Im Gegensatz zu den anderen Parametern der WHERE-Klausel arbeitet der EXISTS-Parameter nicht mit fest vorgegebenen Werten, sondern nur mit dem Ergebnis einer Abfrage, also einer Unterabfrage. Das letzte Beispiel zum IN-Parameter kann auch so formuliert werden:

Liste aller Fahrzeuge vom Typ 'Volkswagen'
Crystal Clear app terminal.png SQL-Quelltext:

SELECT * FROM Fahrzeug fz
 WHERE EXISTS
     ( SELECT * FROM Fahrzeugtyp ft
        WHERE ft.Hersteller_ID = 1
          AND fz.Fahrzeugtyp_ID = ft.ID );

Zu jedem Datensatz aus der Tabelle Fahrzeug wird zu dieser Fahrzeugtyp_ID eine Unterabfrage aus den Fahrzeugtypen erstellt: Wenn es dort einen Datensatz mit passender ID und Hersteller-ID 1 (= Volkswagen) gibt, gehört der Fahrzeug-Datensatz zur Auswahl, andernfalls nicht.

Da Unterabfragen zuerst ausgeführt werden, wird eine EXISTS-Prüfung in aller Regel schneller erledigt als die entsprechende IN-Prüfung: Bei EXISTS handelt es sich um eine Feststellung "ist überhaupt etwas vorhanden"; bei IN dagegen muss ein exakter Vergleich mit allen Werten einer Liste durchgeführt werden. Bei unserer kleinen Beispieldatenbank spielt das natürlich keine Rolle, aber bei einer "echten" Datenbank mit Millionen von Einträgen schon.


[Bearbeiten] Mehrere Bedingungen verknüpfen

Bei der WHERE-Klausel geht es darum festzustellen, ob ein bestimmter Datensatz Teil des Abfrageergebnisses ist oder nicht; bei der <search condition> handelt sich also um einen booleschen Ausdruck, d.h. einen Ausdruck, der einen der booleschen Werte WAHR oder FALSCH – TRUE bzw. FALSE – als Ergebnis hat. Nur bei einfachen Abfragen genügt dazu eine einzelne Bedingung; meistens müssen mehrere Bedingungen verknüpft werden (wie beim letzten Beispiel unter IS NULL).

Dazu gibt es die Wikipedia-logo.png booleschen Operatoren NOT, AND, OR.

[Bearbeiten] NOT als Wikipedia-logo.png Negation

Dieser Operator kehrt das Ergebnis um: aus TRUE wird FALSE, aus FALSE wird TRUE.

Siehe oben: keine Führerschein-Neulinge
Crystal Clear app terminal.png SQL-Quelltext:

SELECT * FROM Versicherungsnehmer
 WHERE NOT (Fuehrerschein >= '01.01.2007');


[Bearbeiten] AND als Wikipedia-logo.png Konjunktion

Eine Bedingung, die durch eine AND-Verknüpfung gebildet wird, ist genau dann TRUE, wenn beide (bzw. alle) Bestandteile TRUE sind.

Die nach Alphabet erste Hälfte der Versicherungsnehmer eines PLZ-Bereichs
Crystal Clear app terminal.png SQL-Quelltext:

SELECT ID, Name, Vorname, PLZ, Ort 
  FROM Versicherungsnehmer
 WHERE PLZ BETWEEN '45000' AND '45999'
   AND Name < 'K';


[Bearbeiten] OR als Wikipedia-logo.png Adjunktion

Eine Bedingung, die durch eine OR-Verknüpfung gebildet wird, ist genau dann TRUE, wenn mindestens ein Bestandteil TRUE ist; dabei ist es gleichgültig, ob die anderen Bestandteile TRUE oder FALSE sind.

Die nach Alphabet erste Hälfte der Versicherungsnehmer und alle eines PLZ-Bereichs
Crystal Clear app terminal.png SQL-Quelltext:

SELECT ID, Name, Vorname, PLZ, Ort 
  FROM Versicherungsnehmer
 WHERE PLZ BETWEEN '45000' AND '45999'
    OR Name < 'K';

Bitte beachten Sie, dass der normale Sprachgebrauch "alle ... und alle ..." sagt. Gemeint ist nach logischen Begriffen aber, dass <Bedingung 1> erfüllt sein muss ODER <Bedingung 2> oder beide.


[Bearbeiten] XOR als Wikipedia-logo.png Kontravalenz

Eine Bedingung, die durch eine XOR-Verknüpfung zweier Bedingungen gebildet wird, ist genau dann TRUE, wenn ein Bestandteil TRUE ist, aber der andere Bestandteil FALSE ist – "ausschließendes oder", "entweder - oder". Diese Verknüpfung gibt es selten, z.B. bei MySql; ich erwähne es der Vollständigkeit halber.

Die nach Alphabet erste Hälfte der Versicherungsnehmer oder alle eines PLZ-Bereichs
Crystal Clear app terminal.png SQL-Quelltext:

SELECT ID, Name, Vorname, PLZ, Ort 
  FROM Versicherungsnehmer
 WHERE PLZ BETWEEN '45000' AND '45999'
   XOR Name < 'K';

Bitte beachten Sie, dass hier der normale Sprachgebrauch "oder" sagt und "entweder ... oder" meint.

Anstelle von XOR kann immer eine Kombination verwendet werden:

( <Bedingung 1> AND ( NOT <Bedingung 2> ) ) OR ( <Bedingung 2> AND ( NOT <Bedingung 1> ) )


[Bearbeiten] Klammern benutzen oder weglassen?

Bereits unter Ausführliche SELECT-Struktur habe ich auf folgende Hierarchie hingewiesen:

  • NOT ist die engste Verbindung und wird vorrangig ausgewertet.
  • AND ist die nächststärkere Verbindung und wird danach ausgewertet.
  • OR ist die schwächste Verbindung und wird zuletzt ausgewertet.
  • Was in Klammern steht, wird vor allem anderen ausgewertet.

Bitte setzen Sie im folgenden Beispiel Klammern an anderen Stellen oder streichen Sie Klammern, und vergleichen Sie die Ergebnisse.

Crystal Clear app terminal.png SQL-Quelltext:

SELECT ID, Name, Vorname, PLZ, Ort 
  FROM Versicherungsnehmer
 WHERE NOT ( PLZ BETWEEN '45000' AND '45999'
             AND ( Name LIKE 'B%'
                OR Name LIKE 'K%'
                OR NOT Name CONTAINING 'ei'
                 )
           )
 ORDER BY PLZ, Name;

Sie werden ziemlich unterschiedliche Ergebnisse feststellen. Es empfiehlt sich deshalb, an allen sinnvollen Stellen Klammern zu setzen – auch dort, wo sie nicht erforderlich sind – und das, was zusammengehört, durch Einrückungen sinnvoll zu gliedern.


[Bearbeiten] Zusammenfassung

In diesem Kapitel lernten wir neben dem Vergleich von Werten viele Möglichkeiten kennen, mit denen Bedingungen für Abfragen festgelegt werden können:

  • Mit BETWEEN AND werden Werte innerhalb eines Bereichs geprüft.
  • Mit LIKE und CONTAINS werden Werte gesucht, die mit vorgegebenen Werten teilweise übereinstimmen.
  • Mit IS NULL werden null-Werte gesucht.
  • Mit IN und EXISTS werden Spaltenwerte mit einer Liste verglichen.

Mit AND, OR, NOT werden Bedingungen zusammengefasst.


[Bearbeiten] Übungen


Persönliche Werkzeuge