Вы находитесь на странице: 1из 36

Язык запросов SQL .............................................................................................

2
1.1. Основы языка SQL ............................................................................................ 2
1.2. Формы языка SQL ............................................................................................. 2
1.3. Группы операторов SQL ................................................................................... 3
1.4. Инструкции и имена.......................................................................................... 4
1.5. Типы данных ...................................................................................................... 5
1.6. Оператор выборки SELECT ............................................................................. 6
1.6.1. Предложение FROM ................................................................................... 8
1.6.2.. Предложение WHERE ................................................................................ 9
1.6.3. Предложение ORDER BY.......................................................................... 14
1.7. Вычисления и подведение итогов в запросах: ............................................. 15
1.7.1. Построение вычисляемых полей .............................................................. 15
1.7.2. Использование итоговых функций........................................................... 17
1.8. Преобразование вывода из встроенной функции ........................................ 18
1.9. Предложение GROUP BY............................................................................... 18
2.1. Предложение HAVING ................................................................................... 21
2.2. Построение нетривиальных запросов ........................................................... 22
2.2.1. Понятие подзапроса ................................................................................. 22
2.2.2. Использование подзапросов, возвращающих единичное значение ....... 23
2.2.3. Использование подзапросов, возвращающих множество значений .... 25
2.3. Запросы модификации данных ...................................................................... 25
2.3.1. Запрос добавления ..................................................................................... 26
2.3.2. Запрос удаления ......................................................................................... 27
2.3.3. Запрос обновления ..................................................................................... 28
2.4. Понятие «целостность данных»..................................................................... 29
2.5. Операции с индексами .................................................................................... 32
2.6. Объединения таблиц ....................................................................................... 33
2.6.1. Левое объединение таблиц ....................................................................... 35
2.6.2. Правое объединение таблиц..................................................................... 35
2.6.3. Полное объединение таблиц..................................................................... 36
Язык запросов SQL
1.1. Основы языка SQL

Изначально создаваемый как инструмент для выборки и представления


данных, содержащихся в базе данных, SQL сегодня представляет собой нечто
гораздо большее. Несмотря на то, что выборка данных по – прежнему остается
одной из наиболее важных функций SQL, сейчас этот язык используется для
реализации всех функциональных возможностей, необходимых для управления
БД, в том числе и для:
организации данных – SQL позволяет определять и изменять структуру
представления данных, а также устанавливать отношения;
обработки данных – SQL позволяет изменять содержимое базы
данных: добавлять новые данные, удалять или обновлять уже имеющиеся в ней
данные;
управления доступом – SQL позволяет ограничивать возможности
пользователя по чтению и изменению данных (зашита данных от
несанкционированного доступа) и координировать их совместное
использование пользователями, работающими параллельно.
Операторы SQL встраиваются в базовый язык, например PASCAL,
FORTRAN или С, и дают возможность получать доступ к базам данных из
прикладных программ. Кроме того, из многих языков программирования
операторы SQL можно посылать СУБД в явном виде, используя интерфейс
вызовов функций.

1.2. Формы языка SQL

Формы структурированного языка запросов SQL

Интерактивный SQL Статический SQL.

Динамический SQL Встроенный SQL


Рисунок 1.1 – Формы языка SQL

Интерактивный SQL позволяет конечному пользователю в


интерактивном режиме выполнять SQL – операторы. Все СУБД
предоставляют инструментальные средства для работы с базой данных в
интерактивном режиме. Например, СУБД Oracle включает утилиту SQL*Plus,
позволяющую в строчном режиме выполнять большинство SQL – операторов.
Статический SQL может реализовываться как встроенный SQL или
модульный SQL. Операторы статического SQL определены уже в момент
компиляции программы.
Динамический SQL позволяет формировать операторы SQL во время
выполнения программы.
Встроенный SQL позволяет включать операторы SQL в код программы
на другом языке программирования (например, C++).

1.3. Группы операторов SQL

Язык SQL определяет:


 операторы языка, называемые иногда командами языка SQL;
 типы данных;
 набор встроенных функций.
По своему логическому назначению операторы языка SQL часто
разбиваются на следующие группы:
 язык определения данных DDL (Data Definition Language);
 язык манипулирования данными DML (Data Manipulation Language).
Язык определения данных включает операторы, управляющие
объектами базы данных. К последним относятся таблицы, индексы,
представления. Для каждой конкретной базы данных существует свой набор
объектов базы данных, который может значительно расширять набор
объектов, предусмотренный стандартом. В некоторых СУБД, таких как Oracle,
все объекты базы данных, принадлежащие одному пользователю, образуют
схему базы данных. С другой стороны, в стандарте SQL92 термином «схема»
стали называть группу взаимосвязанных таблиц.

Язык определения данных DDL

CREATE TABLE DROP TABLE


создание таблицы удаление таблицы

ALTER TABLE
модификация таблицы

Рисунок 1.2 – Язык DDL

Язык манипулирования данными включает операторы, управляющие


содержанием таблиц базы данных и извлекающими информацию из этих
таблиц.
Операторы языка DML

SELECT UPDATE
извлечение данных из одной или изменение значений полей в
нескольких таблиц таблице

DELETE INSERT
удаление строк из таблицы добавление строк в таблицу

Рисунок 1.3 – Язык DML

Термины и определения:
Ключевое слово означает оператор, команду, инструкцию
Оператор определения (::=),
[ ] – не обязательный элемент
{ } – обозначают логическую группу
/ – возможны варианты

1.4. Инструкции и имена

SQL представлен множеством инструкций, каждая из которых


предписывает СУБД выполнить определенное действие: создать таблицу,
извлечь данные, добавить в таблицу новые данные и т. п. Инструкция SQL
начинается с команды – ключевого слова, описывающего действие,
выполняемое инструкцией. Типичными являются команды
CREATE (создать), INSERT (добавить), SELECT (выбрать), DELETE (удалить).
Следом за командой указывается одно или несколько предложений.
Предложение описывает данные, с которыми должна работать инструкция, или
уточняет действие, выполняемое инструкцией. Предложения в инструкции
делятся на обязательные и необязательные.
Каждое предложение начинается с ключевого слова, например – WHERE
(где), FROM (откуда), INTO (куда). Многие предложения в качестве параметров
содержат имена таблиц или столбцов; некоторые из них могут содержать
дополнительные ключевые слова, константы и выражения.
У каждого объекта в базе данных есть уникальное имя. Имена
используются в инструкциях SQL и указывают, над каким объектом базы
данных инструкция должна выполнить действие. В соответствии со стандартом
ANSI/ISO имена в SQL могут содержать от 1 до 18 символов, начинаться с
буквы и не должны включать пробелов или специальных символов пунктуации.
В стандарте SQL2 максимальное число символов в
имени увеличено до 128. На практике в различных СУБД поддержка
именования реализована по – разному: в DB2, например, имена пользователей
не могут превышать восьми символов, а имена таблиц и столбцов могут быть
более длинными. В различных СУБД также существуют и различные подходы
к использованию в именах специальных
символов. В инструкциях SQL могут использоваться как полные имена
объектов, так и короткие. Полное имя таблицы (в отличие от короткого)
содержит имя пользователя и короткое имя таблицы, разделенные точкой:
< Имя_пользователя >. < Имя_таблицы >
При этом уникальность именования таблицы сохраняется в случае, если в
рамках одной базы данных разные пользователи создают таблицы с
одинаковыми именами.
Полное имя столбца в свою очередь состоит из полного ( или короткого)
имени таблицы, которой принадлежит столбец, и короткого имени столбца,
разделенных точкой: <Имя_пользователя>.<Имя_таблииы>.<Имя_столбца>
или <Имя таблицы>.<Имя столбиа>
В рамках одной таблицы не может быть определено двух столбцов с
одинаковыми именами, но в разных таблицах это возможно. При этом в
инструкциях SQL необходимо использовать полное именование столбцов.

1.5. Типы данных

Современные СУБД позволяют обрабатывать данные разнообразных


типов, среди которых наиболее распространенными можно назвать
следующие.
Целые числа (INT, SMALLINT (– 215flo+215) ,INTEGER ( – 231 до +231)). В
столбцах, имеющих такой тип данных, обычно хранятся данные о количестве и
возрасте сотрудников, идентификаторы. Десятичные числа (NUMERIC,
DECIMAL). В столбцах данного типа хранятся числа, имеющие дробную часть
с фиксированным количеством знаков после запятой, например курсы валют и
проценты.
Числа с плавающей запятой (REAL, FLOAT). Числа с плавающей
запятой представляют больший диапазон действительных значений, чем
десятичные числа. Строки символов постоянной длины (CHAR). В столбцах,
имеющих этот тип данных, хранятся имена и фамилии, географические
названия, адреса и т. п.
Строки символов переменной длины (VARCHAR). Столбцы этого типа
позволяют хранить символьные строки, длина которых изменяется в заданном
диапазоне. Денежные величины (MONEY, SMALL
MONEY). Наличие отдельного типа данных для хранения денежных
величин позволяет правильно форматировать их и снабжать признаком валюты
перед выводом на экран.
Дата и время (DATETIME, SMALLDATETIME). Поддержка особого
типа данных для значений дата/время широко распространена в различных
СУБД. Как правило, с этим типом данных связаны особые операции и
процедуры обработки. Булевы величины (BIT). Столбцы такого типа
данных позволяют хранить логические значения True (1) и False (0).
Длинный текст (TEXT). Многие СУБД поддерживают хранение в
столбцах текстовых строк длиной до 32КБ или 64КБ символов, а в
некоторых случаях и больше. Это позволяет хранить в базе данных целые
документы.
Неструктурированные потоки байтов (BINARY, VARBINARY, IMAGE).
Современные СУБД позволяют хранить и извлекать неструктурированные
потоки байтов переменной длины. Такой тип данных обычно используется для
хранения графических и видеоизображений, исполняемых файлов и других
неструктурированных данных.

Встроенные функции
Язык SQL содержит так называемые встроенные функции, которые
реализуют некоторые наиболее распространенные алгоритмы. Основной
особенностью этих функций является возможность их использования при
построении выражений. Встроенные функции, доступные при работе с SQL,
можно условно разделить на следующие группы:

Встроенные функции

математические функции строковые функции

функции для работы с


функции
величинами типа
конфигурирования
дата-время

функции системы
системные функции
безопасности

функции управления
статистические функции
метаданными

Рисунок 1.4 – Встроенные функции

1.6. Оператор выборки SELECT

Оператор SELECT - один из наиболее важных и самых распространенных


операторов SQL. Он позволяет производить выборки данных из таблиц и
преобразовывать к нужному виду полученные результаты. Будучи очень
мощным, он способен выполнять действия, эквивалентные операторам
реляционной алгебры, причем в пределах единственной выполняемой команды.
При его помощи можно реализовать сложные и громоздкие условия отбора
данных из различных таблиц.
Оператор SELECT - средство, которое полностью абстрагировано от
вопросов представления данных, что помогает сконцентрировать внимание на
проблемах доступа к данным. Примеры его использования наглядно
демонстрируют один из основополагающих принципов больших
(промышленных) СУБД: средства хранения данных и доступа к ним
отделены от средств представления данных. Операции над данными
производятся в масштабе наборов данных, а не отдельных записей.

SELECT [ALL | DISTINCT ] {*|[имя_столбца [AS новое__имя]]}


FROM имя таблицы [[AS] псевдоним] [,...п]
[WHERE <условие отбора>]
[ORDER BY <список полей> desc или asc]
[GROUP BY <список полей>]
Используются встроенные функции
COUNT – подсчет количества в группе
AVJ – среднее арифметическое значение
МАХ
SUM
MIN
[HAVING <критерии выбора групп>]

Обработка элементов оператора SELECT выполняется в следующей


последовательности:
 FROM – определяются имена используемых таблиц;
 WHERE – выполняется фильтрация строк объекта в соответствии с
заданными условиями, при формирования запроса можно использовать , >, and,
nod, or;
 GROUP BY – образуются группы строк , имеющих одно и то же
значение в указанном столбце;
 HAVING – фильтруются группы строк объекта в соответствии с
указанным условием, определят условие по которому группы включаются
в выходные данные, применяется только с GROUP BY;
 SELECT – устанавливается, какие столбцы должны присутствовать в
выходных данных;
 ORDER BY – определяется упорядоченность результатов выполнения
операторов. сортировка). Сортировать можно по нескольким полям. ASC
возрастающий он принят по умолчанию, DESC убывающий;
Порядок предложений и фраз в операторе SELECT не может быть
изменен. Только два предложения SELECT и FROM являются обязательными,
все остальные могут быть опущены. SELECT – закрытая операция:
результат запроса к таблице представляет собой другую таблицу. Существует
множество вариантов записи данного оператора, что иллюстрируется
приведенными ниже примерами.
Оператор SELECT определяет поля (столбцы), которые будут входить в
результат выполнения запроса. В списке они разделяются запятыми и
приводятся в такой очередности, в какой должны быть представлены в
результате запроса. Если используется имя поля, содержащее пробелы или
разделители, его следует заключить в квадратные скобки. Символом * можно
выбрать все поля, а вместо имени поля применить выражение из нескольких
имен.
Если обрабатывается ряд таблиц, то (при наличии одноименных полей
в разных таблицах) в списке полей используется полная спецификация поля,
т.е. Имя_таблицы. Имя_поля.

1.6.1. Предложение FROM

Предложение FROM задает имена таблиц и просмотров, которые


содержат поля, перечисленные в операторе SELECT. Необязательный параметр
псевдонима – это сокращение, устанавливаемое для имени таблицы.

Пример 1. Показать фамилии и имена студентов из таблицы «студент».

SELECT Fam, Imy FROM Student;

При указании списка полей данные будут выводиться в соответствие с


этим списком, а не в соответствии со структурой.

Пример 2. Показать студентов и день рождения.

SELECT Fam, Birthday FROM Student;


SELECT * FROM Student;

Пример 3. Показать города, в которых живут студенты.

SELECT City FROM Student;


SELECT DISTING City FROM Student;

Пример 4. Составить список сведений о всех клиентах.

SELECT * FROM Klient

Пример 5. Составить список всех фирм.

SELECT ALL Klient.Firma FROM Klient Или (что эквивалентно)


SELECT Klient.Firma FROM Klient

Результат выполнения запроса может содержать дублирующиеся


значения, поскольку в отличие от операций реляционной алгебры оператор
SELECT не исключает повторяющихся значений при выполнении выборки
данных.
Предикат DISTINCT следует применять в тех случаях, когда требуется
отбросить блоки данных, содержащие дублирующие записи в выбранных полях.
Значения для каждого из приведенных в инструкции SELECT полей должны
быть уникальными, чтобы содержащая их запись смогла войти в выходной
набор.
Причиной ограничения в применении DISTINCT является то
обстоятельство, что его использование может резко замедлить выполнение
запросов.
1.6.2.. Предложение WHERE

С помощью WHERE – параметра пользователь определяет, какие блоки


данных из приведенных в списке FROM таблиц появятся в результате
запроса. За ключевым словом WHERE! следует перечень условий поиска,
определяющих те строки, которые должны быть выбраны при выполнении
запроса. Существует пять основных типов условий поиска (или предикатов):
 сравнение, сравниваются результаты вычисления одного
выражения с результатами вычисления другого.
 диапазон: проверяется, попадает ли результат вычисления выражения
в заданный диапазон значений.
 принадлежность множеству, проверяется, принадлежит ли
результат вычислений выражения заданному множеству значений.
 соответствие шаблону, проверяется, отвечает ли некоторое
строковое значение заданному шаблону.
 значение NULL: проверяется, содержит ли данный столбец
определитель NULL (неизвестное значение).

Пример 6. Отобразить студентов с ФИО Петров.

SELECT Fam, Imy FROM Student WHERE Fam = "Петров";

Пример 7. Выбрать студентов 3 – его курса получивших стипендию.

SELECT Fam, Imy FROM Student WHERE Kurs = 3 AND Stip > 0;

Запрос выбирающий в следующем порядке Курс, ФИО, Стипендия.


SELECT Kurs, Fam, Stip FROM Student;

Сравнение

В языке SQL можно использовать следующие операторы сравнения: =


– равенство; < – меньше; > – больше; <= – меньше или равно; >= –
больше или равно; <> – не равно.

Пример 8. Показать все операции отпуска товаров объемом больше 20.

SELECT *
FROM Sdelka
WHERE Kolichestvo>20
Более сложные предикаты могут быть построены с помощью логических
операторов AND, OR или NOT, а также скобок, используемых для
определения порядка вычисления выражения. Вычисление выражения в
условиях выполняется по следующим правилам.
 Выражение вычисляется слева направо.
 Первыми вычисляются подвыражения в скобках.
 Операторы NOT выполняются до выполнения операторов AND и OR.
 Операторы AND выполняются до выполнения операторов OR.
Для устранения любой возможной неоднозначности рекомендуется
использовать скобки.

Пример 9. Вывести список товаров, цена которых больше или равна 100
и меньше или равна 150.

SELECT Nazvanie,Cena
FROM Tovar
WHERE Cena>=100 And Cena<=150

Пример 10. Вывести список клиентов из Москвы или из Самары.

SELECT Familiya, GorodKlienta


FROM Klient
WHERE GorodKlienta="Москва" Or GorodKlienta ="Самара"

Диапазон

Оператор BETWEEN используется для поиска значения внутри


некоторого интервала, определяемого своими минимальным и максимальным
значениями. При этом указанные значенья включаются в условие поиска.
BETWEEN <выражение 1> AND <выражение 2>

Пример 11. Вывести список товаров, цена которых лежит в диапазоне от


100 до 150.

SELECT Nazvanie, Cena


FROM Tovar
WHERE Cena Between 100 And 150

Пример 12. Список товаров, цена которых не лежит в


диапазоне от 100 до 150.

SELECT * FROM Subject


WHERE Hour BETWEEN 30 AND 40 i*
Пример 13. Получить сведения о студентах получающих стипендию от
100 – 140 руб.

SELECT * FROM Student WHERE Stip BETWEEN 100 AND 140

Пример 14. Вывести список товаров, цена которых лежит в диапазоне от


100 до 150.

SELECT Nazvanie, Cena


FROM Tovar
WHERE Cena Between 100 And 150

Принадлежность множеству

Оператор IN используется для сравнения некоторого значения со списком


заданных значений, при этом проверяется, соответствует ли результат
вычисления выражения одному из значений в предоставленном списке. При
помощи оператора IN может быть достигнут тот же результат, что и в случае
применения оператора OR, однако оператор IN выполняется быстрее.
IN (<выражение 1>, <выражение 2>)

Пример 15. Вывести список клиентов из Москвы или из Самары

SELECT Familiya, GorodKlienta


FROM Klient
WHERE GorodKlienta in ("Москва", "Самара")

NOT IN используется для отбора любых значений, кроме тех, которые


указаны в представленном списке.

Пример 16. Вывести список клиентов, проживающих не в Москве и не в


Самаре.

SELECT Familiya, GorodKlienta


FROM Klient
WHERE GorodKlienta Not in ("Москва","Самара")

Пример 17. Получить список предметов 1 – ого, 2 – ого семестра.

SELECT * FROM Subject WHERE Curs IN (1, 2) 4

Пример 18. Получить фамилии студентов 1 – ого, 4 – ого курса.

SELECT Fam FROM Student WHERE Curs IN (1, 4)

Пример 19. Определить товары, покупку которых осуществляют только


клиенты из Москвы, и никто другой.
SELECT DISTINCT Tovar.Nazvanie, Klient. GorodKlientа
FROM Tovar INNER JOIN
(Klient INNER JOIN Sdelka
ON Klient.KodKlientа=Sdelka.KodKlientа)
ON Tovar. КодTovarа=Sdelka. Kod Tovarа WHERE Tovar.Nazvanie NOT IN
(SELECT Tovar.Nazvanie
FROM Tovar INNER JOIN Klient INNER JOIN Sdelka
ON Klient.KodKlientа=Sdelka.KodKlientа)
ON Tovar.KodTovarа=Sdelka.KodTovarа
WHERE Klient.GorodKlientао'Москва')

Пример 20. Какие товары ни разу не купили московские клиенты?

SELECT DISTINCT Tovar.Nazvanie, Klient. GorodKlientа


FROM Tovar INNER JOIN
(Klient INNER JOIN Sdelka
ON Klient.KodKlientа=Sdelka.KodKlientа)
ON Tovar.KodTovarа=Sdelka.KodTovarа WHERE Tovar.Nazvanie NOT IN
(SELECT Tovar.Nazvanie FROM Tovar INNER JOIN
(Klient INNER JOIN Sdelka
ON Klient.KodKlientа=Sdelka.KodKlientа)
ON Tovar. KodTovarа=Sdelka.KodTovarа WHERE.GorodKlientа='Москва')

Соответствие шаблону

С помощью оператора можно выполнять сравнение выражения с


заданным шаблоном, в котором допускается использование символов –
заменителей:
 Символ % – вместо этого символа может быть
подставлено любое Kolichestvo произвольных символов.
 Символ __ заменяет один символ строки.
 [] – вместо символа строки будет подставлен один из возможных
символов, указанный в этих ограничителях.
 [^] – вместо соответствующего символа строки будут
подставлены все символы, кроме указанных в ограничителях.
Like применяется только с символьными выражениями. Просматривает
символьное поле и выявляет совпадает ли значение поля с выражением в
операторе Like.
Like <выражение>

Пример 21. Показать фамилии студентов начинающихся с


буквы А SELECT * FROM Student WHERE Fam LIKE "A%"

Пример 22. Найти клиентов, у которых в номере телефона вторая цифра


– 4.
SELECT Klient.Familiya, Klient.Telefon
FROM Klient
WHERE Klient.Telefon Like"_4%"

Пример 23. Найти клинтов, у которых в номере телефона вторая цифра


– 2 или 4.

SELiiCT Klient.Familiya, Klient.Telefon


FROM Klient
WHERE Klient.Telefon Like "_[24]%"

Пример 24. Найти клиентов, у которых в номере телефона вторая цифра


2, 3 или 4.

SELECT Klient.Familiya, Klient.Telefon


FROM Klient.
WHERE Klient.Telefon Like "[2 – 4]%"

Пример 25. Найти клинтов, у которых в фамилии встречается слог "ро".

SELECT Klient.Familiya
FP ОМ Klient.
WHERE Klient.Familiya Like "%ро%"

Значение NULL

Оператор IS NULL используется для сравнения текущего значения со


значением NULL – специальным значением, указывающим на отсутствие
любого значения. NULL – это не то же самое, что знак пробела (пробел –
допустимый символ) или ноль (0 – допустимое число). NULL отличается и от
строки нулевой длины (пустой строки).

Пример 26. Найти сотрудников, у которых нет телефона (поле Телефон


не содержит никакого значения).

SELECT Familiya, Telefon


FROM Klient
WHERE Telefon Is Null

Пример 27. Выборка сотрудников, у которых есть телефон (поле


Телефон, содержит какое – либо значение).

SELECT Klient.Familiya, Klient.Telefon


FROM Klient.
WHERE Klient.Telefon Is Not ull
1.6.3. Предложение ORDER BY

В общем случае строки в результирующей таблице SQL – запроса никак


не упорядочены. Однако их можно требуемым образом отсортировать, для
чего в оператор SELECT помещается фраза ORDER BY, которая сортирует
данные выходного набора в заданной последовательности. Сортировка
может выполняться по нескольким полям, в этом случае они перечисляются
за ключевым словом ORDER BY через запятую. Способ сортировки задается
ключевым словом, указываемым в рамках параметра ORDER BY следом за
названием поля, по которому выполняется сортировка. По умолчанию
реализуется сортировка по возрастанию. Явно ога задается ключевым словом
ASC. Для выполнения сортировки в обратной последовательности необходимо
после имени поля, по которому она выполняется, указать ключевое слово
DESC. Фраза ORDER BY позволяет упорядочить выбранные записи в порядке
возрастания или убывания значений любого столбца или комбинации
столбцов, независимо от того, присутствуют эти столбцы в таблице
результата или нет. Фраза ORDER BY всегда должна быть последним
элементом в операторе SELECT.

Пример 28. Вывести список клиентов в алфавитном порядке.

SELECT Klient.Familiya, Klient.Telefon


FROM Klient
ORDER BY Klient.Familiya,

Пример 29. Показать записи из таблицы предметы в алфавитном


порядке наименование предметов.

SELECT * FROM Subject ORDER BY Name;

Пример 30. Показать в убывающем порядке количество часов

SELECT * FROM Subject ORDER BY Hours DESC;

Пример 31. Упорядочить по 2-м полям.

SELECT * FROM Subject ORDER BY Sem, Name;

Во фразе ORDER BY может быть указано и больше одного элемента.


Главный (первый) ключ сортировки определяет общую упорядоченность строк
результирующей таблицы. Если во всех строках результирующей таблицы
значения главного ключа сортировки являются уникальными, нет
необходимости использовать дополнительные ключи сортировки. Однако,
если значения главного ключа не уникальны, в результирующей таблице будет
присутствовать несколько строк с одним и тем же значением старшего ключа
сортировки. В этом случае, возможно, придется упорядочить строки с
одним и тем же значением главного ключа по какому – либо
дополнительному ключу сортировки.

Пример 32. Вывести список фирм и клиентов. Названия фирм


упорядочить в алфавитном порядке, имена клиентов в каждой фирме
отсортировать в обратном порядке.

SELECT Klient.Firma, Klient.Familiya


FROM Klient
ORDER BY Klient.Firma, Klient.Familiya DESC

1.7. Вычисления и подведение итогов в запросах:

Описывается использование арифметических операторов и построение


вычисляемых столбцов. Рассматриваются итоговые (агрегатные) функции
COUNT, SUM, AVG, MAX, MIN. Дается пример использования оператора
GROUP BY для группировки в запросах выборки данных. Описывается
применение предложения HAVING.

1.7.1. Построение вычисляемых полей

В общем случае для создания вычисляемого (производного) поля в списке


SELECT следует указать некоторое выражение языка SQL. В этих выражениях
применяются арифметические операции сложения, вычитания, умножения и
деления, а также встроенные функции языка SQL. Можно указать имя любого
столбца (поля) таблицы или запроса, но использовать имя столбца только той
таблицы или запроса, которые указаны в списке предложения FROM
соответствующей инструкции. При построении сложных выражений могут
понадобиться скобки.
Стандарты SQL позволяют явным образом задавать имена столбцов
результирующей таблицы, для чего применяется фраза AS.

Пример 33. Рассчитать общую стоимость для каждой сделки. Этот запрос
использует расчет результирующих столбцов на основе арифметических
выражений.

SELECT Tovar Nazvonie, Tovar Cena,


Sdelka.Kolichestvo,
Tovar Cena*Sdelka Kolichestvo AS Stoimosti
FROM Tovar INNER JOIN Sdelka
ON Tovar.KodTovar=Sdelka.Kod.Tovar

Пример 34. Получить список фирм с указанием фамилии и инициалов


клиентов.
SELECT Firma.Familiya+"."+
Left(ИМЯ,l)+ "."+Left(OTЧЕСTBO,l)+"."AS ФИО
FROM Klient

В запросе использована встроенная функция Left, позволяющая вырезать в


текстовой переменной один символ слева в данном случае.

Пример 35. Получить список товаров с указанием года и месяца


продажи.

SELECT Tovar.Nazvanie, Уеаг(Sdelka.Data)


AS Уеаг.Month(Sdelka.Data)
AS Mesyac
FROM Tovar INNER JOIN Sdelka
ON Tovar.KodTovar=Sdelka.Kod.Tovar

Пример 36. Определить товары, которые покупают клиенты из Москвы.

SELECT DISTINCT Tovar.Nazvanie, Klient. Gorod.Klientа


FROM Tovar INNER JOIN
(Klient INNER JOIN Sdelka ON Klient.KodKlientа=Sdelka.KodKlientа) ON
Tovar.KodTovarа=Sdelka.KodTovarа
WHERE Klient.GorodKlientа – “Москва”

Пример 37. Определить фирмы, покупающие товары местного


производства.

SELECT DISTINCT Klient.Firma, Klient.GorodKlientа,Tovar. Gorod Tovarа


FROM Tovar INNER JOIN
(Klient INNER JOIN Sdelka
ON Klient.KodKlientа.Sdelka.KodKlientа)
ON Tovar.К.одTovarа=Sdelka.KodTovarа
WHERE Klient.GorodKlientа=Tovar.GorodTovarа

Пример 38. Определить среднюю цену проданного товара.

SELECT Аvg(Tovar.Cena) AS Avg_Cena


FROM Tovar INNER JOIN Sdelka
ON Tovar. Kod Tovara=Sdelka Kod Tovara

Пример 39. Подсчитать общую стоимость проданных товара.

SELECT Sum(Tovar.Cena*Sdelka Kolichestvo)


AS Stoimosti
FRCM Tovar INNER JOIN Sdelka ON
Tovar. Kod Tovara.Sdelka Kod Tovara

В запросе использованы встроенные функции Year и Month для выделения


года и месяца из даты.
1.7.2. Использование итоговых функций

С помощью итоговых (агрегатных) функций в рамках SQL – запроса


можно получить ряд обобщающих статистических сведений о множестве
отобранных значений выходного набора.
Пользователю доступны следующие основные итоговые функции:
 Count (Выражение) – определяет количество записей в выходном
наборе SQL-запроса;
 Min/Max (Выражение) – определяют наименьшее и наибольшее из
множества значение в некотором поле запроса;
 Avg (Выражение) – эта функция позволяет рассчитать среднее
значение множества значений, хранящихся в определенном поле отобранных
запросом записей.
Оно является арифметическим средним значением, т.е. суммой значений,
деленной на их количество.
 Sum (Выражение) – вычисляет сумму множества значений,
содержащихся в определенном поле отобранных запросом записей.
Чаще всего в качестве выражения выступают имена столбцов. Выражение
может вычисляться и по значениям нескольких таблиц.
Все эти функции оперируют со значениями в единственном столбце
таблицы или с арифметическим выражением и возвращают единственное
значение. Функции COUNT, MIN и МАХ применимы как к числовым, так и к
нечисловым полям, тогда как функции SUM и AVG могут использоваться
только в случае числовых полей, за исключением COUNTY*. При
вычислении результатов любых функций сначала исключаются все пустые
значения, после чего требуемая операция применяется только к оставшимся
конкретным значениям столбца. Вариант COUNT(*) – особый случай
использования функции COUNT, его назначение состоит в подсчете всех
строк в результирующей таблице, независимо от того, содержатся там
пустые, дублирующиеся или любые другие значения.
Если до применения обобщающей функции необходимо исключить
дублирующиеся значения, следует перед именем столбца в определении
функции поместить ключевое слово DISTINCT. Оно не имеет смысла для
функций MIN и МАХ, однако его использование может повлиять на
результаты выполнения функций SUM и AVG, поэтому необходимо заранее
обдумать, должно ли оно присутствовать в каждом конкретном случае. Кроме
того, ключевое слово DISTINCT может быть указано в любом запросе не более
одного раза.
Очень важно отметить, что итоговые функции могут использоваться
только в списке предложения SELECT и в составе предложения HAVING. Во
всех других случаях это недопустимо. Если список в предложении SELECT
содержит итоговые функции, а в тексте запроса отсутствует фраза GROUP
BY, обеспечивающая объединение данных в группы, то ни один из элементов
списка предложения SELECT не может включать каких – либо ссылок на
поля, за исключением ситуации, когда поля выступают в качестве аргументов
итоговых функций.

Пример 40. Определить количество сделок.

SELECT Count(*) AS Kolichestvo sdelok


FROM Sdelka

Пример 41. Определить суммарное количество проданного товара.

SELECT Sum(Sdelka. Kolichestvo)


AS Kolichestvo Tovara
FROM Sdelka

1.8. Преобразование вывода из встроенной функции

Операторы преобразования применяются с выражениями:


Арифметические (+;– ; /; *) применяются только с числовыми полями.

Пример 42. Получить фамилии у которых стипендия увеличена на


100

SELECT Fam, Stip + 100


FROM Student

Строковые:
<выражение 1> || <выражение 2> позволяет соединить 2 и более
символьных выражений. Применяется только с символьными полями А.
Показать фамилии и имя студентов 4 – ого курса

SELECT Fam, || « «, || Imy


FROM Student
WHERE Curs = 4

1.9. Предложение GROUP BY

Часто в запросах требуется формировать промежуточные итоги, что


обычно отображается появлением в запросе фразы «для каждого...». Для этой
цели в операторе SELECT используется предложение GROUP BY. Запрос, в
котором присутствует GROUP BY, называется группирующим запросом,
поскольку в нем группируются данные, полученные в результате выполнения
операции SELECT, после чего для каждой отдельной группы создается
единственная суммарная строка. Стандарт SQL требует, чтобы предложение
SELECT и фраза GROUP BY были тесно связаны между собой. При наличии
в операторе SELECT фразы GROUP BY каждый элемент списка в
предложении SELECT должен иметь единственное значение для всей группы.
Более того, предложение SELECT может включать только следующие типы
элементов: имена полей, итоговые функции, константы и выражения,
включающие комбинации перечисленных выше элементов.
Все имена полей, приведенные в списке предложения SELECT, должны
присутствовать и во фразе GROUP BY – за исключением случаев, когда имя
столбца используется в итоговой функции. Обратное правило не является
справедливым – во фразе GROUP BY могут быть имена столбцов,
отсутствующие в списке предложения SELECT.
Если совместно с GROUP BY используется предложение WHERE, то оно
обрабатывается первым, а группированию подвергаются только те строки,
которые удовлетворяют условию поиска.
Стандартом SQL определено, что при проведении группирования все
отсутствующие значения рассматриваются как равные. Если две строки
таблицы в одном и том же группируемом столбце содержат значение NULL и
идентичные значения во всех остальных непустых группируемых столбцах,
они помещаются в одну и ту же группу.

Пример 43. Вычислить средний объем покупок, совершенных каждым


покупателем.

SELECT Klient.Familiya, Аvg(Sdelka. Kolichestvo)


AS Srednee Kolichestvo
FROM Klient INNER JOIN Sdelka
ON Klient.KodKlienta= Sdelka.KodKlienta
GROUP BY Klient.Familiya

Пример 44. Определить, на какую сумму был продан товар каждого


наименования.

SELECT Tovar.Nazvanie,
Sum(Tovar.Cena*Sdelka. Kolichestvo)
AS Stoimosti
FROM Tovar INNER JOIN Sdelka
ON Tovar.KodTovara=Sdelka.KodTovara
GROUP BY Tovar.Nazvanie

Пример 45. Подсчитать количество сделок, осуществленных каждой


фирмой.

SELECT Klient.Firma, Count;(Sdlka.KodSdelki)


AS Kolichestvo Sdelok
FROM Klient INNER JOIN Sdelka
ON Klient.KodKlienta= Sdelka.KodKlienta
GROUP BY Klient.Firma

Пример 46. Подсчитать общее количество купленного для каждой


фирмы товара и его стоимость.

SELECT Klient.Firma, Sum(Sdelka. Kolichestvo)


AS Obshee Kolichestvo,
Sum(Tovar Cena*Sdelka. Kolichestvo)
AS Stoimosti FROM Tovar INNER JOIN
(Klient INNER JOIN Sdelka
ON Klient.KodKlientа=Sdelka.KodKlientа)
ON Tovar.KodTovarа=Sdelka.KodTovarа GROUP BY Klient.Firma

Пример 47.Сколько студентов на каждом курсе

SELECT Count (*) FROM Student


GROUP BY Kurs;

Пример 48.Сколько студентов проживают в Москве

SELECT Count (*) FROM Student


WHERE City = "Москва"
GROUP BY City;

Пример 49. Определить суммарную стоимость каждого товара за


каждый месяц.

SELECT Tovar.Nazvanie, Month(Sdelka.Data)


AS Mesyac,
Sum(Tovar.Cena*Sdelka.Kolichestvo)
AS Stoimosti FROM Tovar INNER JOIN Sdelka
ON Tovar.KodTovarа=Sdelka.KodTovarа
GROUP BY Tovar.Nazvanie, Month(Sdelka.Data)

Пример 50. Определить суммарную стоимость каждого товара первого


сорта за каждый месяц.

SELECT Tovar.Nazvanie, Month(Sdelka.Data)


AS Mesyac, Sum(Tovar.Cena*Sdelka. Kolichestvo)
AS Stoimosti
FROM Tovar INNER JOIN Sdelka
ON Tovar.KodTovarа=Sdelka.KodTovarа
WHERE Tovar.Sort="Первый"
GROUP BY Tovar.Nazvanie, Month(Sdelka.Data)
2.1. Предложение HAVING

При помощи HAVING отражаются все предварительно сгруппированные


посредством GROUP BY блоки данных, удовлетворяющие заданным в
HAVING условиям. Это дополнительная возможность «профильтровать»
выходной набор.
Условия в HAVING отличаются от условий в WHERE:
 HAVING исключает из результирующего набора данных
группы с результатами агрегированных значений;
 WHERE исключает из расчета агрегатных значений по
группировке записи, не удовлетворяющие условию;
 в условии поиска WHERE нельзя задавать агрегатные функции.

Пример 51. Определить фирмы, у которых общее количество сделок


превысило три.

SELECT Klient.Firma, Соunt(Sdelka. Kolichestvo)


AS Kolichestvo Sdelok
FROM Klient INNER JOIN Sdelka
ON Klient.KodKlientа=Sdelka.KodKlientа
GROUP BY Klient.Firma
HAVING Count(Sdelka. Kolichestvo)>3

Пример 52. Вывести список товаров, проданных на сумму более 10000


руб.

SELECT Tovar.Nazvanie,
Sum(Tovar.Cena*Sdelka. Kolichestvo)
AS Stoimosti
FROM Tovar INNER JOIN Sdelka
ON Tovar.KodTovarа=Sdelka.KodTovarа
GRCUP BY Tovar.Nazvanie
HAVING Sum(Tovar.Cena*Sdelka. Kolichestvo)>10000

Пример 53.Вывести список товаров, проданных на сумму более 10000 без


указания суммы.

SELECT Tovar.Nazvanie
FROM Tovar INNER JOIN Sdelka
ON Tovar.KodTovarа=Sdelka.KodTovarа
GROUP BY Tovar.Nazvanie
HAVING Sum(Tovar.Cena*Sdelka. Kolichestvo)>10000

Пример 54. Отобразить предметы, у которых > 70 часов (отбор


произвести в каждой групп предметов)
SELECT Name, MAX(hours)
FROM Subject
GROUP BY Name
HAVING MAX (Hours)>70

2.2. Построение нетривиальных запросов

Дается определение подзапроса. Приводятся примеры формирования


вложенных подзапросов. Показывается способ построения подзапросов,
возвращающих множественные и единичные значения с использованием
операторов EXISTS, ALL, ANY.
2.2.1. Понятие подзапроса

Часто невозможно решить поставленную задачу путем одного запроса.


Это особенно актуально, когда при использовании условия поиска в
предложении WHERE значение, с которым надо сравнивать, заранее не
определено и должно быть вычислено в момент выполнения оператора
SELECT. В таком случае приходят на помощь законченные операторы
SELECT, внедренные в тело другого оператора SELECT. Внутренний
подзапрос представляет собой также оператор SELECT, а кодирование его
предложений подчиняется тем же правилам, что и основного оператора
SELECT. Внешний оператор SELECT использует результат выполнения
внутреннего оператора для определения содержания окончательного результата
всей операции. Внутренние запросы могут быть помещены непосредственно
после оператора сравнения (=, <, >, <=, >=, <>) в предложения WHERE и
HAVING внешнего оператора SELECT – они получают название
подзапросов или вложенных запросов. Кроме того, внутренние операторы
SELECT могут применяться в операторах INSERT, UPDATE и DELETE.
Подзапрос – это инструмент создания временной таблицы, содержимое
которой извлекается и обрабатывается внешним оператором. Текст подзапроса
должен быть заключен в скобки. К подзапросам применяются следующие
правила и ограничения:
 фраза ORDER BY не используется, хотя и может присутствовать во
внешнем подзапросе',
 список в предложении SELECT состоит из имен отдельных столбцов
или составленных из них выражений – за исключением случая, когда в
подзапросе присутствует ключевое слово EXISTS;
 по умолчанию имена столбцов в подзапросе относятся к таблице,
имя которой указано в предложении FROM. Однако допускается ссылка и
на столбцы таблицы, указанной во фразе FROM внешнего запроса, для чего
применяются квалифицированные имена столбцов (т.е. с указанием таблицы);
 если подзапрос является одним из двух операндов, участвующих в
операции сравнения, то запрос должен указываться в правой части этой
операции.
Существует два типа подзапросов:
 Скалярный подзапрос возвращает единственное значение. В
принципе, он может использоваться везде, где требуется указать единственное
значение.
 Табличный подзапрос возвращает множество значений, т.е.
значения одного или нескольких столбцов таблицы, размещенные в более
чем одной строке. Он возможен везде, где допускается наличие таблицы.

2.2.2. Использование подзапросов, возвращающих единичное значение

Пример 55. Определить дату продажи максимальной партии товара.

SELECT Data, Kolichestvo


FROM Sdelka
WHERE Kolichestvo=(SELЕСТ Мах (Kolichestvo) FROM Sdelka)

Во вложенном подзапросе определяется максимальное количество


товара. Во внешнем подзапросе – Data, для которой количество товара
оказалось равным максимальному. Необходимо отметить, что нельзя прямо
использовать предложение WHERE
Kolichestvo=Мах(Kolichestvo), поскольку применять обобщающие
функции в предложениях WHERE запрещено. Для достижения желаемого
результата следует создать подзапрос, вычисляющий максимальное
значение количества, а затем использовать его во внешнем операторе
SELECT, предназначенном ДЛЯ выборки дат сделок, где количество товара
совпало с максимальным значением.

Пример 56. Определить даты сделок, превысивших по количеству


товара среднее значение и указать для этих сделок превышение над средним
уровнем.

SELECT Data, Kolichestvo,


Kolichestvo – (SELЕСТ Аvg(Kolichestvo)
FROM Sdelka) AS Prewishenie
FROM Sdelka
WHERE Kolichestvo >
(SELECT Avg(Kolichestvo)
FROM Sdelka)

В приведенном примере результат подзапроса, представляющий собой


среднее значение количества товара по всем сделкам вообще, используется во
внешнем операторе SELECT как для вычисления отклонения количества от
среднего уровня, так и для отбора сведений о Dataх
Пример 57. Определить клиентов, совершивших сделки с максимальным
количеством товара.

SELECT Klient.Familiya
FROM Klient INNER JOIN Sdelka
ON Klient.KodKlientа=Sdelka.KodKlientа
WHERE Sdelka. Kolichestvo ^
(SELECT Мах(Sdelka. Kolichestvo)
FROM Sdelka)

Здесь показан пример использования подзапроса при выборке данных из


разных таблиц.

Пример 58. Определить клиентов, в сделках которых количество


товара отличается от максимального не более чем на 10%.

SELECT Klient.Familiya,
Sdelka.Kolichestvo
FROM Klient
INNER JOIN Sdelka
ON Klient.KodKlientа=Sdelka. Kod Klientа
WHERE Sdelka.Kolichestvo >=0.9*
(SELECT Мах(Sdelka.Kolichestvo)
FROM Sdelka)

Пример 59. Определить фирмы, которые покупают только товары,


произведенные в своем городе, и никакие другие.

SELECT DISTINCT Klient.Firma,


Klient.GorodKlientа,
Tovar. Gorod То вара FROM Tovar INNER JOIN
(Klient INNER JOIN Sdelka
ON Klient.KodК лиента=Sdelka.KodKlientа)
ON Tovar.KodTovarа=Sdelka.KodTovarа
WHERE Klient.GorodKlientа NOT IN
(SELECT DISTINCT Klient.GorodKlientа
FROM Tovar INNER JOIN
(Klient INNER JOIN Sdelka
ON Klient.KodKlientа=Sdelka.KodKlientа)
ON Tovar.KodTovarа=Sdelka.KodTovarа
WHERE Klient.GorodKlientао
Tovar. Gorod Tovarа)

Покажем, как применяются подзапросы в предложении HAVING.

Пример 60. Определить даты, когда среднее кол – во проданного за


день товара оказалось больше 20 единиц.
SELECT Sdelka.Data, АvgSdelka. Kolichestvo) AS
Srednee za den
FROM Sdelka
GROUP BY Sdelka.Data
HAVING Аvg(Sdelka. Kolichestvo)>20

За каждый день определяется среднее кол – во товара, которое сравнивается


с числом 20. Добавим в запрос подзапрос.

Пример 61. Определить даты, когда среднее кол – во проданного за


день товара оказалось больше среднего показателя по всем сделкам вообще.

SELECT Sdelka.Data, Аvg(Sdelka. Kolichestvo)


AS Srednee za den
FROM Sdelka
GROUP BY Sdelka.Data
HAVING Аvg(Sdelka. Kolichestvo)>(SELECT А\^(Sdelka. Kolichestvo)
FROM Sdelka)

Внутренний подзапрос определяет средний по всем сделкам показатель, с


которым во внешнем запросе сравнивается среднее за каждый день количество
товара.

2.2.3. Использование подзапросов, возвращающих множество значений

Во многих случаях значение, подлежащее сравнению в предложениях


WHERE или HAVING, представляет собой не одно, а несколько значений.
Вложенные подзапросы генерируют непоименованное промежуточное
отношение, временную таблицу. Оно может использоваться только в том
месте, где появляется в подзапросе. К такому отношению невозможно
обратиться по имени из какого – либо другого места запроса. Применяемые к
подзапросу операции основаны на тех операциях, которые, в свою очередь,
применяются к множеству, а именно:
 { WHERE | HAVING } выражение [ NOT ] IN (подзапрос);
 { WHERE | HAVING } выражение оператор сравнения { ALL | SOME |
ANY } (подзапрос);
 (WHERE | HAVING } [ NOT ] EXISTS (подзапрос);

2.3. Запросы модификации данных

Рассматриваются запросы модификации данных в реляционной таблице:


вставка отдельной записи INSERTS VALUESs или группы записей из
имеющейся таблицы INSERTS SELECTS, удаление записей по условию
DELETE, изменение записей по условию UPDATE. Вводится понятие
целостности данных. Определяются целостность сущностей и ссылочная
целостность.
Язык SQL ориентирован на выполнение операций над группами
записей, хотя в некоторых случаях их можно проводить и над отдельной
записью.
Запросы действия представляют собой достаточно мощное средство,
так как позволяют оперировать не только отдельными строками, но и набором
строк. С помощью запросов действия пользователь может добавить, удалить
или обновить блоки данных. Существует три вида запросов действия:
INSERT INTO – запрос добавления',
DELETE – запрос удаления',
UPDATE – запрос обновления.

2.3.1. Запрос добавления

Оператор INSERT применяется для добавления записей в таблицу.


Формат оператора:

<оператор__вставки>::=INSERT INTO <имя_таблицы> [(имя_столбца [,...п])]


{ALUES (значение[,...п])| <SELECT оператор>}

Здесь параметр имя таблицы представляет собой либо имя таблицы базы
данных, либо имя обновляемого представления.
Первая форма оператора INSERT с параметром VALUES предназначена для
вставки единственной строки в указанную таблицу. Список столбцов указывает
столбцы, которым будут присвоены значения в добавляемых записях. Список
может быть опущен, тогда подразумеваются все столбцы таблицы (кроме
объявленных как счетчик), причем в определенном порядке, установленном
при создании таблицы. Если в операторе INSERT указывается конкретный
список имен полей, то любые пропущенные в нем столбцы должны быть
объявлены при создании таблицы как допускающие значение NULL, за
исключением тех случаев, когда при описании столбца использовался
параметр DEFAULT. Список значений должен следующим образом
соответствовать списку столбцов:
 Количество элементов в обоих списках должно быть одинаковым;
 должно существовать прямое соответствие между позицией одного
и того же элемента в обоих списках, поэтому первый элемент списка
значений должен относиться к первому столбцу в списке столбцов, второй –
ко второму столбцу и т.д.
 типы данных элементов в списке значений должны быть
совместимы с типами данных соответствующих столбцов таблицы.

Пример 62. Добавить в таблицу TOVAR новую запись.

INSERT INFO Tovar (Nazvanie, Tip, Cena)


VALUES(«Славянский» , «шоколад», 12)

Если столбцы таблицы TOVAR указаны в полном составе и в том порядке, в


котором они перечислены при создании таблицы TOVAR, оператор можно
упростить.
INSERT INTO Tovar VALUES («Славянский» , «шоколад», 12)

Вторая форма оператора INSERT с параметром SELECT позволяет


скопировать множество строк из одной таблицы в другую. Предложение
SELECT может представлять собой любой допустимый оператор SELECT.
Вставляемые в указанную таблицу строки в точности должны соответствовать
строкам результирующей таблицы, созданной при выполнении вложенного
запроса. Все ограничения, указанные выше для первой формы оператора
SELECT, применимы и в этом случае.
Поскольку оператор SELECT в общем случае возвращает множество
записей, то оператор INSERT в та! ой форме приводит к добавлению в таблицу
аналогичного числа новых записей.

Пример 63. Добавить в итоговую таблицу сведения об общей сумме


ежемесячных продаж каждого наименования товара

INSERT INTO
(Nazvanie, Mesyac, Stoimosti)
SELECT Tovar.Nazvanie, Моnth(Sdelka.Data)
AS Mesyac, Sum(Tovar.Cena*Sdelka.Kolichestvo)
AS Stoimosti
FROM Tovar
INNER JOIN Sdelka
ON Tovar.KodTovarа= Sdelka. Kod Tovarа
GROUP BY Tovar.Nazvanie, Month(Sdelka.Data)
2.3.2. Запрос удаления

Оператор DELETE предназначен для удаления группы записей из таблицы.


Формат оператора:

<оператор_удаления> : :=DELETE
FROM <имя таблицы>[WHERE <yсловие_отбора>]

Здесь параметр имя таблицы представляет собой либо имя таблицы базы
данных, либо имя обновляемого представления.
Если предложение WHERE присутствует, удаляются записи из таблицы,
удовлетворяющие условию отбора. Если опустить предложение WHERE, из
таблицы будут удалены все записи, однако сама таблица сохранится.

Пример 64. Удалить все прошлогодние сделки.


DELETE
FROM Sdelka
WHERE Уеаг(Sdelka.Data) – Year(GETDATE()) – 1

В приведенном примере условие отбора формируется с учетом года


(функция Year) от текущей даты (функция GETDATEQ).

2.3.3. Запрос обновления

Оператор UPDATE применяется для изменения значений в группе


записей или в одной записи указанной таблицы.
Формат оператора:

<оператор изменения> : :=
UPDATE имя_таблицы SET имя_столбца=
<выражение>[,...п]
[WHERE <условие отбора>]

Параметр имя таблицы – это либо имя таблицы базы данных, либо
имя обновляемого представления. В предложении SET указываются имена
одного и более столбцов, данные в которых необходимо изменить.
Предложение WHERE является необязательным. Если оно опущено,
значения указанных столбцов будут изменены во всех строках таблицы.
Если предложение WHERE присутствует, то обновлены будут только те
строки, которые удовлетворяют условию отбора. Выражение
представляет собой новое значение соответствующего столбца и должно
быть совместимо с ним по типу данных.

Пример 65. Для товаров первого сорта установить цену в значение 140 и
остаток – в значение 20 единиц.

UPDATE Tovar SET Tovar.Cena – 140, Tovar.Octatoc=20


WHERE Tovar.Sort – " Perviy "

Пример 66. Увеличить цену товаров первого сорта на 25%.

UPDATE Tovar SET Tovar.Cena=Tovar.Cena* 1.25


WHERE Tovar.Sort – " Первый "

Пример 67. В сделке с максимальным кол – вом товара увеличить число


товаров на 10%.

UPDATE Sdelka
SET Sdelka. Kolichestvo =Sdelka. Kolichestvo * 1.1
WHERE Sdelka. Kolichestvo ^
(SELECT Мах(Sdelka.Kolichestvo)
FROM Sdelka)

2.4. Понятие «целостность данных»

Выполнение операторов модификации данных в таблицах базы данных


INSERT, DELETi и UPDATE может привести к нарушению целостности
данных и их корректности, т.е. к потере чх достоверности и
непротиворечивости.
Чтобы информация, хранящаяся в базе данных, была однозначной и
непротиворечивой, в реляционной модели устанавливаются некоторые
ограничительные условия – правила, определяющие возможные значения
данных и обеспечивающие логическую основу для поддержания корректных
значений. Ограничения целостности позволяют свести к минимуму ошибки,
возникающие при обновлении и обработке данных.
В базе данных, построенной на реляционной модели, задается ряд
правил целостности, которые, по сути, являются ограничениями для всех
допустимых состояний базы данных и гарантируют корректность данных.
Рассмотрим следующие типы ограничений целостности данных:
 обязательные данные;
 ограничения для доменов полей;
 корпоративные ограничения;
 целостность сущностей;
 ссылочная целостность.
Обязательные данные
Некоторые поля всегда должны содержать одно из допустимых
значений, другими словами, эти поля не могут иметь пустого значения.
Ограничения для доменов полей
Каждое поле имеет свой домен, представляющий собой набор его
допустимых значений. Корпоративные ограничения целостности
Существует понятие «корпоративные ограничения целостности» как
дополнительные правила поддержки целостности данных, определяемые
пользователями, принятые на предприятии или администраторами баз данных.
Ограничения предприятия называются бизнес – правилами.
Целостность сущностей
Это ограничение целостности касается первичных ключей базовых таблиц. По
определению, первичный ключ – минимальный идентификатор (одно
или несколько полей), который используется для уникальной
идентификации записей в таблице. Таким образом, никакое подмножество
первичного ключа не может быть достаточным для уникальной идентификации
записей.
Целостность сущностей определяет, что в базовой таблице ни одно
поле первичного ключа не может содержать отсутствующих значений,
обозначенных NULL.
Если допустить присутствие определителя NULL в любой части
первичного ключа, го равносильно утверждению, что не все его поля
необходимы для уникальной идентификации записей, и противоречит
определению первичного ключа.
Часто связь между таблицами устанавливается по первичному ключу, т.е.
значениям внешнего ключа одной таблицы присваиваются значения первичного
ключа другой. Однако это не является обязательным – в общем случае связь
может устанавливаться и с помощью вторичных ключей. Кроме того, при
установлении связей между таблицами не требуется непременная уникальность
ключа, обеспечивающего установление связи. Поля внешнего ключа не
обязаны иметь те же имена, что и имена ключей, которым они соответствуют.
Внешний ключ может ссылаться на свою собственную таблицу – в таком
случае внешний ключ называется рекурсивным.
Ссылочная целостность определяет: если в таблице существует внешний
ключ, то его значение должно либо соответствовать значению первичного
ключа некоторой записи в базовой таблице, либо задаваться определителем
NULL.
Существует несколько важных моментов, связанных с внешними ключами.
Во – первых, следует проанализировать, допустимо ли использование во
внешних ключах пустых значений. В общем случае, если участие дочерней
таблицы в связи является обязательным, то рекомендуется запрещать
применение пустых значений в соответствующем внешнем ключе. В то же
время, если имеет место частичное участие дочерней таблицы в связи, то
помещение пустых значений в поле внешнего ключа должно быть разрешено.
Например, если в операции фиксации сделок некоторой торговой фирмы
необходимо указать покупателя, то поле код клиента должно иметь атрибут
NOT NULL. Если допускается продажа или покупка товара без указания
клиента, то для поля код клиента можно указать атрибут NULL.
Следующая проблема связана с организацией поддержки ссылочной
целостности при выполнении операций модификации данных в базе. Здесь
возможны следующие ситуации:
1. Вставка новой строки в дочернюю таблицу. Для обеспечения
ссылочной целостности необходимо убедиться, что значение внешнего
ключа новой строки дочерней шаблоны равно пустому значению либо
некоторому конкретному значению, присутствующему в поле первичного
ключа одной из строк родительской таблицы.
2. Удаление строки из дочерней таблицы. Никаких нарушений
ссылочной целостности не происходит.
3. Обновление внешнего ключа в строке дочерней таблицы. Этот случай
подобен описанной выше первой ситуации. Для сохранения ссылочной
целостности необходимо убедиться, что значение внешнего ключа в
обновленной строке дочерней таблицы равно пустому значению либо
некоторому конкретному значению, присутствующему в поле первичного
ключа одной из строк родительской таблицы.
4. Вставка строки в родительскую таблицу. Такая вставка не может
вызвать нарушения ссылочной целостности. Добавленная строка просто
становится родительским объектом, не имеющим дочерних объектов.
5. Удаление строки из родительской таблицы. Ссылочная
целостность окажемся нарушенной, если в дочерней таблице будут
существовать строки, ссылающиеся на удаленную строку родительской
таблицы. В этом случае может использоваться одна из следующих стратегий:
NO ACTION. Удаление строки из родительской таблицы
запрещается, если в дочерней таблице существует хотя бы одна ссылающаяся
на нее строка.
CASCADE. При удалении строки из родительской таблицы
автоматически удаляются все ссылающиеся на нее строки дочерней
таблицы. Если любая из удаляемых строк дочерней таблицы выступает в
качестве родительской стороны в какой – либо другой связи, то операция
удаления применяется ко всем строкам дочерней таблицы этой связи и т.д.
Другими словами, удаление строки родительской таблицы автоматически
распространяется на любые дочерние таблицы.
SET NULL. При удалении строки из родительской таблицы во всех
ссылающихся на нее строках дочернего отношения в поле внешнего ключа,
соответствующего первичному ключу удаленной строки, записывается пустое
значение. Следовательно, удаление строк из родительской таблицы вызовет
занесение пустого значения в соответствующее поле дочерней таблицы. Эта
стратегия может использоваться, только когда в поле внешнего ключа
дочерней таблицы разрешается помещать пустые значения.
SET DEFAULT. При удалении строки из родительской таблицы в поле
внешнего ключа всех ссылающихся на нее строк дочерней таблицы
автоматически помещается значение, указанное для этого поля как значение
по умолчанию. Таким образом, удаление строки из родительской таблицы
вызывает помещение принимаемого по умолчанию значения в поле внешнего
ключа всех строк дочерней таблицы, ссылающихся на удаленную строку. Эта
стратегия применима лишь в тех случаях, когда полю внешнего ключа
дочерней таблицы, назначено некоторое значение, принимаемое по
умолчанию.
NO CHECK. При удалении строки из родительской таблицы никаких
действий по сохранению ссылочной целостности данных не предпринимается.
6. Обновление первичного ключа в строке родительской таблицы. Если
значение первичного ключа некоторой строки родительской таблицы будет
обновлено, нарушение ссылочной целостности случится при том условии,
что в дочернем отношении существуют строки, ссылающиеся на исходное
значение первичного ключа. Для сохранения ссылочной целостности
может применяться любая из описанных выше стратегий. При использовании
стратегии CASCADE обновление значения первичного ключа в строке
родительской таблицы будет отображено в любой строке дочерней
таблицы, ссылающейся на данную строку.
Существует и другой вид целостности – смысловая (семантическая)
целостность базы данных. Требование смысловой целостности определяет,
что данные в базе данных должны изменяться таким образом, чтобы не
нарушалась сложившаяся между ними смысловая связь.
Уровень поддержания целостности данных в разных системах
существенно варьируется.
Идеология архитектуры Klient – сервер требует переноса максимально
возможного числа правил целостности данных на сервер. К преимуществам
такого подхода относятся:
 гарантия целостности базы данных, поскольку все правила
сосредоточены в одном месте (в базе данных);
 автоматическое применение определенных на сервере
ограничений целостности для любых приложений;
 отсутствие различных реализаций ограничений в разных
клиентских приложениях, работающих с базой данных;
 быстрое срабатывание ограничений, поскольку они
реализованы на сервере и, следовательно, нет необходимости посылать
данные клиенту, увеличивая при этом сетевой трафик;
 доступность внесенных в ограничения на сервере изменений
для всех клиентских приложений, работающих с базой данных, и
отсутствие необходимости повторного распространения измененных
приложений клиентов среди пользователей.
К недостаткам хранения ограничений целостности на сервере можно
отнести:
 отсутствие у клиентского приложения возможности реагировать на
некоторые ошибочные ситуации, возникающие на сервере при реализации
тех или иных правил (например, ошибок при выполнении хранимых
процедур на сервере);
 ограниченность возможностей языка SQL и языка хранимых
процедур и триггеров для реализации всех возникающих потребностей
определения целостности данных.
На практике в клиентских приложениях реализуют лишь такие правила,
которые тяжело или невозможно реализовать с применением средств сервера.
Все остальные ограничения целостности данных переносятся на сервер.

2.5. Операции с индексами

Индексы существенно ускоряют процесс поиска и упорядочивания записей


таблицы. Если в операторе Select содержится элемент упорядочивания ORDER
BY, то если перечисляемые поля совпадают с определенными в индексе –
упорядочивание будет использовать этот индекс и произойдет с малыми
затратами времени. В противном случае индекс использоваться не будет и
упорядочивание потребует большего времени. Индекс будет использоваться и
в том случае, если в ORDER BY перечислены не все поля индекса, а какие – то
первые из них. Например, если создан индекс по полям pi, р2, рЗ, то при
выполнении запроса
Select ...ORDER BY pl,p2
индекс будет использоваться, а запрос
Select... ORDER BY pl,p3
будет обрабатываться без использования индекса. Создание нового индекса
осуществляется оператором Create Index:
CREATE INDEX <имя индекса> ON <имя таблицы > <список полей>
Пример 68.

CREATE INDEX Depyear ON Pers Dep, Year_b

Удаление существующего индекса осуществляется оператором Drop Index:


DROP INDEX <имя таблицы >.<имя индекса>

Пример 69.

DROP Index Pers.Depyear

Если таблица многократно изменяется и в нее вносится много новых записей,


индексы могут оказаться, разбалансированы и их эффективность при
выполнении запросов уменьшается. В этом случае полезно проводить
повторное создание и балансировку индекса последовательным применением
операторов деактивации и активации:

ALTER INDEX <имя индекса> DEACTIVATE ALTER


INDEX <имя индекса> ACTIVATE

Перестройка индекса может производиться только в случае, если он в


данный момент не используется в запросах.

2.6. Объединения таблиц

В запросе можно объединить данные двух или более таблиц. Пусть, например,
вы хотите получить список сотрудников всех производственных
подразделений. В таблице Pers мы имеем список сотрудников с указанием в
поле Dep подразделений, в которых они работают. А в таблице Dep мы имеем
список всех подразделений в поле Dep и характеристику каждого
подразделения в поле Proisv («n», если подразделение производственное, и «у»,
если оно относится к управлению). Тогда получить список сотрудников всех
производственных подразделений можно оператором:
SELECT Pers.* FROM Pers, Dep
WHERE (Pers.Dep=Dep.Dep) AND (Dep.Proisv=’n’)

В нем мы обращаемся сразу к двум таблицам Pers и Dep, которые перечислены


после ключевого слова FROM. Поэтому каждое имя поля предваряется
ссылкой на таблицу, к которой оно относится. Впрочем, это надо делать только
для полей, имя которых повторяется в разных таблицах (поле Dep). Перед
полем Proisv ссылку на таблицу можно опустить. В конструкции WHERE
условие Pers.DepHDep.Dep ищет запись в таблице Dep, в которой поле Dep
совпадает с полем Dep текущей записи таблицы Pers. A условие Dep.Proisv=
«n» отбирает те записи, в которых в таблице Dep найденному подразделению
соответствует поле Proisv = «n».

В операторах, работающих с несколькими таблицами, обычно каждой


таблице дается псевдоним, сокращающий ссылки на таблицы, а иногда
придающий им некоторый смысл, вытекающий из данного применения.
Псевдоним таблицы может записываться в списке таблиц после слова FROM,
отделяясь от имени таблицы пробелом. Например, приведенный выше
оператор может быть переписан следующим образом:

SELECT P.* FROM Pers P, Dep D


WHERE (P.Dep – D.Dep) AND (D.Proisv – «n»)

В этом примере таблице Pers дан псевдоним Р, а таблице Dep – D.


Конечно, эти псевдонимы действуют только в данном операторе и не имеют
никакого отношения к псевдонимам баз данных, которые мы постоянно
используем.

Возможно самообъединение таблицы. В этом случае одной таблице


даются два псевдонима. Пусть, например, мы хотим найти всех ровесников в
организации. Это можно сделать оператором

SELECT pl.Fam, p2.Fam, pl.Year_b FROM Pers pi, Pers p2


WHERE (pl.Year_b = p2.Year_b) AND (pl.Fam != p2.Fam)

В этом примере для таблицы Pers мы ввели два псевдонима: pi и р2. В


конструкции WHERE мы ищем в этих якобы разных таблицах записи с
одинаковым годом рождения. Второе условие pl.fam != p2.fam нужно, чтобы
сотрудник не отображался в результатах как ровесник сам себя. Правда,
приведенный оператор выдает в результате по две записи на каждую пару
ровесников, сначала, например, «Николаев – Андреев», а потом «Андреев –
Николаев». Чтобы исключить такое дублирование можно добавить еще одно
условие – pl.Fam < p2.Fam:

SELECT pl.Fam, p2.Fam, pl.Year) FROM Pers pi, Pers p2 WHERE (pl.Year_b =
p2.Year_b) AND (pl.Fam != p2.Fam) and (pi.Fam < p2.Fam)

Дополнительное условие упорядочивает появление фамилий в р 1 и р2 и


исключает дублирование результатов.

До сих пор мы рассматривали объединения, основанные на однозначном


соответствии записей двух таблиц, когда каждой записи в первой таблице
находилась соответствующая ей запись во второй таблице. Возможны и другие
виды объединений, которые выдают записи независимо от того, есть ли
соответствующее поле во второй таблице. Это внешние объединения (outer
join). Их три типа: левое, правое и полное. Левое объединение (обозначается
ключевыми словами LEFT OUTER JOIN ... ON) включает в результат все
записи первой таблицы, даже те, для которых не имеется соответствия во
второй. Правое объединение (обозначается ключевыми словами RIGHT
OUTER JOIN ... ON) включает в результат все записи второй таблицы, даже
если им нет соответствия в записях первой. Полное объединение (обозначается
ключевыми словами FULL OUTER JOIN ... ON) включает в результат
объединение записей обеих таблиц, независимо от их соответствия.

2.6.1. Левое объединение таблиц

Пусть, например, у вас есть таблица сотрудников некоей компании Pers и есть
таблица Chef, в которой занесены данные на членов совета директоров этой
компании. В число членов совета входят и сотрудники компании, и
посторонние лица. Для определенности положим, что в таблице Pers имеются
записи на сотрудников «Иванов» и «Петров», причем Петров является членом
совета, а Иванов – нет. В таблице Chef имеются записи на членов совета
«Петров» и «Сидоров», причем Сидоров – не сотрудник компании.
Тогда оператор

SELECT * FROM Pers LEFT OUTER JOIN Chef


ON Pers.Fam = Chef.Fam

выдаст результат вида:


Поля таблицы Pers Поля таблицы Chef

Иванов ………………….

Петров Петров ……………..

Оператор задал левое объединение таблицы Pers (она указана после


ключевого слова FROM) с таблицей Chef (она указана после ключевых слов
LEFT OUTER JOIN). Условие объединения указано после ключевого слова ON
и заключается в совпадении фамилий.
Как показано, результат включает все поля и таблицы Pers, и таблицы
Chef. Число строк соответствует числу записей таблицы Pers. В строках,
относящихся к записям, для которых в Chef не нашлось соответствие, поля
таблицы Chef остаются пустые.
2.6.2. Правое объединение таблиц

Оператор правого объединения

SELECT * FROM Pers RIGHT OUTER JOIN Chef


ON Pers.Fam = Chef.Fam

выдаст результат вида:

Поля таблицы Pers Поля таблицы Chef


Петров …… Петров ……………..

Сидоров ……………..

Число строк соответствует числу записей таблицы Chef. В строках,


относящихся к записям, для которых в r,;rs не нашлось соответствие, поля
таблицы Pers остаются пустые.

2.6.3. Полное объединение таблиц

Оператор полного объединения

SELECT * FROM Pers FULL OUTER JOIN Chef ON


Pers.Fam = Chef.Fam

выдаст результат вида:

Поля таблицы Pers Поля таблицы Chef

Иванов ………………….

Петров …………………. Петров ……………..

Сидоров ……………..

В нем к строкам, относящимся к таблице Pers, добавлены строки, относящиеся


к таблице Chef, для которых не нашлось соответствия в таблице Pers.