Unterabfragen (SQL Server)

  • 18.02.2008
  • 21 Minuten zum Lesen
    • W
    • M
    • T
    • M
    • j
    • +3

Gilt für: SQL Server (alle unterstützten Versionen) Azure SQL-Datenbank Verwaltete Azure SQL-Instanz Azure Synapse Analytics Paralleles Data Warehouse

Eine Unterabfrage ist eine Abfrage, die in einer SELECT, INSERT, UPDATE oder DELETE Anweisung oder in einer anderen Unterabfrage. Eine Unterabfrage kann überall dort verwendet werden, wo ein Ausdruck zulässig ist. In diesem Beispiel wird eine Unterabfrage als Spaltenausdruck mit dem Namen MaxUnitPrice in einer SELECT-Anweisung verwendet.

Grundlagen der Unterabfrage

Eine Unterabfrage ist ebenfalls vorhanden wird als innere Abfrage oder innere Auswahl bezeichnet, während die Anweisung, die eine Unterabfrage enthält, auch als äußere Abfrage oder äußere Auswahl bezeichnet wird.

Viele Transact-SQL-Anweisungen, die Unterabfragen enthalten, können alternativ als Verknüpfungen formuliert werden. Andere Fragen können nur mit Unterabfragen gestellt werden. In Transact-SQL gibt es normalerweise keinen Leistungsunterschied zwischen einer Anweisung, die eine Unterabfrage enthält, und einer semantisch äquivalenten Version, die dies nicht tut. In einigen Fällen, in denen die Existenz überprüft werden muss, führt ein Join jedoch zu einer besseren Leistung. Andernfalls muss die verschachtelte Abfrage für jedes Ergebnis der äußeren Abfrage verarbeitet werden, um die Beseitigung von Duplikaten sicherzustellen. In solchen Fällen würde ein Join-Ansatz zu besseren Ergebnissen führen. Das folgende Beispiel zeigt sowohl eine Unterabfrage SELECT als auch einen Join SELECT, die dieselbe Ergebnismenge zurückgeben:

Eine in der äußeren SELECT-Anweisung verschachtelte Unterabfrage enthält die folgenden Komponenten:

  • Eine reguläre SELECT -Abfrage einschließlich der regulären Auswahllistenkomponenten.
  • Eine reguläre FROM -Klausel, die einen oder mehrere Tabellen- oder Ansichtsnamen enthält.
  • Eine optionale WHERE -Klausel.
  • Eine optionale GROUP BY -Klausel.
  • Eine optionale HAVING -Klausel.

Die SELECT-Abfrage einer Unterabfrage wird immer in Klammern eingeschlossen. Es darf keine COMPUTE – oder FOR BROWSE -Klausel enthalten und darf nur eine ORDER BY -Klausel enthalten, wenn Es wird auch eine TOP-Klausel angegeben.

Eine Unterabfrage kann in der WHERE – oder HAVING -Klausel eines Outer verschachtelt werden SELECT, INSERT, UPDATE oder DELETE -Anweisung oder in einer anderen Unterabfrage. Es sind bis zu 32 Verschachtelungsebenen möglich, obwohl der Grenzwert je nach verfügbarem Speicher und der Komplexität anderer Ausdrücke in der Abfrage variiert. Einzelne Abfragen unterstützen möglicherweise nicht das Verschachteln von bis zu 32 Ebenen. Eine Unterabfrage kann überall dort angezeigt werden, wo ein Ausdruck verwendet werden kann, wenn er einen einzelnen Wert zurückgibt.

Wenn eine Tabelle nur in einer Unterabfrage und nicht in der äußeren Abfrage angezeigt wird, können Spalten aus dieser Tabelle nicht in die Liste aufgenommen werden Ausgabe (die Auswahlliste der äußeren Abfrage).

Anweisungen, die eine Unterabfrage enthalten, haben normalerweise eines der folgenden Formate:

  • WHERE-Ausdruck IN (Unterabfrage)
  • WHERE-Ausdruck compare_operator (Unterabfrage)
  • WHERE EXISTS (Unterabfrage)

In einigen Transact-SQL-Anweisungen kann die Unterabfrage so ausgewertet werden, als wäre sie unabhängig Abfrage. Konzeptionell werden die Unterabfrageergebnisse in die äußere Abfrage eingesetzt (obwohl SQL Server auf diese Weise nicht unbedingt Transact-SQL-Anweisungen mit Unterabfragen verarbeitet).

Es gibt drei grundlegende Arten von Unterabfragen. Diejenigen, die:

  • mit Listen arbeiten, die mit IN eingeführt wurden, oder diejenigen, die ein Vergleichsoperator mit ANY oder ALL.
  • Werden mit einem unveränderten Vergleichsoperator eingeführt und müssen einen einzelnen Wert zurückgeben.
  • Werden Existenztests mit EXISTS.

Unterabfrageregeln

Eine Unterabfrage unterliegt den folgenden Einschränkungen:

  • Die Auswahlliste einer mit einem Vergleichsoperator eingeführten Unterabfrage kann nur einen Ausdruck oder Spaltennamen enthalten (außer dass EXISTS und IN auf SELECT * bzw. eine Liste).
  • Wenn die WHERE -Klausel einer äußeren Abfrage einen Spaltennamen enthält, ist dies der Fall muss mit der Spalte in der Unterabfrageauswahlliste kompatibel sein.
  • Die Datentypen ntext, text und image können nicht in der Auswahlliste der Unterabfragen verwendet werden.
  • Da sie einen einzelnen Wert zurückgeben müssen, werden Unterabfragen von einem unveränderten Vergleichsoperator (einer) eingeführt ohne das Schlüsselwort ANY oder ALL) darf die Klauseln GROUP BY und HAVING nicht enthalten.
  • Die DISTINCT kann nicht mit Unterabfragen verwendet werden, die GROUP BY enthalten.
  • Die COMPUTE und INTO -Klauseln können nicht angegeben werden.
  • ORDER BY kann nur angegeben werden, wenn auch TOP angegeben ist.
  • Eine mithilfe einer Unterabfrage erstellte Ansicht kann nicht aktualisiert werden.
  • Die Auswahlliste einer mit EXISTS eingeführten Unterabfrage enthält gemäß Konvention ein Sternchen ( *) anstelle eines einzelnen Spaltennamens. Die Regeln für eine mit EXISTS eingeführte Unterabfrage sind dieselben wie für eine Standardauswahlliste, da eine mit EXISTS eingeführte Unterabfrage eine Existenz erzeugt testet und gibt TRUE oder FALSE anstelle von Daten zurück.

Qualifizierende Spaltennamen in Unterabfragen

Im folgenden Beispiel die BusinessEntityID-Spalte in der WHERE -Klausel der äußeren Abfrage wird implizit durch den Tabellennamen in der äußeren Abfrage FROM -Klausel (Sales.Store) qualifiziert. Der Verweis auf CustomerID in der Auswahlliste der Unterabfrage wird durch die Klausel FROM qualifiziert, dh durch die Tabelle Sales.Customer.

Die allgemeine Regel lautet, dass Spaltennamen in einer Anweisung implizit durch die Tabelle qualifiziert werden, auf die in der Klausel FROM auf derselben Ebene verwiesen wird. Wenn in der Tabelle, auf die in der FROM -Klausel einer Unterabfrage verwiesen wird, keine Spalte vorhanden ist, wird sie implizit durch die Tabelle qualifiziert, auf die in der FROM Klausel der äußeren Abfrage.

So sieht die Abfrage mit diesen impliziten Annahmen aus:

Es ist niemals falsch um den Tabellennamen explizit anzugeben, und es ist immer möglich, implizite Annahmen über Tabellennamen mit expliziten Qualifikationen zu überschreiben.

Wichtig

Wenn in einer Unterabfrage auf eine Spalte verwiesen wird, die existiert nicht in der Tabelle, auf die durch die Unterabfrage „s FROM -Klausel verwiesen wird, sondern in einer Tabelle, auf die durch die äußere Abfrage“ s FROM verwiesen wird Klausel wird die Abfrage fehlerfrei ausgeführt. SQL Server qualifiziert die Spalte in der Unterabfrage implizit mit dem Tabellennamen in der äußeren Abfrage.

Mehrere Verschachtelungsebenen

Eine Unterabfrage kann selbst eine oder mehrere Unterabfragen enthalten. In einer Anweisung können beliebig viele Unterabfragen verschachtelt werden.

Die folgende Abfrage ermittelt die Namen von Mitarbeitern, die auch Verkäufer sind.

Hier ist die Ergebnismenge.

Die innerste Abfrage gibt die Verkäufer-IDs zurück. Die Abfrage auf der nächsthöheren Ebene wird mit diesen Verkäufer-IDs ausgewertet und gibt die Kontakt-ID-Nummern der Mitarbeiter zurück. Schließlich verwendet die äußere Abfrage die Kontakt-IDs, um die Namen der Mitarbeiter zu ermitteln.

Sie können diese Abfrage auch als Join ausdrücken:

Viele Abfragen können ausgewertet werden, indem die Unterabfrage einmal ausgeführt und der oder die resultierenden Werte in die WHERE -Klausel der äußeren Abfrage eingesetzt werden. Bei Abfragen, die eine korrelierte Unterabfrage enthalten (auch als sich wiederholende Unterabfrage bezeichnet), hängt die Unterabfrage von der äußeren Abfrage für ihre Werte ab. Dies bedeutet, dass die Unterabfrage wiederholt ausgeführt wird, einmal für jede Zeile, die von der äußeren Abfrage ausgewählt werden könnte. Diese Abfrage ruft eine Instanz des Vor- und Nachnamens jedes Mitarbeiters ab, für die der Bonus in der SalesPerson-Tabelle 5000 beträgt und für die die Mitarbeiteridentifikationsnummern stimmen in den Mitarbeiter- und SalesPerson-Tabellen überein.

Hier ist die Ergebnismenge.

Die vorherige Unterabfrage in dieser Anweisung kann nicht unabhängig von der äußeren Abfrage ausgewertet werden. Sie benötigt einen Wert für Employee.BusinessEntityID. Dieser Wert ändert sich jedoch, wenn SQL Server verschiedene Zeilen in Employee untersucht.
Genau so Die Abfrage wird ausgewertet: SQL Server berücksichtigt jede Zeile der Employee-Tabelle für die Aufnahme in die Ergebnisse, indem der Wert in jeder Zeile in die innere Abfrage eingesetzt wird. Wenn SQL Server beispielsweise die Zeile zuerst auf Syed Abbas, die Variable Employee.BusinessEntityID nimmt den Wert 285 an, den SQL Server ersetzt utes in die innere Abfrage.

Das Ergebnis ist 0 (Syed Abbas hat keinen Bonus erhalten, weil er es ist kein Verkäufer), daher ergibt die äußere Abfrage Folgendes:

Da dies falsch ist, wird die Zeile für Syed Abbas ist nicht in den Ergebnissen enthalten.

Write a Comment

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.