Как известно, базы данных – это множество взаимосвязанных сущностей или отношений (таблиц) в терминологии реляционных СУБД. При проектировании стремятся создавать таблицы, в каждой из которых содержалась бы информация об одном и только об одном типе сущностей. Это облегчает модификацию базы данных и поддержание ее целостности. Даже при отсутствии средств одновременного доступа ко многим таблицам нежелателен проект, в котором информация о многих типах сущностей перемешана в одной таблице. SQL же обладает механизмом для одновременной или последовательной обработки данных из нескольких взаимосвязанных таблиц. В нем реализованы возможности “соединять” или “объединять” несколько таблиц и так называемые “вложенные подзапросы”.
Объединения – это связь нескольких таблиц в запросе. Объединение соединяет все строки одной таблицы со строками другой таблицы и обычно сопровождается условием объединения таблиц.
Существует три типа объединений, используемых в предложении FROM: левое внешнее (LEFT JOIN), правое внешнее (RIGHT JOIN) и внутреннее (INNER JOIN).
Ниже перечислены аргументы операций LEFT JOIN, RIGHT JOIN, INNER JOIN:
таблица_1, таблица_2 – имена таблиц, записи которых подлежат объединению;
поле_1, поле_2 – имена объединяемых полей. Поля должны иметь одинаковый тип данных и содержать данные одного рода, однако могут иметь разные имена;
оператор – любой оператор сравнения: “=,” “<,” “>,” “<=,” “>=,” или “<>”;
ON – определяет критерии объединения.
В левом внешнем объединении всем записям в таблице_1 поставлены в соответствие записи из таблицы_2, отвечающие заданным критериям. Записи из таблицы_1 включаются даже тогда, если для них нет соответствующих записей в таблице_2.
Правое внешнее объединение аналогично левому, но в данном случае отображаются все записи таблицы_2 и соответствующие критерию записи таблицы_1.
Внутреннее объединение возвращает строки обеих таблиц, включаемых в операцию, которые соответствуют заданным критериям.
Кроме механизма объединений в SQL есть механизм вложенных подзапросов, позволяющий объединить несколько простых запросов в едином предложении SELECT. Иными словами, вложенный подзапрос – это уже знакомый подзапрос, который вложен в WHERE-фразу другого вложенного подзапроса или WHERE-фразу основного запроса:
SELECT * FROM таблица_1 WHERE поле_1 = (SELECT поля_2 FROM таблица_1 WHERE условие);
Чтобы оценить внешний (основной) запрос, сначала надо оценить внутренний запрос (или подзапрос) внутри предложения WHERE. Основной запрос затем выполняется, как обычно, с полученными результатами. Подзапрос должен выбрать один и только один столбец, а тип данных этого столбца должен совпадать с тем значением, с которым он будет сравниваться в предикате. В свою очередь внутренний запрос также может содержать подзапрос.
Оптимизация запросов
Язык SQL часто называют непроцедурным, так как пользователь указывает, что делать, а не как делать, т.е. пользователь говорит, что ему нужно, без указания процедуры получения результата. Процесс навигации по хранимой базе данных для удовлетворения пользовательского запроса выполняется СУБД автоматически, а не пользователем вручную. Поэтому реляционные системы иногда называют системами автоматической навигации.
Ответственность за то, как выполняется автоматическая навигация, несет очень важный компонент СУБД – оптимизатор. Другими словами, работа оптимизатора заключается в том, чтобы для каждого запроса пользователя выбрать самый эффективный способ выполнения этого запроса. Например, при поиске записи существует, по крайней мере, два способа выполнения запроса:
1) последовательный физический просмотр таблицы (хранимой версии), пока не будет найдена требуемая запись;
2) если есть индекс для столбца таблицы, содержащего запись, то переход с помощью этого индекса непосредственно к записи.
Оптимизатор выберет, какую именно из этих стратегий применить. В общем случае для реализации любого определенного отдельного реляционного запроса оптимизатор будет делать выбор стратегии на основе соображений, подобных следующим:
– на какие таблицы есть ссылки в запросе (может быть несколько ссылок, если, например, используются какие-нибудь соединения);
– насколько велики эти таблицы;
– какие индексы созданы;
– как выбраны эти индексы;
– как физически группируются данные на диске и т.д.
Пользователь указывает в запросе, какие данные требуются для него, а не как получить эти данные, стратегия доступа к данным выбирается оптимизатором.