
Организация баз данных
..pdf
5.1 Язык SQL |
101 |
одной или нескольких таблиц, которые содержат необходимые для отбора записи; предложение GROUP BY в SQL-предложении объединяет записи с одинаковыми значениями в указанном списке полей в одну запись. Если инструкция SELECT содержит статистическую функцию SQL, например Sum или Count, то для каждой записи будет вычислено итоговое значение; предложение HAVING определяет, какие сгруппированные записи, выданные в результате выполнения запроса, отображаются при использовании инструкции SELECT с предложением GROUP BY. После того как записи результирующего набора будут сгруппированы с помощью предложения GROUP BY, предложение HAVING отберет те из них, которые удовлетворяют условиям отбора, указанным в предложении HAVING; предложение ORDER BY позволяет отсортировать записи, полученные в результате запроса, в порядке возрастания или убывания на основе значений указанного поля или полей.
Следует отметить, что инструкции SELECT не изменяют данные в базе данных. Для более наглядного представления результатов выполнения запросов на выборку добавим в нашу базу данных таблицы «Дисциплина» и «Успеваемость» и добавим поле «Номер_группы» в таблицу «Студенты» (рис. 5.9), а также заполним
эти таблицы.
Рис. 5.9 – Обновленная схема базы данных
На рисунке 5.10 приведено содержимое таблиц «Студент», «Успеваемость»
и«Дисциплина».
Вследующем примере представлен простейший запрос на выборку записей
из таблицы «Студенты», в котором отбираются студенты, обучающиеся в группе 432-1.
. . . . . . . . . . . . . . . . . . . . . . Пример 5.8 . . . . . . . . . . . . . . . . . . . . .
SELECT Студент.Номер_зачетной_книжки, Студент.ФИО_студента, Студент.Номер_группы
FROM Студент
WHERE Студент.Номер_группы='432-1';
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

102 |
Глава 5. Языки управления и манипулирования данными |
Рис. 5.10 – Содержимое таблиц базы данных
На рисунке 5.11 представлен результат выполнения этого запроса, были найдены две записи, удовлетворяющие критерию запроса.
Рис. 5.11 – Результат выполнения запроса
Помимо обычных знаков сравнения (=, <, >, <=, >=, <>) в языке SQL в условии отбора используется ряд ключевых слов:
•Is not null — выбрать только непустые значения;
•Is null — выбрать только пустые значения;
•Between. . .And определяет принадлежность значения выражения указанному диапазону.
Синтаксис:
выражение [Not] Between значение_1 And значение_2,
где выражение — выражение, определяющее поле, значение которого проверяется на принадлежность к диапазону; значение_1, значение_2 — выражения, задающие границы диапазона.
Если значение поля, определенного в аргументе выражение, попадает в диапазон, задаваемый аргументами значение_1 и значение_2 (включительно), то оператор Between. . .And возвращает значение True; в противном случае возвращается

5.1 Язык SQL |
103 |
значение False. Логический оператор Not позволяет проверить противоположное условие: что выражение находится за пределами диапазона, заданного с помощью аргументов значение_1 и значение_2.
Оператор Between. . .And часто используют для проверки: попадает ли значение поля в указанный диапазон чисел.
Если выражение, значение_1 или значение_2 имеет значение NULL, оператор Between. . .And возвращает значение NULL.
Оператор Like используется для сравнения строкового выражения с образцом. Синтаксис:
выражение Like «образец»,
где выражение — выражение SQL, используемое в предложении WHERE; образец — строка, с которой сравнивается выражение.
Оператор Like используется для нахождения в поле значений, соответствующих указанному образцу. Для аргумента образец можно задавать полное значение (например, Like «Иванов») или использовать подстановочные знаки для поиска диапазона значений (например, Like «Ив*»).
В таблице 5.3 приведен перечень подстановочных символов и пример их использования в диалекте языка SQL, используемого в MS Access (Microsoft Jet SQL).
Таблица 5.3 – Параметры оператора Like
Тип совпадения |
Образец |
Совпадение |
Несовпадение |
|
(True) |
(False) |
|||
|
|
|||
|
|
|
|
|
Несколько символов |
a*a |
aa, aBa, aBBBa |
aBC |
|
|
|
|
|
|
|
*ab* |
abc, AABB, Xab |
aZb, bac |
|
|
|
|
|
|
Специальный символ |
a[*]a |
a*a |
aaa |
|
Несколько символов |
ab* |
abcdefg, abc |
cab, aab |
|
Одиночный символ |
a?a |
aaa, a3a, aBa |
aBBBa |
|
|
|
|
|
|
Одиночная цифра |
a#a |
a0a, a1a, a2a |
aaa, a10a |
|
|
|
|
|
|
Диапазон символов |
[a-z] |
f, p, j |
2, & |
|
|
|
|
|
|
Вне диапазона |
[!a-z] |
9, &,% |
b, a |
|
Не цифра |
[!0–9] |
A, a, &, |
0, 1, 9 |
|
|
|
|
|
|
Комбинированное выражение |
a[!b-m]# |
An9, az0, a99 |
abc, aj0 |
|
|
|
|
|
Внутреннее соединение
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Операция INNER JOIN объединяет записи из двух таблиц, если связующие поля этих таблиц содержат одинаковые значения.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Синтаксис операции:
FROM таблица_1 INNER JOIN таблица_2 ON таблица_1.поле_1 оператор таблица_2.поле_2,
где таблица_1, таблица_2 — имена таблиц, записи которых подлежат объединению; поле_1, поле_2 — имена объединяемых полей. Поля должны иметь одинаковый тип

104 |
Глава 5. Языки управления и манипулирования данными |
данных и содержать данные одного рода, однако эти поля могут иметь разные имена; оператор — любой оператор сравнения: =, <, >, <=, >=, или <>.
Операцию INNER JOIN можно использовать в любом предложении FROM. Это самые обычные типы связывания. Они объединяют записи двух таблиц, если связующие поля обеих таблиц содержат одинаковые значения.
В следующем примере составим запрос, выдающий сведения об успеваемости студентов по всем изученным ими дисциплинам.
. . . . . . . . . . . . . . . . . . . . . . Пример 5.9 . . . . . . . . . . . . . . . . . . . . .
SELECT Студент.ФИО_студента as ФИО, Дисциплина.Наименование_дисциплины as Предмет, Успеваемость.Семестр, Успеваемость.Оценка
FROM Студент INNER JOIN (Дисциплина INNER JOIN Успеваемость ON Дисциплина.Код_дисциплины = Успеваемость.Код_дисциплины)
ON Студент.Код_студента = Успеваемость.Код_студента;
На рисунке 5.12 представлен результат выполнения этого запроса.
Рис. 5.12 – Результат выполнения запроса с внутренним соединением
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Внешнее соединение
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Операции LEFT JOIN, RIGHT JOIN объединяют записи исходных таблиц при использовании в любом предложении FROM.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Операция LEFT JOIN используется для создания внешнего соединения, при котором все записи из первой (левой) таблицы включаются в результирующий набор, даже если во второй (правой) таблице нет соответствующих им записей.

5.1 Язык SQL |
105 |
Операция RIGHT JOIN используется для создания внешнего объединения, при котором все записи из второй (правой) таблицы включаются в результирующий набор, даже если в первой (левой) таблице нет соответствующих им записей.
Синтаксис операции:
FROM таблица_1 [LEFT | RIGHT] JOIN таблица_2
ON таблица_1.поле_1 оператор таблица_2.поле_2.
В следующем примере в результате выполнения запроса будут найдены все студенты и их успеваемость, при этом в результирующий набор данных будут также включены студенты, чьи сведения об успеваемости отсутствуют.
. . . . . . . . . . . . . . . . . . . . . . Пример 5.10 . . . . . . . . . . . . . . . . . . . . .
SELECT Студент.ФИО_студента, Дисциплина.Наименование_дисциплины, Успеваемость.Семестр, Успеваемость.Оценка
FROM Студент LEFT JOIN (Дисциплина RIGHT JOIN Успеваемость ON Дисциплина.Код_дисциплины = Успеваемость.Код_ дисциплины)
ON Студент.Код_студента = Успеваемость.Код_студента;
На рисунке 5.13 представлен результат выполнения этого запроса, где видно, что по сравнению с предыдущим примером добавлена еще одна запись о студенте Глазове Олеге Владимировиче.
Рис. 5.13 – Результат выполнения запроса с внешним соединением
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Важно отметить, что операции LEFT JOIN или RIGHT JOIN могут быть вложены в операцию INNER JOIN, но операция INNER JOIN не может быть вложена в операции LEFT JOIN или RIGHT JOIN.

106 |
Глава 5. Языки управления и манипулирования данными |
Перекрестные запросы
В Jet SQL существует такой вид запросов, как перекрестный. В таком запросе отображаются результаты статистических функций — суммы, средние значения и др., а также количество записей. При этом подсчет выполняется по данным одного из полей таблицы. Результаты группируются по двум наборам данных, один из которых расположен в левом столбце таблицы, а другой — в заголовке таблицы. Например, при необходимости вычислить средний балл за семестр студентов, обучающихся в разных группах, необходимо реализовать перекрестный запрос, результат выполнения которого будет представлен в виде таблицы, где заголовками строк будут служить названия предмета, заголовками столбцов — номера групп, а в полях таблицы будет рассчитан средний балл студентов группы по каждому предмету.
Для создания перекрестного запроса необходимо использовать следующую инструкцию:
TRANSFORM статистическая_функция инструкция_SELECT
PIVOT поле [IN (значение_1[, значение_2[,. . .]])],
где статистическая_функция — статистическая функция SQL, обрабатывающая указанные данные; инструкция_SELECT — запрос на выборку; поле — поле или выражение, которое содержит заголовки столбцов для результирующего набора; значение_1, значение_2 — фиксированные значения, используемые при создании заголовков столбцов.
. . . . . . . . . . . . . . . . . . . . . . Пример 5.11 . . . . . . . . . . . . . . . . . . . . .
Составим SQL-запрос, реализующий описанный выше пример. TRANSFORM Avg(Успеваемость.Оценка)
SELECT Дисциплина.Наименование_дисциплины as [Предмет] FROM Студент INNER JOIN
(Дисциплина INNER JOIN Успеваемость ON Дисциплина.Код_дисциплины = Успеваемость.Код_дисциплины) ON Студент.Код_студента = Успеваемость.Код_ студента
GROUP BY Дисциплина.Наименование_дисциплины, Успеваемость.Код_дисциплины
PIVOT Студент.Номер_группы;
В результате выполнения такого перекрестного SQL-запроса формируется набор данных, представленный на рисунке 5.14.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Таким образом, когда данные сгруппированы с помощью перекрестного запроса, можно выбирать значения из заданных столбцов или выражений и определять как заголовки столбцов. Это позволяет просматривать данные в более компактной форме, чем при работе с обычным запросом на выборку. Отметим, что перекрестные запросы удобно использовать для формирования статистических отчетов.

5.1 Язык SQL |
107 |
Рис. 5.14 – Результат выполнения перекрестного запроса
Подчиненные запросы
Часто возникает ситуация, когда желаемый результат нельзя получить с помощью одного SQL-запроса. Одним из способов решения такой задачи является использование подчиненных запросов в составе главного SQL-запроса. Подчиненным SQL-запросом называют инструкцию SELECT, включаемую в инструкции SELECT, SELECT. . .INTO, INSERT. . .INTO, DELETE или UPDATE или в другой подчиненный запрос. Подчиненный запрос может быть создан одним из трех способов, синтаксис которых представлен ниже:
1)сравнение [ANY | ALL | SOME] (инструкция SQL);
2)выражение [NOT] IN (инструкция SQL);
3)[NOT] EXISTS (инструкция SQL),
где сравнение — выражение и оператор сравнения, который сравнивает выражение с результатами подчиненного запроса; выражение — выражение, для которого проводится поиск в результирующем наборе записей подчиненного запроса; инструкция SQL — инструкция SELECT, заключенная в круглые скобки.
Подчиненный запрос можно использовать вместо выражения в списке полей инструкции SELECT или в предложениях WHERE и HAVING. Инструкция SELECT используется в подчиненном запросе для задания набора конкретных значений, вычисляемых в выражениях предложений WHERE или HAVING.
Предикаты ANY или SOME, являющиеся синонимами, используются для отбора записей в главном запросе, которые удовлетворяют сравнению с записями, отобранными в подчиненном запросе.
Предикат ALL используется для отбора в главном запросе только тех записей, которые удовлетворяют сравнению со всеми записями, отобранными в подчиненном запросе. Если в предыдущем примере предикат ANY заменить предикатом ALL, результат запроса будет включать только тех студентов, у которых средний балл больше 4. Это условие является значительно более жестким.
Предикат IN используется для отбора в главном запросе только тех записей, которые содержат значения, совпадающие с одним из отобранных подчиненным запросом.
Предикат NOT IN используется для отбора в главном запросе только тех записей, которые содержат значения, не совпадающие ни с одним из отобранных подчиненным запросом.
Предикат EXISTS (с необязательным зарезервированным словом NOT) используется в логическом выражении для определения того, должен ли подчиненный запрос возвращать какие-либо записи.

108 |
Глава 5. Языки управления и манипулирования данными |
Вподчиненном запросе можно использовать псевдонимы таблиц для ссылки на таблицы, перечисленные в предложении FROM, расположенном вне подчиненного запроса.
Вследующем примере используем подчиненный запрос на выборку в инструкции UPDATE — увеличим сумму задолженности за обучение не для всех студентов,
атолько для студента группы 423-1 Иванова Ивана Петровича.
. . . . . . . . . . . . . . . . . . . . . . Пример 5.12 . . . . . . . . . . . . . . . . . . . . .
UPDATE Задолженность_за_обучение
SET Сумма_задолженности = Сумма_задолженности * 1.1 WHERE Код_студента =
(Select Код_студента FROM Студент WHERE ФИО_Студента = 'Иванов Иван Петрович'AND Номер_группы = '423-1');
На рисунке 5.15 представлена таблица «Задолженность_ за_обучение» до и после выполнения запроса. (Значение поля «Код_студента» для Иванова Ивана Петровича равно 1.)
Рис. 5.15 – Результат выполнения запроса на обновление с подчиненным запросом
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Некоторые подчиненные запросы можно использовать в перекрестных запросах как предикаты (в предложении WHERE). Подчиненные запросы, используемые для вывода результатов (в списке SELECT), нельзя использовать в перекрестных запросах.
Запрос на объединение
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Операция UNION создает запрос на объединение, который объединяет результаты нескольких независимых запросов или таблиц.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

5.1 Язык SQL |
109 |
Синтаксис команды:
[TABLE] запрос_1 UNION [ALL] [TABLE] запрос_2 [UNION[ALL] [TABLE] запрос_n [. . .]],
где запрос_1–n — инструкция SELECT или имя сохраненной таблицы, перед которым стоит зарезервированное слово TABLE.
В одной операции UNION можно объединить в любом наборе результаты нескольких запросов, таблиц и инструкций SELECT.
. . . . . . . . . . . . . . . . . . . . . . Пример 5.13 . . . . . . . . . . . . . . . . . . . . .
Для выполнения следующего запроса создадим в БД и заполним таблицу «Абитуриент» (рис. 5.16).
Рис. 5.16 – Таблица «Абитуриент»
Здесь объединяются существующая таблица «Студент» и запрос на выборку всех записей из таблицы «Абитуриент».
TABLE Студент
UNION ALL SELECT *
FROM Абитуриент;
Результат выполнения запроса представлен на рисунке 5.17.
Рис. 5.17 – Результат выполнения запроса на объединение
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
По умолчанию повторяющиеся записи не возвращаются при использовании операции UNION, однако в нее можно добавить предикат ALL, чтобы гаранти-

110 |
Глава 5. Языки управления и манипулирования данными |
ровать возврат всех записей. Кроме того, такие запросы выполняются несколько быстрее.
Таблица и все запросы, включенные в операцию UNION, должны отбирать одинаковое число полей, при этом имена полей, типы данных и размеры полей могут не совпадать.
В каждом аргументе «Запрос» допускается использование предложения GROUP BY или HAVING для группировки возвращаемых данных. В конец последнего аргумента «Запрос» можно включить предложение ORDER BY, чтобы отсортировать возвращенные данные.
Удаление записей
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Инструкция DELETE создает запрос на удаление записей из одной или нескольких таблиц, перечисленных в предложении FROM и удовлетворяющих предложению WHERE.
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Синтаксис команды:
DELETE [Таблица.*]
FROM таблица
WHERE условие Отбора,
где Таблица — необязательное имя таблицы, из которой удаляются записи; таблица — имя таблицы, из которой удаляются записи; условие Отбора — выражение, определяющее удаляемые записи.
С помощью инструкции DELETE можно осуществлять удаление большого количества записей. Данные из таблицы также можно удалить и с помощью инструкции DROP, однако при таком удалении теряется структура таблицы. Если же применить инструкцию DELETE, удаляются только данные. При этом сохраняются структура таблицы и все остальные ее свойства, такие как атрибуты полей
ииндексы.
Вследующем примере из таблицы «Абитуриент» будет удален абитуриент Авдеев Н. В.
. . . . . . . . . . . . . . . . . . . . . . Пример 5.14 . . . . . . . . . . . . . . . . . . . . .
DELETE
FROM Абитуриент
WHERE ФИО_Абитуриента = 'Авдеев Н. В.'
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Запрос на удаление удаляет записи целиком, а не только содержимое указанных полей. Нельзя восстановить записи, удаленные с помощью запроса на удаление. Чтобы узнать, какие записи будут удалены, необходимо посмотреть результаты запроса на выборку, использующего те же самые условия отбора в предложении Where, а затем выполнить запрос на удаление.