Underforespørgsler (SQL Server)

  • 02/18/2018
  • 21 minutter at læse
    • W
    • M
    • T
    • M
    • j
    • +3

Gælder for: SQL Server (alle understøttede versioner) Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Parallelt datalager

En underforespørgsel er en forespørgsel, der er indlejret i en SELECT, INSERT, UPDATE eller DELETE udsagn eller inde i en anden underforespørgsel. En underforespørgsel kan bruges hvor som helst et udtryk er tilladt. I dette eksempel bruges en underforespørgsel som et kolonneudtryk ved navn MaxUnitPrice i en SELECT-sætning.

Underforespørgsel Grundlæggende

En underforespørgsel er også kaldes en indre forespørgsel eller indre markering, mens udsagnet, der indeholder en underforespørgsel, også kaldes en ydre forespørgsel eller ydre markering.

Mange Transact-SQL-sætninger, der inkluderer underforespørgsler, kan alternativt formuleres som sammenføjninger. Andre spørgsmål kan kun stilles med underforespørgsler. I Transact-SQL er der normalt ingen forskel i ydeevne mellem en sætning, der inkluderer en underforespørgsel og en semantisk ækvivalent version, der ikke gør det. I nogle tilfælde, hvor eksistensen skal kontrolleres, giver en sammenkædning imidlertid bedre ydeevne. Ellers skal den indlejrede forespørgsel behandles for hvert resultat af den ydre forespørgsel for at sikre eliminering af dubletter. I sådanne tilfælde vil en tilslutningstilgang give bedre resultater. Følgende er et eksempel, der viser både en underforespørgsel SELECT og en join SELECT, der returnerer det samme resultatsæt:

En underforespørgsel indlejret i den ydre SELECT-sætning har følgende komponenter:

  • En almindelig SELECT forespørgsel inklusive de almindelige listekomponenter til listen.
  • En almindelig FROM -klausul, der inkluderer et eller flere tabel- eller visningsnavne.
  • En valgfri WHERE klausul.
  • En valgfri GROUP BY klausul.
  • En valgfri HAVING -klausul.

SELECT-forespørgslen i en underforespørgsel er altid lukket i parentes. Den kan ikke indeholde en COMPUTE eller FOR BROWSE -klausul og kan kun omfatte en ORDER BY -klausul, når der er også angivet en TOP-klausul.

En underforespørgsel kan indlejres inde i WHERE eller HAVING -klausulen i en ydre SELECT, INSERT, UPDATE eller DELETE statement eller inde i en anden underforespørgsel. Op til 32 niveauer af indlejring er mulig, selvom grænsen varierer afhængigt af tilgængelig hukommelse og kompleksiteten af andre udtryk i forespørgslen. Individuelle forespørgsler understøtter muligvis ikke indlejring op til 32 niveauer. En underforespørgsel kan vises hvor som helst et udtryk kan bruges, hvis det returnerer en enkelt værdi.

Hvis en tabel kun vises i en underforespørgsel og ikke i den ydre forespørgsel, kan kolonner fra denne tabel ikke medtages i output (vælg listen over den ydre forespørgsel).

Udsagn, der inkluderer en underforespørgsel, tager normalt et af disse formater:

  • WHERE expression IN (subquery)
  • WHERE udtryk sammenligningsoperator (underforespørgsel)
  • HVOR EXISTS (underforespørgsel)

I nogle Transact-SQL-sætninger kan underforespørgslen evalueres som om det var en uafhængig forespørgsel. Konceptuelt erstattes underforespørgselsresultaterne i den ydre forespørgsel (skønt dette ikke nødvendigvis er, hvordan SQL Server faktisk behandler Transact-SQL-sætninger med underforespørgsler).

Der er tre grundlæggende typer underforespørgsler. Dem, der:

  • Betjener på lister introduceret med IN, eller dem, som en sammenligningsoperator ændret af ANY eller ALL.
  • Indføres med en ikke-ændret sammenligningsoperator og skal returnere en enkelt værdi.
  • Indføres eksistensforsøg med EXISTS.

Underforespørgselsregler

En underforespørgsel er underlagt følgende begrænsninger:

  • Valglisten for en underforespørgsel introduceret med en sammenligningsoperator kan kun omfatte ét udtryk eller kolonnenavn (bortset fra at EXISTS og IN fungerer på SELECT * eller en liste).
  • Hvis WHERE -sætningen til en ydre forespørgsel indeholder et kolonnenavn, er det skal være kompatibel med kolonnen i listen over underforespørgsler.
  • Datatyperne ntext, tekst og billede kan ikke bruges i listen over underforespørgsler.
  • Da de skal returnere en enkelt værdi, introduceres underforespørgsler af en umodificeret sammenligningsoperator (en ikke efterfulgt af nøgleordet ALLE eller ALLE) kan ikke omfatte GROUP BY og HAVING klausuler.
  • DISTINCT nøgleord kan ikke bruges med underforespørgsler, der inkluderer GROUP BY.
  • COMPUTE og INTO klausuler kan ikke angives.
  • ORDER BY kan kun angives, når TOP også er angivet.
  • En visning oprettet ved hjælp af en underforespørgsel kan ikke opdateres.
  • Vælg listen over en underforespørgsel introduceret med EXISTS har som konvention en stjerne ( *) i stedet for et enkelt kolonnenavn. Reglerne for en underforespørgsel introduceret med EXISTS er de samme som for en standardliste, fordi en underforespørgsel introduceret med EXISTS skaber en eksistens test og returnerer SAND eller FALSK i stedet for data.

Kvalificerende kolonnenavne i underforespørgsler

I det følgende eksempel viser BusinessEntityID-kolonnen i WHERE -klausul for den ydre forespørgsel er implicit kvalificeret af tabelnavnet i den ydre forespørgsel FROM -klausul (Sales.Store). Henvisningen til kunde-ID i listen over underforespørgsler er kvalificeret af underforespørgslen FROM -klausulen, det vil sige ved tabellen Sales.Customer.

Den generelle regel er, at kolonnenavne i en erklæring er implicit kvalificeret af tabellen, der henvises til i FROM -sætningen på samme niveau. Hvis der ikke findes en kolonne i den tabel, der henvises til i FROM -klausulen i en underforespørgsel, er den implicit kvalificeret af den tabel, der er henvist til i FROM klausul om den ydre forespørgsel.

Sådan ser forespørgslen ud med disse implicitte antagelser:

Det er aldrig forkert at angive tabelnavnet eksplicit, og det er altid muligt at tilsidesætte implicitte antagelser om tabelnavne med eksplicitte kvalifikationer.

Vigtigt

Hvis der henvises til en kolonne i en underforespørgsel, der findes ikke i tabellen, der henvises til med underforespørgslen “s FROM, men findes i en tabel, der henvises til ved den ydre forespørgsel” s FROM klausul, udfører forespørgslen uden fejl. SQL Server kvalificerer implicit kolonnen i underforespørgslen med tabelnavnet i den ydre forespørgsel.

Flere indlejringsniveauer

En underforespørgsel kan selv indeholde en eller flere underforespørgsler. Ethvert antal underforespørgsler kan indlejres i en erklæring.

Den følgende forespørgsel finder navnene på medarbejdere, der også er salgspersoner.

Her er resultatsættet.

Den inderste forespørgsel returnerer sælgerens id’er. Forespørgslen på det næste højere niveau evalueres med disse sælger-id’er og returnerer medarbejdernes kontakt-id-numre. Endelig bruger den ydre forespørgsel kontakt-id’erne til at finde navnene på medarbejderne.

Du kan også udtrykke denne forespørgsel som en sammenføjning:

Mange forespørgsler kan evalueres ved at udføre underforespørgslen en gang og erstatte den resulterende værdi eller værdier i WHERE -klausulen i den ydre forespørgsel. I forespørgsler, der inkluderer en korreleret underforespørgsel (også kendt som en gentagen underforespørgsel), afhænger underforespørgslen af den ydre forespørgsel for dens værdier. Dette betyder, at underforespørgslen udføres gentagne gange, en gang for hver række, der muligvis kan vælges af den ydre forespørgsel. Denne forespørgsel henter en forekomst af hver medarbejders for- og efternavn, hvor bonusen i SalesPerson-tabellen er 5000, og for hvilken medarbejderidentifikationsnumre matcher i medarbejder- og SalesPerson-tabellerne.

Her er resultatsættet.

Den forrige underforespørgsel i denne erklæring kan ikke evalueres uafhængigt af den ydre forespørgsel. Den har brug for en værdi for Employee.BusinessEntityID, men denne værdi ændres, når SQL Server undersøger forskellige rækker i Employee.
Sådan er dette forespørgsel evalueres: SQL Server betragter hver række i medarbejdertabellen for inkludering i resultaterne ved at erstatte værdien i hver række i den indre forespørgsel. Hvis SQL Server f.eks. først undersøger rækken for Syed Abbas, variablen Employee.BusinessEntityID tager værdien 285, som SQL Server erstatter ter i den indre forespørgsel.

Resultatet er 0 (Syed Abbas modtog ikke en bonus, fordi han er ikke en sælger), så den ydre forespørgsel evalueres til:

Da dette er forkert, er rækken for Syed Abbas er ikke inkluderet i resultaterne.

Write a Comment

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *