- 18.02.2018
- 21 de minute de citit
-
- W
- M
- T
- M
- j
-
+3
Se aplică la: SQL Server (toate versiunile acceptate) Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Depozit de date paralele
O interogare este o interogare care este imbricată în interiorul unui SELECT
, INSERT
, UPDATE
sau instrucțiunea DELETE
sau în cadrul unei alte interogări. O interogare poate fi utilizată oriunde este permisă o expresie. În acest exemplu, o subinterogare este utilizată ca expresie de coloană numită MaxUnitPrice într-o instrucțiune SELECT.
Fundamentele subinterogării
De asemenea, este o interogare numită interogare interioară sau selectare interioară, în timp ce instrucțiunea care conține o interogare se numește și interogare externă sau selectare externă.
Multe instrucțiuni Transact-SQL care includ subinterogări pot fi formulate alternativ ca îmbinări. Alte întrebări pot fi puse numai cu subinterogări. În Transact-SQL, de obicei nu există nicio diferență de performanță între o instrucțiune care include o subinterogare și o versiune echivalentă semantic care nu. Cu toate acestea, în unele cazuri în care existența trebuie verificată, o îmbinare produce o performanță mai bună. În caz contrar, interogarea imbricată trebuie procesată pentru fiecare rezultat al interogării externe pentru a asigura eliminarea duplicatelor. În astfel de cazuri, o abordare de asociere ar produce rezultate mai bune. Următorul este un exemplu care arată atât o subinterogare SELECT
, cât și o unire SELECT
care returnează același set de rezultate:
O subinterogare imbricată în instrucțiunea SELECT exterioară are următoarele componente:
- O interogare obișnuită
SELECT
inclusiv componentele obișnuite ale listei de selectare. - O clauză regulată
FROM
care include unul sau mai multe nume de tabele sau vizualizări. - Un
WHERE
clauză. - O clauză opțională
GROUP BY
. - O clauză.
Interogarea SELECT a unei subinterogări este întotdeauna inclusă între paranteze. Nu poate include o clauză COMPUTE
sau FOR BROWSE
și poate include o clauză ORDER BY
numai atunci când este de asemenea specificată o clauză TOP.
O subinterogare poate fi imbricată în interiorul WHERE
sau HAVING
clauză a unei clauze externe SELECT
, INSERT
, UPDATE
sau DELETE
declarație sau în interiorul unei alte interogări. Este posibilă până la 32 de niveluri de cuibărire, deși limita variază în funcție de memoria disponibilă și de complexitatea altor expresii din interogare. Este posibil ca interogările individuale să nu accepte cuibărirea până la 32 de niveluri. O subinterogare poate apărea oriunde poate fi utilizată o expresie, dacă returnează o singură valoare.
Dacă un tabel apare doar într-o interogare și nu în interogarea externă, atunci coloanele din acel tabel nu pot fi incluse în output (lista de selectare a interogării externe).
Instrucțiunile care includ o interogare iau de obicei unul dintre aceste formate:
- WHERE expression IN (subinterogare)
- WHERE expresie comparison_operator (subinterogare)
- WHERE EXISTS (subinterogare)
În unele instrucțiuni Transact-SQL, subinterogarea poate fi evaluată ca și cum ar fi un independent interogare. Conceptual, rezultatele subinterogării sunt înlocuite în interogarea externă (deși nu aceasta este neapărat modul în care SQL Server procesează de fapt instrucțiunile Transact-SQL cu subinterogări).
Există trei tipuri de bază de subinterogări. Cele care:
- Operează pe liste introduse cu
IN
, sau pe cele pe care un operator de comparație le-a modificat cuANY
sauALL
. - Sunt introduse cu un operator de comparație nemodificat și trebuie să returneze o singură valoare.
- Testele de existență sunt introduse cu
EXISTS
.
Reguli de interogare
O subinterogare este supusă următoarelor restricții:
- Lista selectată a unei interogări introduse cu un operator de comparație poate include o singură expresie sau nume de coloană (cu excepția faptului că
EXISTS
șiIN
funcționează peSELECT *
sau o listă, respectiv). - Dacă clauza
WHERE
a unei interogări externe include un nume de coloană, aceasta trebuie să fie compatibilă cu unirea cu coloana din lista de selectare a subinterogării. - Tipurile de date ntext, text și imagine nu pot fi utilizate în lista selectată de subinterogări.
- Deoarece trebuie să returneze o singură valoare, subinterogări introduse de un operator de comparație nemodificat (una care nu este urmat de cuvântul cheie ORICE sau TOATE) nu poate include clauze
GROUP BY
șiHAVING
. - nu poate fi utilizat cu subinterogări care includ GROUP BY.
-
COMPUTE
șiINTO
clauzele nu pot fi specificate. -
ORDER BY
poate fi specificat numai atunci când este specificat șiTOP
. - O vizualizare creată utilizând o subinterogare nu poate fi actualizată.
- Lista de selectare a unei subinterogări introdusă cu
EXISTS
, prin convenție, are un asterisc ( *) în locul unui singur nume de coloană. Regulile pentru o subinterogare introdusă cuEXISTS
sunt aceleași cu cele pentru o listă de selectare standard, deoarece o subinterogare introdusă cuEXISTS
creează o existență testează și returnează ADEVĂRAT sau FALS, în loc de date.
Numele de coloane eligibile în subinterogări
În exemplul următor, coloana BusinessEntityID din a interogării externe este implicit calificată de numele tabelului din interogarea externă FROM
clauza (Sales.Store). Referința la ID-ul clientului din lista selectată a subinterogării este calificată prin clauza subinterogare FROM
, adică de tabelul Sales.Customer.
Regula generală este că numele coloanelor dintr-o instrucțiune sunt implicit calificate de tabelul la care se face referire în clauza FROM
la același nivel. Dacă nu există o coloană în tabelul la care se face referire în clauza FROM
a unei subinterogări, aceasta este implicit calificată de tabelul la care se face referire în FROM
clauza interogării externe.
Iată cum arată interogarea cu aceste ipoteze implicite specificate:
Nu este niciodată greșit pentru a specifica în mod explicit numele tabelei și este întotdeauna posibil să se anuleze ipotezele implicite despre numele tabelelor cu calificări explicite.
Important
Dacă se face referire la o coloană într-o subinterogare care nu există în tabelul la care face referire subclauza „s FROM
, ci există într-un tabel la care se face referire prin interogarea externă” s FROM
clauză, interogarea se execută fără erori. SQL Server implică calificarea implicită a coloanei din subinterogare cu numele tabelei din interogarea externă.
Mai multe niveluri de cuibărire
O subinterogare poate include una sau mai multe subinterogări. Orice număr de subinterogări pot fi imbricate într-o declarație.
Următoarea interogare găsește numele angajaților care sunt și persoane de vânzări.
Iată setul de rezultate.
Interogarea cea mai internă returnează ID-urile persoanei de vânzări. Interogarea la următorul nivel superior este evaluată cu aceste ID-uri de persoane de vânzări și returnează numerele de identificare de contact ale angajaților. În cele din urmă, interogarea externă utilizează ID-urile de contact pentru a găsi numele angajaților.
Puteți exprima această interogare și ca unire:
Multe interogări pot fi evaluate executând subinterogarea o dată și înlocuind valoarea sau valorile rezultate în clauza WHERE
a interogării externe. În interogările care includ o subinterogare corelată (cunoscută și ca subinterogare repetată), interogarea depinde de interogarea externă pentru valorile sale. Aceasta înseamnă că subinterogarea este executată în mod repetat, o dată pentru fiecare rând care ar putea fi selectat de interogarea externă. Această interogare preia o instanță din numele și prenumele fiecărui angajat pentru care bonusul din tabelul SalesPerson este 5000 și pentru care numerele de identificare ale angajaților se potrivesc în tabelele Angajat și SalesPerson.
Iată setul de rezultate.
Subinterogarea anterioară din această instrucțiune nu poate fi evaluată independent de interogarea externă. Are nevoie de o valoare pentru Employee.BusinessEntityID, dar această valoare se modifică pe măsură ce SQL Server examinează diferite rânduri din Employee.
Exact așa interogarea este evaluată: SQL Server consideră fiecare rând din tabelul Angajaților pentru includerea în rezultate prin înlocuirea valorii din fiecare rând în interogarea interioară. De exemplu, dacă SQL Server examinează mai întâi rândul pentru Syed Abbas
, variabila Employee.BusinessEntityID ia valoarea 285, pe care o substituie SQL Server intră în interogarea interioară.
Rezultatul este 0 (Syed Abbas
nu a primit bonus deoarece este nu o persoană de vânzări), astfel încât interogarea externă se evaluează la:
Deoarece acest lucru este fals, rândul pentru Syed Abbas
nu este inclus în rezultate.