Современные СУБД в большинстве своем построены на реляционной модели данных. Чтобы получить информацию из таблиц базы данных в качестве языка манипулирования данными с теоретической точки зрения можно использовать 3 абстрактных языка:
- реляционной алгебры;
- реляционного исчисления на кортежах;
- реляционного исчисления на доменах.
В качестве использования языка работы с данными на практике в 70-е годы прошлого века фирмой IBM был разработан язык структурных запросов SQL, который стал в дальнейшем фактическим стандартом при работе с БД. В наши дни наметился переход к крупным корпоративным СУБД типа Oracle, Informix, Sybase, DB2, Progress, PostgreSQL, делающий актуальным изучение языка SQL как на практике, так и в теории, так как за основу элементов языка SQL взяты положения теории отношений, теории множеств и логики.
Простые запросы на языке SQL
Для формирования запроса на языке SQL используется оператор Select. Данный оператор используют:
- при выборке данных из базы данных;
- при получении новых строк в составе оператора Insert;
- при обновлении информации в составе оператора Update.
В операторе Select содержатся 8 спецификаторов, расположенных в следующем порядке:
- Select.
- From.
- Join.
- Where.
- Group by.
- Having.
- Order by.
- Into temp.
Обязательные спецификаторы Select и From, составляющие основу всех запросов к БД, так как ими определяются таблицы и столбцы таблиц для выбора данных.
Спецификаторы Join (их может быть несколько) используют при перечислении присоединяемых таблиц и указании условий соединения.
Спецификатор Where используется при выборке определенных строк или указании условий соединения. Спецификатор Order by используют при изменении порядка получаемых данных. Спецификатор Into temp используют при сохранении этих результатов в виде таблицы, чтобы выполнить последующие запросы. Дополнительные спецификаторы Group by (спецификатор группирования) и Having (спецификатор условия выборки группы) используются при выполнении более сложных выборок данных.
Группирование
Оператором Group by группируется таблица, представленная фразой From в группы таким образом, чтобы все строки каждой группы имели одинаковое значение полей, указанное во фразе Group by. Затем, относительно каждой группы перекомпонованной таблицы (не к каждой строке первоначальной таблицы) применяют фразу Select, в итоге каждое выражение фразы Select примет единственное значение для группы.
Роль фразы Having для групп аналогична роли фразы Where для строк и используется для исключения групп так же, как и Where - для исключения строк. Выражение во фразе Having имеет единственное значение для группы.
Соединения таблиц
В классической реляционной алгебре Кодда имеется 9 реляционных операций, последовательное использование которых дает возможность реализовать выборку любых данных. 3 из 9 связаны с соединением таблиц:
- операция взятия декартова произведения;
- операция соединения;
- операция эквисоединения.
В операции взятия декартова произведения содержатся все возможные комбинации конкатенаций кортежей (строк) из соединяемых таблиц.
Операция соединения служит для соединения кортежей соединяемых таблиц в соответствии с указанным условием соединения. Строки, не удовлетворяющие условию соединения, исключаются.
Операция эквисоединения представляет собой частный случай операции соединения по условию равенства атрибутов.
Помимо этого данная операция имеет естественное (внешнее) соединение, которое может сохранять строки, не имеющие соответствий в другой таблице. При этом недостающие поля заполняются значениями NULL. Решение о вхождении таких строк в результирующий набор зависит от того, в какой из соединяемых таблиц отсутствуют данные, и от типа внешнего соединения.
Внешние соединения бывают 3 видов:
- Левое внешнее соединение содержит хотя бы 1 экземпляр каж¬дой строки из таблицы, указываемой слева от ключевого слова JOIN. Отсутствую¬щие поля из правой таблицы заполняются значениями NULL.
- Правое внешнее соединение всегда содержит хотя бы 1 экземпляр каждой строки из таблицы, указываемой справа от JOIN. Отсут-ствующие поля левой таблицы заполнятся значениями NULL.
- Полное внешнее соединение всегда содержит хотя бы 1 экземпляр каждой строки каждой из соединяемых таблиц. Отсутствующие поля в записях результирующего набора заполнятся значениями NULL.
При построении соединений стандартом ANSI предусмотрена следующая конструкция:
FROM источник1
[Nutural] тип соединения JOIN источник2 [on условие [,...] | Using (поле1 [,...])],
где:
- источник1 - представлен первым из соединяемых наборов данных (имя таблицы или подзапрос);
- [Nutural] - 2 набора данных соединяются по равным значениям одноименных полей. Конструкции Оn и Using в данном случае использовать нельзя;
- тип соединения может быть представлен следующими возможными видами соединений:
- [Inner] - внутренним;
- Left [Outer] - левым внешним;
- Right [Outer] - правым внешним;
- Full [Outer] - полным внешним;
- Cross – декартовым произведением;
- Источник2 – это второй из соединяемых наборов данных (имя таблицы или подзапрос);
- On условие [,...] представляет отношение между источниками (аналогичен критерию в конструкции Where);
- Using (поле1 [,...]) - одноименные поля источников, по совпадающим значениям которых производится соединение. В отличии от Nutural ограничивается некоторыми одноименными полями, в то время как Nutural соединяет по всем одноименным полям.
- Простое декартово произведение.
- Простое эквисоединение.
- Соединение таблиц с дополнительным условием.
- Соединение таблицы с ней самой.
- Внутреннее соединение
- Соединение 3-х таблиц.
- Простое внешнее соединение 2-х таблиц.
- Внешнее соединение внутреннего соединения с 3-ей таблицей.
Подзапросы
Оператор Select, который является вложенным в спецификатор Where другого оператора Select (или одного из операторов Insert, Delete, Update), называют подзапросом. Каждый подзапрос в своем составе имеет спецификаторы Select и From и заключается в круглые скобки для указания серверу баз данных на приоритет операции быть выполненной первой.
Подзапросы различают коррелированные и некоррелированные. Подзапрос коррелированный в том случае, когда его значение зависит от значения, производимого внешним оператором Select, содержащим этот подзапрос. Любые другие виды запроса называются некоррелированными.
Важным свойством коррелированного подзапроса является то, что он, завися от значения результата внешнего оператора Select, выполняется повторно по 1 разу для каждого значения, производимого внешним оператором Select. Некоррелированный подзапрос выполняется лишь 1 раз.
Для включения подзапроса в спецификатор Where оператора Select используются ключевые слова: ALL, ANY, IN, EXISTS.
ALL
Данное ключевое слово, которое указывается перед подзапросом, используют для определения выполнения условия сравнения для каждого возвращаемого подзапросом значения. В случае не возврата подзапросом значений условие поиска считается выполненным.
ANY
Данное ключевое слово, которое указывается перед запросом, используют для определения выполнения сравнения, по крайней мере, для 1 значения, которое возвращается подзапросом. В случае не возврата подзапросом значений условие поиска считается не выполненным.
IN
Данное ключевое слово используется:
- в простом подзапросе;
- в подзапросе с несколькими уровнями вложенности;
- при использовании одной и той же таблицы в подзапросе внешнего запроса;
- в подзапросе с оператором сравнения отличным от IN;
- в простом коррелированном подзапросе;
- в коррелированном подзапросе с использованием в коррелированном и внешнем запросе одной и той же таблицы.
EXISTS
Данное ключевое слово используется в следующих случаях:
-
В качестве квантора существования.
В языке SQL предикат с квантором существования представляют выражением вида: EXISTS (select * from...).
Это выражение бывает истинным лишь в том случае, когда результат вычисления подзапроса, который представлен с помощью Select * From является непустым множеством, т.е. в случае существования какой-либо записи в таблице, которая указана в слове From подзапроса, удовлетворяющего условию Where этого подзапроса.
-
В запросе, реализующем квантор общности.
Квантор общности FORALL в SQL не поддерживается, однако он может быть выражен через квантор существования при помощи тождества FORALL x(p)=NOT(EXISTS x(NOT(p))).
Помимо вышеперечисленного в подзапросах используются функции манипулирования данными (delete, Insert, Update).