Sql-und-Xml - Home

Sql-Tutorial

Mit WHERE wenige Zeilen auswählen

Die SELECT-Anweisung liefert eine virtuelle Tabelle, bestehend aus Zeilen und Spalten zurück. Der nach FROM folgende WHERE-Abschnitt kann Spaltennamen verwenden, um Bedingungen festzulegen. Für jede Zeile wird geprüft, ob die durch den Spaltennamen festgelegte Zelle die Bedingung erfüllt. Falls dies der Fall ist, wird die Zeile zur Ausgabe hinzugefügt, ansonsten wird diese Zeile nicht zum Resultset ergänzt.

Syntax

  • SELECT ...
    FROM ...
    WHERE <Bedingung 1> [<logischer Operator> <Bedingung 2>]
    Es kann entweder nur eine Bedingung geben. Oder es werden mehrere Bedingungen angegeben, welche mit logischen Operatoren (NOT, AND, OR) miteinander verknüpft sind.
  • Zulässige Vergleichsoperatoren zwischen Spaltennamen und Ausdrücken, Konstanten und weiteren Spaltennamen:
    =
    Gleichheit
    <>
    verschieden
    <
    kleiner
    >
    größer
    <=
    kleiner oder gleich
    >=
    größer oder gleich
    IS NULL
    prüft, ob die Zelle leer ist
    IS NOT NULL
    prüft, ob die Zelle einen Wert enthält
    Between
    Zwischen zwei Werten liegend
    In
    prüft, ob der linke Ausdruck in einem der rechten vorkommt
    Like
    Vergleich auf Textmuster
    Exists
    prüft, ob die folgende Unterabfrage mindestens eine Zeile zurückliefert
  • Zulässige logische Operatoren, die Ausdrücke mit Vergleichsoperatoren verknüpfen:
    NOT
    der folgende Ausdruck darf nicht erfüllt sein
    AND
    beide Bedingungen müssen erfüllt sein
    OR
    mindestens eine Bedingung muß erfüllt sein

Beispiele:

  1. Select A.*
    FROM ARTIKEL As A
    WHERE A.A_NR = 11
    Wählt die Zeile aus, bei welcher die Zelle A_NR den Wert 11 hat. Hier ist eine Bedingung und kein logischer Operator angegeben.
  2. WHERE NOT A.A_NR = 11
    WHERE A.A_NR <> 11
    Wählt alle Zeilen aus, deren A_NR verschieden von 11 und nicht leer (Not Null) ist.
  3. WHERE A_PREIS IS NULL
    Wählt jene Zeilen aus, bei welchen derzeit kein Preis definiert ist, bei denen die Zelle A_PREIS also leer ist. Beachten Sie, daß eine Zelle mit dem Wert 0 nicht leer ist, sondern den Wert 0 enthält. Ebenso ist bei Zellen mit Text die Belegung mit einer leeren Zeichenfolge (A_NAME = "" bzw. '') verschieden von der Zuweisung A_NAME = NULL bzw. der Abfrage A_NAME IS NULL.
  4. WHERE A.A_NAME = 'Oberhemd' And A.A_PREIS < 40.00
    Dies wählt nur jene Zeilen aus, bei denen sowohl der Wert in A_NAME gleich 'Oberhemd' und der Wert in A_PREIS kleiner als 40.00 ist. Es wird nur die Zeile mit A_NR = 12 ausgewählt.
  5. WHERE A.A_NAME = 'Oberhemd' Or A.A_PREIS > 40.00
    Dies wählt jene Zeilen aus, bei denen der Wert in A_NAME gleich 'Oberhemd' oder der Wert in A_PREIS größer als 40.00 ist. Die einzigste Zeile, die einen Preis < 40.00 hat, beschreibt ein 'Oberhemd', so daß von dieser Abfrage alle vier Zeilen zurückgegeben werden.
  6. WHERE A.A_PREIS BETWEEN 39.8 AND 100.00
    Listet die beiden Zeilen auf, deren Preis zwischen 39.8 und 100.00 liegt. Die Randwerte werden mitgezählt, deshalb ist die Zeile A_NR = 12 im Ergebnis enthalten. Beachten Sie, daß das AND zum BETWEEN gehört und hier keine logische Bedeutung hat.
  7. WHERE 39.8 <= A.A_PREIS And A.A_PREIS <= 100
    Diese Version ist gleichwertig zur vorherigen Version.
  8. WHERE A.A_NAME IN ('Hose', 'Mantel', 'Strümpfe')
    Vergleicht den Wert von A_NAME mit jedem der in der Klammer angegebenen Werten. Stimmt er mit einem dieser überein, so wird die betreffende Zeile ausgegeben. Der Ausdruck ist gleichwertig zu
    WHERE A.A_NAME = 'Hose' OR
    	A.A_NAME = 'Mantel' OR
    	A.A_NAME = 'Strümpfe'
    Rechts kann, wie hier, eine Liste von Konstanten, berechneten Werten oder eine Unterabfrage notiert werden. Die Unterabfrage muß eine Spalte zurückliefern.
  9. WHERE 0 = 1
    oder
    WHERE FALSE
    Dieser Ausdruck liefert immer False zurück, es werden also keine Zeilen ausgewählt. Dies kann verwendet werden, falls nur die Spaltennamen gewünscht sind. Analog liefert 0 = 0 oder TRUE alle Zeilen zurück, so daß eine solche WHERE-Klausel redundant ist.
  10. Textvergleiche mit LIKE
    SELECT V.* FROM VERTRETER
    WHERE V.V_NAME LIKE 'Me_er, Franz'
    Mit LIKE können Zellen gegen Textmuster geprüft werden, ohne daß eine vollständige Übereinstimmung notwendig ist. Der Unterstrich (_) fungiert als Platzhalter für ein Zeichen, so daß der obige Ausdruck sowohl 'Meyer, Franz' als auch 'Meier, Franz' findet.
    WHERE A.V_NAME LIKE 'Me%'
    Das Prozentzeichen (%) schließt 0 bis mehrere Zeichen ein, so daß aus der Beispieldatenbank sowohl 'Meier, Franz' als auch 'Meyer, Emil' gefunden wird.
  11. Suche nach den Sonderzeichen '_' und '%': Wenn Sie nach diesen Sonderzeichen selbst suchen möchten, dann setzen Sie diese in eckige Klammern ([]). Damit wird die eckige Klammer selbst zum Sonderzeichen, so daß auch eine Suche nach einer eckigen Klammer den Einschluß erfordert. Ansonsten erlauben eckige Klammern das Angeben eines Bereiches. Beispiel:
    WHERE <Spaltenname> LIKE '%Tulpen[_]und[_]Zwiebeln%'
    findet 'Hier gibt es Tulpen_und_Zwiebeln', nicht jedoch 'Hier gibt es Tulpen-und-Zwiebeln'. Entfernt man die Eckklammern, werden beide Einträge ausgegeben.
    WHERE <Spaltenname> LIKE 'Mayer [5-7]'
    WHERE <Spaltenname> LIKE 'Mayer [567]'
    findet 'Mayer 5', 'Mayer 6', 'Mayer 7', nicht jedoch 'Mayer 8'
    WHERE <Spaltenname> LIKE 'Mayer [[]5]'
    findet 'Mayer [5]'
  12. Mit Exists prüfen, ob eine Unterabfrage Werte enthält:
    SELECT A.A_NR
    FROM ARTIKEL As A
    WHERE EXISTS
    	(SELECT B.UMSATZ_NR
    	FROM UMSATZ As B
    	WHERE B.A_NR = A.A_NR)
    
    Diese Abfrage liefert jene Artikel einmal (!) zurück, für die es Einträge in der Tabelle 'Umsatz' gibt. Diese Abfrage erzeugt dasselbe Ergebnis wie:
    SELECT DISTINCT A.A_NR
    FROM ARTIKEL As A INNER JOIN UMSATZ As U
    ON A.A_NR = U.A_NR
    Nur wird die letztere Abfrage in der Regel teurer sein, da zunächst alle passenden Zeilen gesucht und mehrfache Einträge anschließend mit DISTINCT entfernt werden. EXISTS bricht dagegen ab, falls bereits eine einzige Zeile gefunden wurde.

Bemerkungen

  • Zur Suche nach ganzen Zahlen werden diese direkt notiert. Für Zahlen mit Nachkommastellen ist der Punkt das gültige Trennzeichen (A_Preis > 99.99). Textkonstanten werden in einfache Hochkommata (') gesetzt. Soll nach einem einfachen Hochkomma gesucht werden, so genügt es, dieses zu verdoppeln:
    WHERE V.V_Name = 'O''Neil'
    findet
    O'Neil
  • Grundsätzlich gilt, daß jeder Vergleich mit einem Operator (NOT, =, <, >, IN) auf NULL ausgewertet wird, falls einer der beiden Ausdrücke NULL ist. Damit liefert auch die Verneinung eines solchen Ausdrucks NULL. Damit wird eine gesamte Menge von Zeilen mit NULL-Zellen nicht vollständig durch einen Vergleich und dessen Verneinung ausgeschöpft.
  • WHERE A.A_PREIS = 10.00
    ...
    UNION
    ...
    WHERE A.A_PREIS <> 10.00
    liefert alle Zeilen mit Preis, jedoch nicht jene Artikel, für die kein Preis definiert ist, bei welchen die A_PREIS-Zelle leer ist. Denn bei einer leeren Zelle kann keine der obigen Bedingungen positiv geprüft werden.
  • Ein Beispiel mit einem logischen Operator:
    SELECT A.* FROM ARTIKEL AS A
    WHERE A.A_NAME = 'Hose'
    
    UNION
    
    SELECT A.* FROM ARTIKEL AS A
    WHERE NOT A.A_NAME = 'Hose'
    Im Rahmen von jedem Logik-Kurs wird Ihnen mitgeteilt, daß diese Abfrage sämtliche Zeilen liefert, hier also 4 Zeilen ausgibt. Löschen Sie anschließend testweise eine Zelle der Spalte A_NAME, etwa eine Zelle mit dem Wert 'Oberhemd'. Löschen Sie nur die Zelle, nicht die Zeile. Führen Sie anschließend die Abfrage erneut aus, so werden Sie nur drei Ergebniszeilen erhalten.
  • Operatorreihenfolge: Ein Vergleich mit = bindet am stärksten, so daß ein Ausdruck
    A_NAME = 11 Or A_PREIS > 100
    wie gewünscht interpretiert wird:
    (A_NAME = 11) Or (A_PREIS > 100)
    Verwenden Sie verschiedene logische Operatoren in einem WHERE-Ausdruck, so nutzen Sie am besten Klammern. Dies ist für jeden, der den Code später bearbeitet und die genaue Operator-Reihenfolge nicht weiß, die sicherste Lösung, damit sich nicht unbeabsichtigte Fehler einschleichen.

    Betrachten Sie den folgenden Ausdruck:
    WHERE A.A_NR BETWEEN 11 AND 10 OR 15
    Der erste Ausdruck ist für A_NR = 11 zumindest für Access in Sql-Interaktiv-lernen erfüllt, so daß mit einem Datensatz zu rechnen wäre. Da AND stärker bindet als OR und AND zu BETWEEN gehört, wird der Ausdruck tatsächlich jedoch so ausgewertet:
    WHERE (A.A_NR BETWEEN 11 AND 10) OR (15)
    Der Ausdruck (15) ist verschieden von 0, damit in den meisten Datenbank-Systemen wahr. Also handelt es sich um eine Konstante, so daß alle Zeilen ausgegeben werden.
  • Platzhaltersuche bei Access: Werden in Access über die gewöhnliche Programmierumgebung Abfragen erstellt, so müssen entgegen den oben genannten Konventionen für die Suche nach einem einzelnen Zeichen das '?', für die Suche nach mehreren Zeichen '*' verwendet werden. In diesem Fall wird das DAO-Modell (Data Access Objects) genutzt, welches einen Non-Standard - Sql-Dialekt implementiert. Wird dagegen auf eine Access-Datenbank über eine der Programmierschnittstellen ADO oder .NET zugegriffen, so sind die Standard-Zeichen '_' und '%' zu verwenden. Das Sql-Interaktiv-lernen verwendet .NET-Zugriffstechniken, so daß hier der Standard einzusetzen ist.
  • Anstatt eines Ausdrucks der Form
    <Spaltenname> = <Wert>
    kann rechts auch entweder ein anderer Spaltenname oder eine eigenständige in Klammern stehende Select-Abfrage angegeben werden. Diese muß genau eine Zelle zurückliefern. Ebenso kann bei einem Ausdruck der Form
    <Spaltenname> IN (<Unterabfrage mit einer Spalte>)
    eine Unterabfrage eingesetzt werden, die genau eine Spalte zurückliefert. Beispiele hierzu finden Sie im Abschnitt zu Unterabfragen.
  • EXISTS kann beim Sql-Server ressourcenschonend bsp. am Anfang eines Scripts dazu verwendet werden, um zu prüfen, ob ein Objekt existiert, um es gegebenenfalls zu löschen:
    If (Exists
    	(Select A.Table_Name
    	From Information_Schema.Tables As A
    	Where A.Table_Name = 'Artikel')
        )
        Drop Table Artikel
    Diese Technik ist jedem Group By bzw. Count(*) vorzuziehen, etwa dem folgenden Code:
    If ((Select Count(*) From Information_Schema.Tables As A
    	Where A.Table_Name = 'Artikel') > 0)
        Drop Table Artikel

© 2003-2017 Jürgen Auer, Berlin.