В вышеупомянутом примере, "внутренний"(inner) и "внешний"(outer), это псевдонимы, подобно обсужденным в Главе 9. Мы выбрали эти имена для большей ясности; они отсылают к значениям внутренних и внешних запросов, соответственно. Так как значение в поле cnum внешнего запроса меняется, внутренний запрос должен выполняться отдельно для каждой строки внешнего запроса. Строка внешнего запроса для которого внутренний запрос каждый раз будет выполнен, называется - текущей строкой-кандидатом. Следовательно, процедура оценки выполняемой соотнесенным подзапросом - это:
=============== SQL Execution Log ============
| |
| SELECT * |
| FROM Customers outer |
| WHERE 10/03/1990 IN |
| (SELECT odate |
| FROM Orders inner |
| WHERE outer.cnum = inner.cnum); |
| ============================================= |
| cnum cname city rating snum |
| ----- -------- ---- ------ ----- |
| 2001 Hoffman London 100 1001 |
| 2003 Liu San Jose 200 1002 |
| 2008 Cisneros San Jose 300 1007 |
| 2007 Pereira Rome 100 1004 |
=============================================
Рисунок 11.1: Использование соотнесенного подзапроса
1. Выбрать строку из таблицы именованной в внешнем запросе.
Это будет текущая строка-кандидат.
2. Сохранить значения из этой строки-кандидата в псевдониме с именем в предложении FROM внешнего запроса.
3. Выполнить подзапрос. Везде, где псевдоним данный для внешнего запроса найден ( в этом случае "внешний" ),использовать значение для текущей строки-кандидата. Использование значения из строки кандидата внешнего запроса в подзапросе называется - внешней ссылкой.
4. Оценить предикат внешнего запроса на основе результатов подзапроса выполняемого в шаге 3. Он определяеть - выбирается ли строка-кандидат для вывода.
5. Повторить процедуру для следующей строки-кандидата таблицы, и так далее пока все строки таблицы не будут проверены.
В вышеупомянутом примере, SQL осуществляет следующую процедуру:
1. Он выбирает строку Hoffman из таблицы Заказчиков.
2. Сохраняет эту строку как текущую строку-кандидат под псевдонимом - "внешним".
3. Затем он выполняет подзапрос. Подзапрос просматривает всю таблицу Порядков чтобы найти строки где значение cnum поле - такое же как
значение outer.cnum, которое в настоящее время равно 2001, - поле cnum строки Hoffmanа.
Затем он извлекает поле odate из каждой строки таблицы Порядков для которой это верно, и формирует набор значений поля odate.
4. Получив набор всех значений поля odate, для поля cnum = 2001,он проверяет предикат основного запроса чтобы видеть имеется ли значение на 3 Октября в этом наборе. Если это так(а это так), то он выбирает строку Hoffmanа для вывода ее из основного запроса.
5. Он повторяет всю процедуру, используя строку Giovanni как строку-кандидата, и затем сохраняет повторно пока каждая строка таблицы Заказчиков не будет проверена.
Как вы можете видеть, вычисления которые SQL выполняет с помощью этих простых инструкций - это полный комплекс. Конечно, вы могли бы решить ту же самую проблему используя обьединение, следующего вида ( вывод для этого запроса показывается в Рисунке 11.2 ):