Основы вложенных запросов
Вложенным запросом называется запрос, помещаемый в инструкцию SELECT, INSERT, UPDATE или DELETE или в другой вложенный запрос. Подзапрос может быть использован везде, где разрешены выражения. В данном примере вложенный запрос используется в качестве выражения для столбца с именем MaxUnitPrice в инструкции SELECT.
USE AdventureWorks;
GO
SELECT Ord.SalesOrderID, Ord.OrderDate,
(SELECT MAX(OrdDet.UnitPrice)
FROM AdventureWorks.Sales.SalesOrderDetail AS OrdDet
WHERE Ord.SalesOrderID = OrdDet.SalesOrderID) AS MaxUnitPrice
FROM AdventureWorks.Sales.SalesOrderHeader AS Ord
Вложенный запрос по-другому называют внутренним запросом или внутренней операцией выбора, в то время как инструкцию, содержащую вложенный запрос, называют внешним запросом или внешней операцией выбора.
Многие инструкции языка Transact-SQL, включающие подзапросы, можно записать в виде соединений. Другие запросы могут быть осуществлены только с помощью подзапросов. В языке Transact-SQL обычно не бывает разницы в производительности между инструкцией, включающей вложенный запрос, и семантически эквивалентной версией без вложенного запроса. Однако в некоторых случаях, когда проверяется существование, соединения показывают лучшую производительность. В противном случае для устранения дубликатов вложенный запрос должен обрабатываться для получения каждого результата внешнего запроса. В таких случаях метод работы соединений дает лучшие результаты. Следующий пример содержит запросы SELECT с вложенным запросом и с соединением, возвращающие одинаковый результирующий набор:
/* SELECT statement built using a subquery. */
SELECT Name
FROM AdventureWorks.Production.Product
WHERE ListPrice =
(SELECT ListPrice
FROM AdventureWorks.Production.Product
WHERE Name = 'Chainring Bolts' )
/* SELECT statement built using a join that returns
the same result set. */
SELECT Prd1. Name
FROM AdventureWorks.Production.Product AS Prd1
JOIN AdventureWorks.Production.Product AS Prd2
ON (Prd1.ListPrice = Prd2.ListPrice)
WHERE Prd2. Name = 'Chainring Bolts'
Вложенный во внешнюю инструкцию SELECT запрос, имеет следующие компоненты:
обычный запрос SELECT, включающий обычные компоненты списка выборки;
обычное предложение FROM, включающее одно или более имен таблиц или представлений;
необязательное предложение WHERE;
необязательное предложение GROUP BY;
необязательное предложение HAVING.
Запрос SELECT вложенного запроса всегда заключен в скобки. Он не может включать предложений COMPUTE или FOR BROWSE и может включать предложение ORDER BY только вместе с предложением TOP.
Вложенный запрос может быть вложен в предложение WHERE или HAVING внешней инструкции SELECT, INSERT, UPDATE или DELETE или в другой вложенный запрос. Возможно создавать вложенность до 32-го уровня, хотя ограничения меняются в зависимости от объема доступной памяти и сложности других выражений в запросе. Отдельные запросы могут не поддерживать вложенность до 32-го уровня. Подзапрос может появляться везде, где может использоваться выражение, если он возвращает одно значение.
Если таблица появляется только во вложенном запросе, а не во внешнем запросе, в этом случае столбцы данной таблицы не могут быть включены в выходные данные (список выборки внешнего запроса).
Инструкции, включающие вложенные запросы, обычно имеют один из следующих форматов:
WHERE expression [NOT] IN (subquery)
WHERE expression comparison_operator [ANY | ALL] (subquery)
WHERE [NOT] EXISTS (subquery)
В некоторых инструкциях языка Transact-SQL вложенный запрос может рассматриваться как отдельный запрос. По существу, результаты вложенного запроса подставляются во внешний запрос (хотя это необязательно и зависит от того, как в MicrosoftSQL Server реализована обработка инструкций языка Transact-SQL с вложенными запросами).
Существуют три основных типа подзапросов, которые:
работают в списках, вставленных после ключевого слова IN, или тех, которые оператор сравнения изменил с помощью ключевого слова ANY или ALL;
вставлены оператором немодифицированных сравнений и должны возвращать одно значение;
являются тестами на существование, начинающимися с ключевого слова EXISTS.