- 18.02.2018
- 21 minutter å lese
-
- W
- M
- T
- M
- j
-
+3
Gjelder for: SQL Server (alle støttede versjoner) Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Parallell datalager
Et underspørsmål er et spørsmål som er nestet i et SELECT
, INSERT
, UPDATE
, eller DELETE
uttalelse, eller inne i et annet underforespørsel. Et underspørsmål kan brukes hvor som helst et uttrykk er tillatt. I dette eksemplet brukes et undersøk som et kolonneuttrykk kalt MaxUnitPrice i en SELECT-setning.
Grunnleggende om undersøk
En underspørsel er også kalt et indre spørsmål eller indre valg, mens utsagnet som inneholder en underspørsel, også kalles et ytre spørsmål eller ytre valg.
Mange Transact-SQL-setninger som inkluderer undersøk kan alternativt formuleres som sammenføyninger. Andre spørsmål kan bare stilles med underspørsmål. I Transact-SQL er det vanligvis ingen forskjell i ytelse mellom en setning som inkluderer en underspørsel og en semantisk ekvivalent versjon som ikke gjør det. I noen tilfeller der eksistensen må kontrolleres, gir en join imidlertid bedre ytelse. Ellers må den nestede spørringen behandles for hvert resultat av den ytre spørringen for å sikre eliminering av duplikater. I slike tilfeller vil en tilknytningstilnærming gi bedre resultater. Følgende er et eksempel som viser både en undersøking SELECT
og en join SELECT
som returnerer det samme resultatsettet:
Et underspørsmål nestet i den ytre SELECT-setningen har følgende komponenter:
- En vanlig
SELECT
spørring inkludert de vanlige utvalgte listekomponentene. - En vanlig
FROM
-klausul som inkluderer ett eller flere navn på tabeller eller visninger. - En valgfri
WHERE
klausul. - En valgfri
GROUP BY
klausul. - En valgfri
HAVING
-klausul.
SELECT-spørringen til et underspørsmål er alltid omgitt av parenteser. Den kan ikke inneholde en COMPUTE
eller FOR BROWSE
klausul, og kan bare inneholde en ORDER BY
klausul når en TOP-klausul er også spesifisert.
Et underspørsmål kan nestes inne i WHERE
eller HAVING
-klausulen til en ytre SELECT
, INSERT
, UPDATE
, eller DELETE
uttalelse, eller inne i en annen underspørsel. Opptil 32 nivåer av hekking er mulig, selv om grensen varierer basert på tilgjengelig minne og kompleksiteten til andre uttrykk i spørringen. Individuelle spørsmål støtter kanskje ikke nesting på opptil 32 nivåer. Et underspørsmål kan vises hvor som helst et uttrykk kan brukes, hvis det returnerer en enkelt verdi.
Hvis en tabell bare vises i et underspørsmål og ikke i det ytre spørringen, kan ikke kolonner fra den tabellen inkluderes i output (valglisten for det ytre spørringen).
Uttalelser som inkluderer en underspørsel tar vanligvis ett av disse formatene:
- WHERE expression IN (subquery)
- WHERE uttrykk sammenligningsoperatør (underspørring)
- WHERE EXISTS (subquery)
I noen Transact-SQL-setninger kan undersøket vurderes som om det var en uavhengig spørsmål. Konseptuelt erstattes undersøkingsresultatene i den ytre spørringen (selv om dette ikke nødvendigvis er hvordan SQL Server faktisk behandler Transact-SQL-setninger med underspørringer).
Det er tre grunnleggende typer underspørsmål. De som:
- Opererer på lister introdusert med
IN
, eller de som en sammenligningsoperator endret avANY
ellerALL
. - Introduseres med en umodifisert sammenligningsoperator og må returnere en enkelt verdi.
- Er eksistensforsøk introdusert med
EXISTS
.
Regler for spørring
Et undersøk er underlagt følgende begrensninger:
- Valglisten for et underspørsmål introdusert med en sammenligningsoperator kan bare inneholde ett uttrykk eller kolonnenavn (bortsett fra at
EXISTS
ogIN
fungerer påSELECT *
eller en liste, henholdsvis). - Hvis
WHERE
-satsen til et ytre spørsmål inneholder et kolonnenavn, blir det må være sammenføyningskompatibel med kolonnen i listen med underspørsmål. - Datatypene ntekst, tekst og bilde kan ikke brukes i listen over delspørringer.
- Fordi de må returnere en enkelt verdi, introduseres delspørsmål av en umodifisert sammenligningsoperator (en ikke fulgt av nøkkelordet ALLE eller ALLE) kan ikke inneholde
GROUP BY
ogHAVING
klausuler. -
DISTINCT
nøkkelordet kan ikke brukes med delsøk som inkluderer GROUP BY. -
COMPUTE
ogINTO
klausuler kan ikke spesifiseres. -
ORDER BY
kan bare spesifiseres nårTOP
også er spesifisert. - En visning opprettet ved hjelp av et underspørsmål kan ikke oppdateres.
- Valglisten for et underspørsmål introdusert med
EXISTS
, som konvensjon, har en stjerne ( *) i stedet for et enkelt kolonnenavn. Reglene for et undersøk introdusert medEXISTS
er de samme som for en standard utvalgsliste, fordi et underspørsmål introdusert medEXISTS
skaper en eksistens test og returnerer SANT eller FALSK, i stedet for data.
Kvalifiserende kolonnenavn i underspørringer
I det følgende eksemplet, BusinessEntityID-kolonnen i WHERE
ledd i den ytre spørringen er implisitt kvalifisert av tabellnavnet i den ytre spørringen FROM
klausul (Sales.Store). Henvisningen til CustomerID i valglisten for underforespørselen er kvalifisert av underforespørselen FROM
klausul, det vil si av salgstabellen. Kunden.
Den generelle regelen er at kolonnenavn i en uttalelse er implisitt kvalifisert av tabellen som det er referert til i FROM
-satsen på samme nivå. Hvis det ikke finnes en kolonne i tabellen som det refereres til i FROM
-klausulen til et underspørsmål, blir den implisitt kvalifisert av tabellen som det refereres til i FROM
ledd i den ytre spørringen.
Slik ser spørringen ut med disse implisitte antagelsene:
Det er aldri feil å oppgi tabellnavnet eksplisitt, og det er alltid mulig å overstyre implisitte antagelser om tabellnavn med eksplisitte kvalifikasjoner.
Viktig
Hvis det er referert til en kolonne i et underspørsmål som eksisterer ikke i tabellen det henvises til underundersøket «s FROM
klausul, men eksisterer i en tabell som det refereres til av det ytre spørringen» s FROM
klausul, kjøres spørringen uten feil. SQL Server kvalifiserer implisitt kolonnen i underspørringen med tabellnavnet i det ytre spørringen.
Flere nivåer av nesting
Et underspørsmål kan selv inneholde ett eller flere underspørsmål. Et hvilket som helst antall underspørsmål kan nestes i en uttalelse.
Følgende spørsmål finner navnene på ansatte som også er selgere.
Her er resultatsettet.
Den innerste spørringen returnerer selgerens ID-er. Spørringen på neste høyere nivå blir evaluert med disse selger-IDene og returnerer kontakt-ID-numrene til de ansatte. Til slutt bruker den ytre spørringen kontakt-ID-ene for å finne navnene på de ansatte.
Du kan også uttrykke dette spørsmålet som en sammenkobling:
Mange spørsmål kan evalueres ved å utføre undersøket en gang og erstatte den resulterende verdien eller verdiene i WHERE
-satsen i det ytre spørringen. I spørringer som inkluderer et korrelert undersøk (også kjent som et gjentatt underspørring), avhenger undersøket av det ytre spørringen for verdiene. Dette betyr at undersøket kjøres gjentatte ganger, en gang for hver rad som kan bli valgt av den ytre spørringen. Denne spørringen henter en forekomst av hver ansattes for- og etternavn som bonusen i SalesPerson-tabellen er 5000 for og som ansattes identifikasjonsnumre samsvarer i tabellene medarbeider og salgsperson.
Her er resultatsettet.
Den forrige undersøket i denne setningen kan ikke evalueres uavhengig av den ytre spørringen. Den trenger en verdi for Employee.BusinessEntityID, men denne verdien endres når SQL Server undersøker forskjellige rader i Employee.
Det er akkurat slik dette spørring blir evaluert: SQL Server vurderer hver rad i tabellen medarbeidere for inkludering i resultatene ved å erstatte verdien i hver rad i den indre spørringen. For eksempel hvis SQL Server først undersøker raden for Syed Abbas
, variabelen Employee.BusinessEntityID tar verdien 285 som SQL Server erstatter ter i det indre spørsmålet.
Resultatet er 0 (Syed Abbas
mottok ikke en bonus fordi han er ikke en selger), så den ytre spørringen vurderes til:
Fordi dette er usant, er raden for Syed Abbas
er ikke inkludert i resultatene.