- •Лабораторная работа 4. Подчиненные и составные запросы
- •Общие сведения
- •Применение подчиненных запросов
- •Подчиненный запрос
- •Подчиненные запросы в предложении where
- •Условия отбора в подчиненном запросе
- •Сравнение с результатом подчиненного запроса
- •Проверка на принадлежность результатам подчиненного запроса
- •Проверка на существование
- •Уровни вложенности запросов
- •Подчиненные запросы — резюме
Проверка на существование
В результате проверки на существование (предикат EXISTS) можно выяснить, содержится ли в таблице результатов подчиненного запроса хотя бы одна строка. Аналогичной простой проверки не существует.
Пример 4.4. Вывести информацию о наименовании поставщиков, которые в поставках поставляют комплектующее с кодом 1.
select Distinct Sname
from Supplier
where exists (select Delivery.SID
from Delivery
where Delivery.SID = Supplier.SID
and PID = 1)
Результат:
Sname
-----------
Информатика
Формоза
Главный запрос последовательно перебирает все строки таблицы поставщиков Supplier, и для каждого поставщика выполняется подчиненный запрос. Результатом подчиненного запроса является столбец данных, содержащий коды поставщиков, поставляющих во всех поставках комплектующее с кодом 1. Если такие поставки есть (то есть столбец не пустой), то проверка EXISTS возвращает TRUE. Если подчиненный запрос не дает ни одной строки поставок, проверка EXISTS возвращает значение FALSE. Эта проверка не может возвращать NULL.
Можно изменить логику проверки EXISTS и использовать форму NOT EXISTS. Toгда в случае, если подчиненный запрос не создает ни одной строки результата, проверка возвращает TRUE, в противном случае — FALSE.
Предикат EXISTS в действительности вовсе не использует результаты подчиненного запроса. Проверяется только наличие результатов. По этой причине в SQL смягчается правило, согласно которому «подчиненный запрос должен возвращать один столбец данных», и в подчиненном запросе проверки EXISTS допускается использование формы SELECT *. Поэтому предыдущий запрос можно переписать следующим образом:
select Distinct Sname
from Supplier
where exists (select *
from Delivery
where Delivery.SID = Supplier.SID
and PID = 1)
На практике при использовании подчиненного запроса в проверке EXISTS всегда применяется форма SELECT *.
Пример 4.5. Вывести информацию о наименовании поставщиков, которые в поставках не поставляют комплектующее с кодом 1.
select Distinct Sname
from Supplier
where not exists (select *
from Delivery
where Delivery.SID = Supplier.SID
and PID = 1)
Результат:
Sname
--------------------
R-Style
Sunrise
Вист-Дон
Уровни вложенности запросов
Все рассмотренные до сих пор запросы были «двухуровневыми» и состояли из главного и подчиненного запросов. Точно так же, как внутри главного запроса может содержаться подчиненный, внутри подчиненного запроса может находиться еще один подчиненный запрос, называемый в таком случае вложенным.
Пример 4.6. Вывести информацию о наименовании поставщиков, которые поставляют комплектующее типа PR-DLC.
select Sname
from Supplier
where SID in
(select SID
from Delivery
where PID in
(select PID
from Product
where Type = 'PR-DLC'))
Результат:
Sname
--------------------
Вист-Дон
Формоза
По такой же методике можно создавать запросы с четырьмя и более уровнями вложенности. Стандарт ANSI/ISO не определяет максимальное число уровней вложенности, но на практике с ростом их числа очень быстро увеличивается время выполнения запроса. Когда запрос имеет более двух уровней вложенности, он становится трудным для чтения и понимания. Во многих СУБД количество уровней вложеннси запросов ограничено относительно небольшим числом.