- 18/02/2018
- 21 minutes de lecture
-
- W
- M
- T
- M
- j
-
+3
S’applique à: SQL Server (toutes les versions prises en charge) Azure SQL Database Instance gérée Azure SQL Azure Synapse Analytics Parallel Data Warehouse
Une sous-requête est une requête imbriquée dans un SELECT
, INSERT
, UPDATE
, ou DELETE
instruction, ou dans une autre sous-requête. Une sous-requête peut être utilisée partout où une expression est autorisée. Dans cet exemple, une sous-requête est utilisée comme expression de colonne nommée MaxUnitPrice dans une instruction SELECT.
Principes de base de la sous-requête
Une sous-requête est également appelée requête interne ou sélection interne, tandis que l’instruction contenant une sous-requête est également appelée requête externe ou sélection externe.
De nombreuses instructions Transact-SQL qui incluent des sous-requêtes peuvent être formulées sous forme de jointures. D’autres questions ne peuvent être posées qu’avec des sous-requêtes. Dans Transact-SQL, il n’y a généralement aucune différence de performances entre une instruction qui inclut une sous-requête et une version sémantiquement équivalente qui ne le fait pas. Cependant, dans certains cas où l’existence doit être vérifiée, une jointure donne de meilleures performances. Sinon, la requête imbriquée doit être traitée pour chaque résultat de la requête externe afin de garantir l’élimination des doublons. Dans de tels cas, une approche de jointure donnerait de meilleurs résultats. Voici un exemple montrant à la fois une sous-requête SELECT
et une jointure SELECT
qui renvoient le même jeu de résultats:
Une sous-requête imbriquée dans l’instruction SELECT externe comprend les éléments suivants:
- Une requête
SELECT
régulière y compris les composants de la liste de sélection standard. - Une clause
FROM
standard comprenant un ou plusieurs noms de table ou de vue. - Un
WHERE
Clause. - Une clause
GROUP BY
facultative. - Une clause clause.
La requête SELECT d’une sous-requête est toujours entre parenthèses. Il ne peut pas inclure de clause COMPUTE
ou FOR BROWSE
, et peut uniquement inclure une clause ORDER BY
lorsque une clause TOP est également spécifiée.
Une sous-requête peut être imbriquée dans la clause WHERE
ou HAVING
d’une clause externe SELECT
, INSERT
, UPDATE
ou DELETE
, ou dans une autre sous-requête. Jusqu’à 32 niveaux d’imbrication sont possibles, bien que la limite varie en fonction de la mémoire disponible et de la complexité des autres expressions de la requête. Les requêtes individuelles peuvent ne pas prendre en charge l’imbrication jusqu’à 32 niveaux. Une sous-requête peut apparaître partout où une expression peut être utilisée, si elle renvoie une seule valeur.
Si une table apparaît uniquement dans une sous-requête et non dans la requête externe, les colonnes de cette table ne peuvent pas être incluses dans le sortie (la liste de sélection de la requête externe).
Les instructions qui incluent une sous-requête prennent généralement l’un de ces formats:
- WHERE expression IN (sous-requête)
- Opérateur de comparaison d’expression WHERE (sous-requête)
- WHERE EXISTS (sous-requête)
Dans certaines instructions Transact-SQL, la sous-requête peut être évaluée comme s’il s’agissait d’un mettre en doute. Conceptuellement, les résultats de la sous-requête sont remplacés dans la requête externe (bien que ce ne soit pas nécessairement la manière dont SQL Server traite réellement les instructions Transact-SQL avec des sous-requêtes).
Il existe trois types de sous-requêtes de base. Ceux qui:
- Opèrent sur des listes introduites avec
IN
, ou celles qu’un opérateur de comparaison a modifiées parANY
ouALL
. - Sont introduits avec un opérateur de comparaison non modifié et doivent renvoyer une valeur unique.
- Les tests d’existence sont-ils introduits avec
EXISTS
.
Règles de sous-requête
Une sous-requête est soumise aux restrictions suivantes:
- La liste de sélection d’une sous-requête introduite avec un opérateur de comparaison ne peut inclure qu’un seul nom d’expression ou de colonne (sauf que
EXISTS
etIN
fonctionnent surSELECT *
ou une liste, respectivement). - Si la clause
WHERE
d’une requête externe inclut un nom de colonne, elle doit être compatible avec la jointure avec la colonne de la liste de sélection de sous-requête. - Les types de données ntext, text et image ne peuvent pas être utilisés dans la liste de sélection des sous-requêtes.
- Comme ils doivent renvoyer une seule valeur, les sous-requêtes introduites par un opérateur de comparaison non modifié (un non suivi du mot clé ANY ou ALL) ne peut pas inclure les clauses
GROUP BY
etHAVING
. - Les
DISTINCT
Le mot clé ne peut pas être utilisé avec les sous-requêtes qui incluent GROUP BY. - Les
COMPUTE
etINTO
ne peut pas être spécifiée. -
ORDER BY
ne peut être spécifiée que siTOP
est également spécifié. - Une vue créée à l’aide d’une sous-requête ne peut pas être mise à jour.
- La liste de sélection d’une sous-requête introduite avec
EXISTS
, par convention, comporte un astérisque ( *) au lieu d’un seul nom de colonne. Les règles d’une sous-requête introduite avecEXISTS
sont les mêmes que celles d’une liste de sélection standard, car une sous-requête introduite avecEXISTS
crée une existence test et renvoie TRUE ou FALSE, au lieu de données.
Qualification des noms de colonne dans les sous-requêtes
Dans l’exemple suivant, la colonne BusinessEntityID dans de la requête externe est implicitement qualifiée par le nom de la table dans la clause FROM
de la requête externe (Sales.Store). La référence à CustomerID dans la liste de sélection de la sous-requête est qualifiée par la clause de sous-requête FROM
, c’est-à-dire par la table Sales.Customer.
La règle générale est que les noms de colonne dans une instruction sont implicitement qualifiés par la table référencée dans la clause FROM
au même niveau. Si une colonne n’existe pas dans la table référencée dans la clause FROM
d’une sous-requête, elle est implicitement qualifiée par la table référencée dans le FROM
clause de la requête externe.
Voici à quoi ressemble la requête avec ces hypothèses implicites spécifiées:
Ce n’est jamais faux pour indiquer explicitement le nom de la table, et il est toujours possible de remplacer les hypothèses implicites sur les noms de table avec des qualifications explicites.
Important
Si une colonne est référencée dans une sous-requête n’existe pas dans la table référencée par la clause de sous-requête « s FROM
, mais existe dans une table référencée par la requête externe » s FROM
clause, la requête s’exécute sans erreur. SQL Server qualifie implicitement la colonne de la sous-requête avec le nom de la table dans la requête externe.
Plusieurs niveaux d’imbrication
Une sous-requête peut elle-même inclure une ou plusieurs sous-requêtes. N’importe quel nombre de sous-requêtes peut être imbriqué dans une instruction.
La requête suivante recherche les noms des employés qui sont également des commerciaux.
Voici l’ensemble de résultats.
La requête la plus interne renvoie les ID des commerciaux. La requête au niveau supérieur suivant est évaluée avec ces ID de vendeur et renvoie les numéros d’ID de contact des employés. Enfin, la requête externe utilise les identifiants de contact pour trouver les noms des employés.
Vous pouvez également exprimer cette requête sous forme de jointure:
De nombreuses requêtes peuvent être évaluées en exécutant la sous-requête une fois et en remplaçant la ou les valeurs résultantes dans la clause WHERE
de la requête externe. Dans les requêtes qui incluent une sous-requête corrélée (également appelée sous-requête répétitive), la sous-requête dépend de la requête externe pour ses valeurs. Cela signifie que la sous-requête est exécutée à plusieurs reprises, une fois pour chaque ligne qui pourrait être sélectionnée par la requête externe. Cette requête récupère une instance du prénom et du nom de chaque employé pour lequel le bonus dans la table SalesPerson est de 5000 et pour lequel le les numéros d’identification des employés correspondent dans les tables Employee et SalesPerson.
Voici l’ensemble de résultats.
La sous-requête précédente de cette instruction ne peut pas être évaluée indépendamment de la requête externe. Elle a besoin d’une valeur pour Employee.BusinessEntityID, mais cette valeur change à mesure que SQL Server examine différentes lignes dans Employee.
C’est exactement ainsi que cela la requête est évaluée: SQL Server considère chaque ligne de la table Employee pour l’inclusion dans les résultats en remplaçant la valeur de chaque ligne dans la requête interne.Par exemple, si SQL Server examine d’abord la ligne pour Syed Abbas
, la variable Employee.BusinessEntityID prend la valeur 285, que SQL Server remplace utes dans la requête interne.
Le résultat est 0 (Syed Abbas
n’a pas reçu de bonus car il est pas un commercial), donc la requête externe évalue comme suit:
Parce que c’est faux, la ligne pour Syed Abbas
n’est pas inclus dans les résultats.