EXISTS

Ein EXISTS-Prädikat wird als wahr erkannt, wenn in einer Suchbedingung eine Unterabfrage? mindestens eine Zeile selektiert. Der NOT EXISTS-Operator ist daher wahr, wenn eine Unterabfrage keine Zeilen liefert (siehe Beispiel2). Der EXISTS-Operator damit ist innerhalb der dreiwertigen Logik von SQL ein Operator, der nur zwei boolesche Wahrheitswerte liefern kann: FALSE, wenn die Ergebnismenge der Unteranfrage leer ist, sonst TRUE. Mit EXISTS wird der Existenzquantor umgesetzt. Der Operator kann in beliebigen SQL-Suchbedingungen verwendet werden und mit NOT negiert werden. Ein Operator mit einer analogen Semantik ist der IN-Operator mit Unteranfragen. Einziger Unterschied ist, dass IN auch UNKNOWN zurückliefert.

Es ist zu beachten, dass für die richtige Semantik der Anfrage in der Regel der EXISTS als korrelierter EXISTS programmiert werden muss. Korreliert heißt er, wenn in der WHERE-Bedingung der Unteranfrage verknüpft wird mit der oberen Anfrage. (siehe Beispiel)

Da in SQL ein Allquantor fehlt, muss der EXISTS-Operator an dieser Stelle aushelfen. Wie bekannt aus der Prädikatenlogik, ist eine doppeltverneiner Existenzquantor ein Allquantor. Und genau diesen Umstand macht man sich in SQL auch zu Nutze. In der relationalen Algebra wird die Allaussage durch die Division realisiert. Ein alternativer Lösungsweg, zählt die Anzahl der Datensätze und ermittelt darüber die Allaussage. Mehr dazu ist bei der HAVING-Klausel zu finden.

Der EXISTS-Operator wird manchmal auch als Semijoin bezeichnet.

Syntax des EXISTS-Operators:

   <EXISTS-Operator>  ::=  EXISTS ( <Unterabfrage?> )

Beispiele:

  -- Selektieren Sie alle Artikel, für die mindestens ein Auftrag vorliegt!
  SELECT a.TNr, a.Bezeichnung
    FROM Artikel a
   WHERE EXISTS (SELECT * FROM Auftragspositionen ap WHERE a.TNr = ap.TNr);

  -- ein nicht korrelierter EXISTS 
  -- seine Semantik: Wurde schon mal ein Auftrag erfasst? 
  -- Diese Semantik mutet bei der Syntax etwas ungewöhnlich an, aber es fehlt ja auch die Korrelation.
  -- Die obere Anfrage liefert für jeden Artikel-Datensatz TRUE, sobald wenigstens ein Datensatz 
  -- in der Auftragspositionen-Tabelle vorliegt - unabhängig davon, ob die TNr-Werte übereinstimmen. 
  -- Ist also in den Auftragspostionen zumindest ein Datensatz gespeichert, bekommt man die gesamten
  -- Datensätze aus der Artikel-Tabelle zurück. Ist kein Auftragspostionen-Datensatz gespeichert, 
  -- bekommt man gar keinen Datensatz bei der oberen Anfrage zurück. 
  SELECT a.TNr, a.Bezeichnung
    FROM Artikel a
   WHERE EXISTS (SELECT * FROM Auftragspositionen ap);


   -- Ein doppeltes NOT EXISTS realisiert die Division aus der relationalen Algebra unter SQL. 
   -- (siehe auch: HAVING-Klausel)
   --
   -- Semantik: Welche Lieferanten können alle Artikel liefern? 
   -- 
   -- Gegeben sind drei Tabellen: Lieferanten, Artikel, Lieferprogramme 
   -- Lösungsidee: Anfrage umformulieren in eine Frage mit doppelter Verneinung.
   -- "Für welche Lieferanten gilt, dass es keinen Artikel gibt, den sie nicht liefern können?"
   -- Wenn es keinen Artikel gibt, den sie nicht liefern können, dann können sie ja alle Artikel liefern. 
   -- "Für welche Lieferanten gilt, ...
   SELECT l.Lief_Nr, l.Name, l.Plz, l.Ort 
     FROM Lieferanten l
          -- ... dass es keinen Artikel gibt, ...
    WHERE NOT EXISTS (SELECT * FROM Artikel a
                             -- ... , den sie nicht liefern können?"
                       WHERE NOT EXISTS (SELECT * FROM Lieferprogramme lp
                                          WHERE lp.Artikel_Nr = a.Artikel_Nr
                                            AND lp.Lief_Nr    = l.Lief_Nr)
                                         -- und zum Schluss die Korrelation aller drei Ebenen
                                         -- jeweils die unterste Tabelle mit den oberen

   -- Noch ein anderes Beispiel, dass zeigt, dass die Lösung auch funktioniert, wenn weniger 
   -- als drei verschiedene Tabellen beteiligt sind. Hier nur eine Tabelle, die Angestellten.
   --
   -- Semantik: In welchen Abteilungen sind alle Berufe vertreten, die es in der Firma gibt? 
   --
   -- Lösungsidee: Anfrage umformulieren in eine Frage mit doppelter Verneinung.
   -- "Für welche Abteilungen gilt, dass es keine Berufe, die ihre Angestellten nicht ausüben?"
   -- Wenn es keine Berufe gibt, die sie nicht ausüben, dann werden in dieser Abteilung alle Berufe ausgeübt. 
   SELECT a.Abt_Nr
   FROM Angestelle a
   WHERE NOT EXISTS
        (SELECT * FROM Angestellte b
         WHERE NOT EXISTS
               (SELECT * FROM Angestellte c
                WHERE a.Abt_Nr 	= b.Abt_nr AND b.Beruf = c.Beruf));

Beispiel 2

 SELECT * FROM Artikel b
         WHERE NOT EXISTS
               (SELECT * FROM Auftragspositionen b
                WHERE a.Tnr     = b.Tnr)

Wenn die Tabelle Auftragspositionen leer ist, werden alle Artikel ausgegeben.

(vgl. auch Beispiele des IN-Operator)

Quellen:

  • INCITS/ISO/IEC 9075-1-2008. Part 1 "SQL/Framework", ISO International Organization for Standardization / INCITS InterNational Committee for Information Technology Standards, 2008
  • INCITS/ISO/IEC 9075-1-2008. Part 2 "SQL/Foundation", ISO International Organization for Standardization / INCITS InterNational Committee for Information Technology Standards, 2008
  • Elmasri, Ramez/Navathe, Shamkant B.: "Grundlagen von Datenbanksystemen" , Pearson Studium, München, 2002, ISBN 3-8273-7021-3
  • Melton, Jim/Simon, Alan R.: "SQL: 1999 - Understanding Relational Language Components", Morgan Kaufmann, San Francisco, 2001, ISBN 1558604561
  • Oracle® Database SQL Language Reference 11g Release 2 (11.2), E17118-03, August 2010, http://download.oracle.com/docs/cd/E11882_01/server.112/e17118.pdf
  • Saake, Gunter/Sattler, Kai-Uwe/Heuer, Andreas: "Datenbanken - Konzepte und Sprachen", mitp-Verlag, Redline GmbH, Heidelberg, 2007, ISBN 3-8266-1664-2

Kategorie: SQL, E