Underforespørsler (SQL Server)

  • 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 av ANY eller ALL.
  • 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 og IN 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 og HAVING klausuler.
  • DISTINCT nøkkelordet kan ikke brukes med delsøk som inkluderer GROUP BY.
  • COMPUTE og INTO klausuler kan ikke spesifiseres.
  • ORDER BY kan bare spesifiseres når TOP 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 med EXISTS er de samme som for en standard utvalgsliste, fordi et underspørsmål introdusert med EXISTS 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.

Write a Comment

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *