- •Введение
- •Глава 1. Основные понятия баз данных
- •1.1. История возникновения баз данных
- •1.2. Модели данных
- •1.2.1. Иерархическая модель данных
- •1.2.2. Сетевая модель базы данных
- •1.2.3. Реляционная модель базы данных
- •1.2.4. Другие модели баз данных (ООСУБД)
- •2.1. История появления и развития SQL
- •Глава 2. SQL
- •2.2. Стандарты SQL
- •2.2.1. Стандарты ANSI/ISO
- •2.2.2. ODBC и консорциум SQL Access Group
- •2.2.3. JDBC и серверы приложений
- •2.3. SQL и переносимость
- •2.4. SQL и сети
- •2.4.1. Централизованная архитектура
- •2.4.2. Архитектура файлового сервера
- •2.4.3. Архитектура “клиент/сервер”
- •2.4.4. Многоуровневая архитектура
- •2.4.5. SQL и мэйнфреймы
- •2.4.7. SQL и UNIX
- •2.4.8. SQL и персональные компьютеры
- •2.4.9. SQL, хранилища данных и интеллектуальные ресурсы предприятия
- •2.4.10. SQL и интернет-приложения
- •2.5. Основы SQL
- •2.5.1. Использование SQL для извлечения информации из таблиц
- •2.5.2. Команда SELECT
- •2.5.3. Создание более сложных предикатов в предложении SELECT
- •2.5.4. Формирование вывода запросов
- •2.5.5. Агрегатные группы
- •2.6. Запросы к нескольким таблицам
- •2.6.1. Подзапросы
- •2.6.2. Использование операторов ANY, ALL и SOME
- •2.6.3. Использование предложения UNION
- •2.6.4. Ввод, удаление и изменение значения поля
- •2.7. DDL (Язык описания данных)
- •2.7.1. Создание таблиц
- •2.7.2. Индексы
- •2.7.3. Изменение структуры таблицы после ее создания
- •2.8. Ограничение данных
- •2.8.1. Ограничение таблиц
- •2.8.2. Установка значений по умолчанию
- •2.9. Поддержка целостности данных
- •2.9.1. Первичные ключи
- •2.9.2. Пользовательские представления
- •2.10. Модификация данных с помощью представлений
- •2.11. Разграничение доступа в базе данных
- •Глава 3. Математические основы реляционных баз данных
- •3.1. Отношения и их схемы
- •3.2. Реляционные операторы
- •3.2.1. Булевы операции
- •3.2.2. Оператор выбора
- •3.2.3. Оператор проекции
- •3.2.4. Оператор соединения
- •3.2.5. Другие операции на отношениях
- •3.2.6. Оператор деления
- •3.2.7. Оператор переименования атрибутов
- •3.2.8. Оператор эквисоединения
- •3.2.9. Расширения для сравнения на доменах
- •3.2.9.1. Расширение выбора
- •3.3. Реляционная алгебра
- •3.3.1. Дополнительные операторы
- •3.3.1.1. Оператор расщепления
- •3.3.1.2. Оператор FACTOR
- •3.4. Функциональные зависимости
- •3.4.1. Определение
- •3.4.2. Аксиомы вывода
- •3.4.3. Применение аксиом вывода
- •3.4.4. Выводы на основе аксиом вывода
- •3.4.6. Направленные ациклические графы вывода
- •3.4.7. Проверка принадлежности к замыканию множества функциональных зависимостей
- •3.5. Покрытия функциональных зависимостей
- •3.5.1. Покрытия и эквивалентность
- •3.5.2. Неизбыточные покрытия
- •3.5.3. Редуцированные покрытия
- •3.5.3.1. Посторонние атрибуты
- •3.5.3.3. Алгоритм построения редуцированного покрытия
- •3.5.3.4. Канонические покрытия
- •3.5.3.5. Структура неизбыточных покрытий
- •3.5.4. Минимальные покрытия
- •3.5.4.1. Прямая определяемость
- •3.5.4.2. Вычисление минимальных покрытий
- •3.5.4.3. Оптимальные покрытия
- •3.5.5. Составные функциональные зависимости
- •3.5.6. Кольцевые покрытия
- •3.6. Многозначные зависимости и зависимости соединения
- •3.6.1. Многозначные зависимости
- •3.6.2. Многозначные и функциональные зависимости
- •3.6.3. Аксиомы вывода для многозначных зависимостей
- •3.6.4. Только многозначные зависимости
- •3.6.5. Функциональные и многозначные зависимости
- •3.6.6. Зависимости соединения
- •3.7. Синтез схем реляционных баз данных
- •3.7.1. Базы данных и их схемы
- •3.7.2. Нормальные формы баз данных
- •3.7.2.1. Первая нормальная форма
- •3.7.2.2. Вторая нормальная форма
- •3.7.2.4. Нормальная форма Бойса - Кодда (НФБК)
- •3.7.2.5. Четвертая нормальная форма
- •3.7.2.3. Третья нормальная форма
- •3.8. Алгоритмы синтеза схем баз данных
- •3.8.1. Нормализация через декомпозицию
- •3.8.2. Недостатки нормализации через декомпозицию
- •3.8.3. Нормализация посредством синтеза
- •Глава 4. Система управления базами данных PostgreSQL
- •4.1. Установка
- •4.2. Запуск и останов сервера PostgreSQL
- •4.2.1. Утилита psql
- •4.2.2. Создание базы данных
- •4.3. Объекты базы данных
- •4.4. Функции и операторы
- •4.4.1. Логические операторы
- •4.4.2. Операторы сравнения
- •4.5. Клиентские приложения PostgreSQL
- •4.5.1. clusterdb
- •4.5.2. createdb
- •4.5.3. createuser
- •4.5.4. dropdb
- •4.5.5. dropuser
- •4.5.6. ecpg
- •4.5.7. pg_basebackup
- •4.5.8. pgbench
- •4.5.9. pg_config
- •4.5.10. pg_dump
- •4.5.11. pg_dumpall
- •4.5.12. pg_isready
- •4.5.13. pg_receivewal
- •4.5.14. pg_restore
- •4.5.15. psql
- •4.5.16. reindexdb
- •4.5.17. vacuumdb
- •4.6. Серверные приложения PostgreSQL
- •4.6.1. initdb
- •4.6.2. pg_archivecleanup
- •4.6.3. pg_checksums
- •4.6.4. pg_controldata
- •4.6.6. pg_resetwal
- •4.6.7. pg_rewind
- •4.6.8. pg_test_fsync
- •4.6.9. pg_test_timing
- •4.6.10. pg_upgrade
- •4.6.11. pg_waldump
- •4.6.12. postgres
- •4.6.13. postmaster
- •4.7. Серверное программирование
- •4.7.1. Расширение SQL
- •4.7.2. Триггеры
- •Заключение
- •Библиографический список
- 31 -
stgroup |
| max |
| min |
| |
avg |
| count |
|
--------- |
+------ |
+------ |
+ |
-------------------- |
+ |
------ |
345 |
| 4.87 |
| 4.87 | |
4.8700000000000000 | |
1 |
||
349 |
| 4.38 |
| 4.38 | |
4.3800000000000000 | |
1 |
||
342 |
| 5.00 |
| 4.12 |
| |
4.6250000000000000 |
| |
4 |
344 |
| 4.31 |
| 4.31 |
| |
4.3100000000000000 |
| |
1 |
(4 rows) |
|
|
|
|
|
|
Кроме этого, существует еще одна агрегатная функция SUM(), которая может просуммировать числовое значение столбца в каждой группе.
2.6. Запросы к нескольким таблицам
До этого каждый запрос, который мы рассматривали, основывался на одиночной таблице. В этой главе вы узнаете, как сделать запрос для любого числа таблиц с помощью одной команды.
Для этого нам понадобится еще одна таблица stgroups, в которой хранится информация о принадлежности к кафедре студенческой группы и о ее кураторе:
stgroup |
| department |
| curator |
--------- |
+------------ |
+----------- |
340 |
| ЭВМ |
| Логинов |
341 |
| ЭВМ |
| Кузьмин |
342 |
| ЭВМ |
| Гринченко |
344 |
| САПР |
| Бабаев |
345 |
| ВПМ |
| Макаров |
349 |
| АСУ |
| Маркин |
Поскольку в двух таблицах могут быть столбцы с одинаковыми именами, то их следует записывать в точечной нотации: имя_таблицы.имя_столбца. Рассмотрим простой пример объединения двух таблиц по общему столбцу stgroup.
SELECT s.family,s.name,s.stgroup, |
|
||||
g.department, g.curator |
|
|
|||
FROM students s, stgroups g |
|
||||
WHERE s.stgroup = g.stgroup; |
|
||||
family |
| name |stgroup | |
department| curator |
|||
------------ |
+------ |
+-------- |
+----------- |
|
+--------- |
Фахрудинова |
|Тамара| 342 |
| |
ЭВМ |
| Гринченко |
|
Никулкин |
|Сергей| 342 |
| |
ЭВМ |
| Гринченко |
|
Катеринченко|Андрей| 342 |
| |
ЭВМ |
| Гринченко |
||
Балашов |
|Андрей| 342 |
| |
ЭВМ |
| Гринченко |
|
Чертков |
|Максим| 344 |
| |
САПР |
| Бабаев |
|
Малин |
|Сергей| 345 |
| |
ВПМ |
| Макаров |
|
Колычева |
|Лия |
| 349 |
| |
АСУ |
| Маркин |
(7 rows) |
|
|
|
|
|
- 32 -
Здесь следует обратить внимание на то, что во фразе FROM после указания таблицы, из которой будут запрашиваться данные, стоит ее краткое обозначение (псевдоним, алиас), которое используется везде в операторе SELECT вместо полных имен столбцов, что позволяет значительно сократить длину кода оператора.
Возможность объединения таблиц подразумевает использование любых допустимых операторов сравнения.
Таблицу можно объединять саму с собой, и тогда использование псевдонимов будет строго обязательно. В примере мы выберем все пары студентов, которые обучаются в одной группе:
SELECT s.family,g.family,s.stgroup FROM students s,
students g WHERE |
s.stgroup = |
g.stgroup; |
|
family |
| |
family |
| stgroup |
-------------- |
+-------------- |
|
+--------- |
Балашов |
| Фахрудинова |
| 342 |
|
Балашов |
| Никулкин |
| 342 |
|
Балашов |
| Катеринченко |
| 342 |
|
Балашов |
| Балашов |
| 342 |
|
Катеринченко |
| Фахрудинова |
| 342 |
|
Катеринченко |
| Никулкин |
| 342 |
|
Катеринченко |
| Катеринченко |
| 342 |
|
Катеринченко |
| Балашов |
| 342 |
|
Колычева |
| Колычева |
| 349 |
|
Малин |
| Малин |
| 345 |
|
Никулкин |
| Фахрудинова |
| 342 |
|
Никулкин |
| Никулкин |
| 342 |
|
Никулкин |
| Катеринченко |
| 342 |
|
Никулкин |
| Балашов |
| 342 |
|
Фахрудинова |
| Фахрудинова |
| 342 |
|
Фахрудинова |
| Никулкин |
| 342 |
|
Фахрудинова |
| Катеринченко |
| 342 |
|
Фахрудинова |
| Балашов |
| 342 |
|
Чертков |
| Чертков |
| 344 |
|
(19 rows) |
|
|
|
Для демонстрации соединения трех таблиц используем еще одну |
|||
таблицу departments, в которой содержится информация о кафедрах (заведующий кафедрой и факультет, к которому она относится). В результате запроса получим информацию о том, на каком факультете учится каждый из наших студентов.
department |
| faculty |
| head |
------------ |
+--------- |
+---------- |
ЭВМ |
| ФВТ |
| Костров |
САПР |
| ФВТ |
| Корячко |
ВПМ |
| ФВТ |
| Овечкин |
АСУ |
| ФАИТУ |
| Одиноков |
-33 -
Асам запрос по трем таблицам и его результат будут выглядеть следующим образом:
SELECT s.family,d.faculty
FROM students s, stgroups g, departments d WHERE s.stgroup = g.stgroup
AND g.department=d.department;
family |
| faculty |
-------------- |
+--------- |
Фахрудинова |
| ФВТ |
Никулкин |
| ФВТ |
Катеринченко |
| ФВТ |
Балашов |
| ФВТ |
Чертков |
| ФВТ |
Малин |
| ФВТ |
Колычева |
| ФАИТУ |
(7 rows) |
|
2.6.1. Подзапросы
Запросы могут управлять другими запросами, что делается путем помещения запроса внутрь предиката другого запроса. При этом количество уровней подзапросов не ограничено. Подзапрос работает следующим образом: внутренний подзапрос генерирует значение (единственное, иначе сервер вернет ошибку), которое проверяется в предикате внешнего запроса.
В примере мы попытаемся выбрать студентов, которые обучаются на ФВТ и у которых куратор Гринченко.
SELECT * FROM students |
|
|
|
|
|
|
WHERE stgroup = |
|
|
|
|
|
|
(SELECT stgroup FROM stgroups g, |
departments d |
|||||
WHERE g.department=d.department |
|
|
|
|||
AND faculty='ФВТ' AND curator='Гринченко' ); |
||||||
family |
| name |
| |
stgroup | |
gpa |
| sex |
|
-------------- |
+-------- |
+ |
--------- |
+ |
------ |
+----- |
Балашов |
| Андрей | |
342 |
| |
5.00 |
| м |
|
Катеринченко |
| Андрей | |
342 |
| |
4.59 |
| м |
|
Никулкин |
| Сергей | |
342 |
| |
4.79 |
| м |
|
Фахрудинова |
| Тамара | |
342 |
| |
4.12 |
| ж |
|
(4 rows) |
|
|
|
|
|
|
Подзапрос должен выбрать один, и только один столбец, а тип данных этого столбца должен совпадать с тем значением, с которым он будет сравниваться в предикате.
-34 -
Вподзапросах можно использовать агрегатные функции. В следующем примере нас интересуют студенты, у которых средний балл выше среднего:
SELECT * FROM students
WHERE gpa > (SELECT AVG(g ) FROM students);
family |
| name |
| |
stgroup | |
gpa |
| sex |
|
-------------- |
+-------- |
+ |
--------- |
+ |
------ |
+----- |
Балашов |
| Андрей | |
342 |
| |
5.00 |
| м |
|
Катеринченко |
| Андрей | |
342 |
| |
4.59 |
| м |
|
Малин |
| Сергей | |
345 |
| |
4.87 |
| м |
|
Никулкин |
| Сергей | |
342 |
| |
4.79 |
| м |
|
(4 rows) |
|
|
|
|
|
|
Можно использовать подзапросы, которые производят любое число строк, если применяется специальный оператор IN (операторы BETWEEN, LIKE и IS NULL не могут использоваться с подзапросами). IN определяет набор значений, одно из которых должно совпадать с другим термином уравнения предиката, чтобы предикат был верным.
Когда используется IN с подзапросом, SQL просто формирует этот набор из вывода подзапроса. Мы можем, следовательно, использовать IN, чтобы выполнить такой подзапрос, который не будет работать с реляционным оператором, и найти все атрибуты таблицы students для факультета вычислительной техники.
SELECT * FROM |
students WHERE stgroup IN |
|
||||
(SELECT g.stgroup |
|
|
|
|
||
FROM stgroups g, departments d |
|
|||||
WHERE g.department=d.department |
|
|||||
AND d.faculty='ФВТ'); |
|
|
|
|||
family |
| name |
| |
stgroup | |
gpa |
| sex |
|
-------------- |
+-------- |
+ |
--------- |
+ |
------ |
+----- |
Балашов |
| Андрей | |
342 |
| |
5.00 |
| м |
|
Катеринченко |
| Андрей | |
342 |
| |
4.59 |
| м |
|
Малин |
| Сергей | |
345 |
| |
4.87 |
| м |
|
Никулкин |
| Сергей | |
342 |
| |
4.79 |
| м |
|
Фахрудинова |
| Тамара | |
342 |
| |
4.12 |
| ж |
|
Чертков |
| Максим | |
344 |
| |
4.31 |
| м |
|
(6 rows) |
|
|
|
|
|
|
Смысл всех подзапросов, приведенных в этой главе, в том, что все они выбирают одиночный столбец. Это обязательно, поскольку полученный вывод сравнивается с одиночным значением. Подтверждением этому является то, что SELECT * не может использоваться в подзапросе.
