Использование вложенных запросов
В этой главе…
- Извлечение данных из множества таблиц с помощью одного оператора SQL
- Поиск элементов данных путем сравнения значения из одной таблицы с набором значений из другой
- Поиск элементов данных путем сравнения значения из одной таблицы с выбранным с помощью оператора select единственным значением из другой
- Поиск элементов данных путем сравнения значения из одной таблицы со всеми соответствующими значениями из другой
- Создание коррелированных подзапросов
- Использование подзапросов для определения строк, которые требуется обновить, удалить или вставить
Одним из лучших способов защиты целостности данных является исключение аномалий модификации с помощью нормализации базы данных. Нормализация заключается в разбиении одной таблицы на несколько других по тематическому признаку. Например, нецелесообразно держать в одной таблице данные и о товарах, и об их покупателях, а лучше разнести эти данные по различным таблицам.
Правильно нормализованная база данных имеет множество таблиц. Типичный запрос к такой базе данных работает с данными не менее чем двух таблиц. Один из способов объединения данных нескольких таблиц заключается в использовании оператора объединения (JOIN) или одного из других реляционных операторов (UNION, INTERSECT или EXCEPT). Реляционные операторы позволяют объединить данные нескольких таблиц. Каждый из перечисленных операторов делает это по-своему. Другой способ объединения данных нескольких таблиц состоит в использовании вложенных запросов.
Совет:
В SQL вложенным запросом называется такой запрос, в котором внешний замыкающий оператор содержит подзапрос. Этот подзапрос может сам быть замыкающим оператором для другого вложенного подзапроса. Теоретически число уровней вложенности для подзапросов не ограничено, а на практике зависит от реализации.
Подзапросы обязательно должны быть операторами SELECT, но самый внешний замыкающий оператор может также быть INSERT, UPDATE или DELETE.
Второй способ извлечения данных из множества таблиц основан на том, что подзапрос может работать с одной таблицей, а его замыкающий оператор – с другой.
Предположим, например, что вы хотите отправить базе данных своей компании следующий запрос: найти всех руководителей отделов старше 50 лет. Если использовать операторы объединения (JOIN), о которых говорилось в главе 10, то можно отправить примерно такой запрос:
SELECT D.DeptNo, D.Name, E.Name, E.Age FROM DEPT D, EMPLOYEE E WHERE D.ManagerID = E.ID AND E.Age > 50;
Где D – это псевдоним для таблицы DEPT (отдел), а Е – для таблицы EMPLOYEE (сотрудник). В EMPLOYEE имеется столбец ID (идентификатор), который является первичным ключом, а в DEPT – столбец ManagerlD (идентификатор руководителя отдела). Их значения совпадают для сотрудника, который одновременно является руководителем отдела. Чтобы соединить связанные друг с другом таблицы, используется простое объединение (список таблиц в предложении FROM), а для "отсева" всех строк, не соответствующих заданному выше критерию, – предложение WHERE. Обратите внимание, что в список параметров оператора SELECT включены из таблицы DEPT столбцы DeptNo (номер отдела) и Name (фамилия), а из таблицы EMPLOYEE – столбцы Age (возраст) и Name.
Затем предположим, что вас интересуют строки, отобранные по тому же условию, но только со столбцами таблицы DEPT. Другими словами, нужны отделы, начальники которых старше 50 лет, и вас при этом не интересует, кто именно эти начальники или сколько им лет. Тогда вместо объединения можно написать запрос с подзапросом:
SELECT D.DeptNo, D.Name FROM DEPT D WHERE EXISTS (SELECT * FROM EMPLOYEE E WHERE E.ID = D.ManagerID AND E.Age > 50);
В этом запросе имеются два новых элемента: ключевое слово EXISTS (существует), а также SELECT * в предложении WHERE из первого предложения SELECT. Это второе предложение SELECT является подзапросом (или подвыборкой), а ключевое слово EXISTS – одним из нескольких рассмотренных в этой главе операторов, предназначенных для использования вместе с подзапросами.