Underfrågor (SQL Server)

  • 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 av ANY eller ALL.
  • 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 och IN 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 och HAVING klausuler.
  • DISTINCT nyckelord kan inte användas med underfrågor som inkluderar GROUP BY.
  • COMPUTE och INTO klausuler kan inte anges.
  • ORDER BY kan bara anges när TOP 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 med EXISTS är desamma som för en standardvalslista, eftersom en underfråga introducerad med EXISTS 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.

Write a Comment

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *