- 2018-02-18
- 21 minuter att läsa
-
- W
- M
- T
- M
- j
-
+3
Gäller för: SQL Server (alla versioner som stöds) Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Parallellt datalager
En underfråga är en fråga som är kapslad i en SELECT
, INSERT
, UPDATE
eller DELETE
uttalande eller i en annan underfråga. En underfråga kan användas var som helst ett uttryck är tillåtet. I det här exemplet används en underfråga som ett kolumnuttryck med namnet MaxUnitPrice i ett SELECT-uttalande.
Underfråga grundläggande
En underfråga är också kallas en inre fråga eller inre markering, medan uttalandet som innehåller en underfråga också kallas en yttre fråga eller yttre markering.
Många Transact-SQL-uttalanden som innehåller underfrågor kan alternativt formuleras som sammanfogningar. Andra frågor kan bara ställas med underfrågor. I Transact-SQL finns det vanligtvis ingen prestationsskillnad mellan ett uttalande som innehåller en underfråga och en semantiskt motsvarande version som inte gör det. I vissa fall där existensen måste kontrolleras ger en koppling dock bättre prestanda. Annars måste den kapslade frågan bearbetas för varje resultat av den yttre frågan för att säkerställa eliminering av dubbletter. I sådana fall skulle en anslutningsmetod ge bättre resultat. Följande är ett exempel som visar både en underfråga SELECT
och en koppling SELECT
som returnerar samma resultatuppsättning:
En underfråga kapslad i den yttre SELECT-satsen har följande komponenter:
- En vanlig
SELECT
fråga inklusive de vanliga listkomponenterna. - En vanlig
FROM
-sats som innehåller ett eller flera tabell- eller vynamn. - En valfri
WHERE
klausul. - En valfri
GROUP BY
klausul. - En valfri
HAVING
klausul.
SELECT-frågan i en underfråga är alltid innesluten inom parentes. Det kan inte innehålla en COMPUTE
eller FOR BROWSE
-sats och får endast innehålla en ORDER BY
-sats när en TOP-sats anges också.
En underfråga kan kapslas inuti WHERE
eller HAVING
en yttre SELECT
, INSERT
, UPDATE
eller DELETE
uttalande eller i en annan underfråga. Upp till 32 nivåer av kapsling är möjliga, även om gränsen varierar beroende på tillgängligt minne och komplexiteten hos andra uttryck i frågan. Enskilda frågor stöder kanske inte häckning upp till 32 nivåer. En underfråga kan visas var som helst ett uttryck kan användas, om det returnerar ett enda värde.
Om en tabell endast visas i en underfråga och inte i den yttre frågan, kan inte kolumner från den tabellen inkluderas i output (väljlistan för den yttre frågan).
Uttalanden som innehåller en underfråga har vanligtvis ett av dessa format:
- WHERE expression IN (subquery)
- VAR uttrycksjämförelseoperatör (underfråga)
- VAR EXIST (underfråga)
I vissa Transact-SQL-satser kan underfrågan utvärderas som om den vore en oberoende fråga. Begreppsmässigt ersätts resultaten från underfrågan i den yttre frågan (även om detta inte nödvändigtvis är hur SQL Server faktiskt bearbetar Transact-SQL-satser med underfrågor).
Det finns tre grundläggande typer av underfrågor. De som:
- Fungerar på listor introducerade med
IN
, eller de som en jämförelseoperatör modifierad avANY
ellerALL
. - Introduceras med en omodifierad jämförelseoperator och måste returnera ett enda värde.
- Introduceras existentstester med
EXISTS
.
Underfrågebestämmelser
En underfråga omfattas av följande begränsningar:
- Markeringslistan för en underfråga som introducerats med en jämförelseoperatör kan bara innehålla ett uttryck eller kolumnnamn (förutom att
EXISTS
ochIN
fungerar påSELECT *
eller en lista, respektive). - Om
WHERE
-satsen i en yttre fråga innehåller ett kolumnnamn måste vara anslutningskompatibel med kolumnen i listan med underfrågor. - Datatyperna ntext, text och bild kan inte användas i listan med underfrågor.
- Eftersom de måste returnera ett enda värde introduceras underfrågor av en omodifierad jämförelseoperator (en följs inte av nyckelordet NÅGON eller ALLA) kan inte innehålla
GROUP BY
ochHAVING
klausuler. -
DISTINCT
nyckelord kan inte användas med underfrågor som inkluderar GROUP BY. -
COMPUTE
ochINTO
klausuler kan inte anges. -
ORDER BY
kan bara anges närTOP
också anges. - En vy som skapats med hjälp av en underfråga kan inte uppdateras.
- Listan över en underfråga som introducerats med
EXISTS
, enligt konvention, har en asterisk ( *) istället för ett enda kolumnnamn. Reglerna för en underfråga introducerad medEXISTS
är desamma som för en standardvalslista, eftersom en underfråga introducerad medEXISTS
skapar en existens testa och returnerar SANT eller FALSKT istället för data.
Kvalificerande kolumnnamn i underfrågor
I följande exempel visar BusinessEntityID-kolumnen i WHERE
klausul för den yttre frågan kvalificeras implicit av tabellnamnet i den yttre frågan FROM
klausul (Sales.Store). Hänvisningen till CustomerID i listan över underfrågor kvalificeras av underfrågan FROM
-satsen, det vill säga av tabellen Sales.Customer.
Den allmänna regeln är att kolumnnamn i ett uttalande är implicit kvalificerade av tabellen som anges i FROM
-satsen på samma nivå. Om det inte finns en kolumn i den tabell som refereras till i FROM
-satsen i en underfråga, kvalificeras den implicit av tabellen som refereras till i FROM
paragraf för den yttre frågan.
Så här ser frågan ut med dessa implicita antaganden:
Det är aldrig fel att ange tabellnamnet uttryckligen och det är alltid möjligt att åsidosätta implicita antaganden om tabellnamn med uttryckliga kvalifikationer.
Viktigt
Om en kolumn hänvisas till i en underfråga som existerar inte i tabellen som refereras av underfrågan ”s FROM
, men finns i en tabell som refereras till av den yttre frågan” s FROM
klausul körs frågan utan fel. SQL Server kvalificerar implicit kolumnen i underfrågan med tabellnamnet i den yttre frågan.
Flera nivåer av kapsling
En underfråga kan själv innehålla en eller flera underfrågor. Valfritt antal underfrågor kan kapas i ett uttalande.
Följande fråga hittar namnen på anställda som också är säljare.
Här är resultatuppsättningen.
Den innersta frågan returnerar säljarens ID: n. Frågan på nästa högre nivå utvärderas med dessa säljar-ID och returnerar de anställdas kontakt-ID-nummer. Slutligen använder den yttre frågan kontakt-ID: n för att hitta namnen på de anställda.
Du kan också uttrycka denna fråga som en koppling:
Många frågor kan utvärderas genom att utföra underfrågan en gång och ersätta det resulterande värdet eller värdena i WHERE
-satsen i den yttre frågan. I frågor som innehåller en korrelerad underfråga (även känd som en upprepad underfråga) beror underfrågan på dess yttre fråga för dess värden. Detta innebär att underfrågan körs upprepade gånger, en gång för varje rad som kan väljas av den yttre frågan. Denna fråga hämtar en förekomst av varje anställds för- och efternamn för vilken bonusen i SalesPerson-tabellen är 5000 och för vilken anställdas identifikationsnummer matchar i tabellerna Anställd och SalesPerson.
Här är resultatuppsättningen.
Den tidigare underfrågan i detta uttalande kan inte utvärderas oberoende av den yttre frågan. Det behöver ett värde för Employee.BusinessEntityID, men detta värde ändras när SQL Server undersöker olika rader i Employee.
Det är precis så här frågan utvärderas: SQL Server tar hänsyn till varje rad i tabellen Anställd för inkludering i resultaten genom att ersätta värdet i varje rad i den inre frågan. Till exempel om SQL Server först undersöker raden för Syed Abbas
, variabeln Employee.BusinessEntityID tar värdet 285 som SQL Server ersätter in i den inre frågan.
Resultatet är 0 (Syed Abbas
fick ingen bonus eftersom han är inte en säljare), så den yttre frågan utvärderas till:
Eftersom detta är falskt, raden för Syed Abbas
ingår inte i resultaten.