
- •Глава 2 Базовые понятия реляционной модели данных 21
- •Глава 3. Целостность реляционных данных 28
- •Глава 4. Реляционная алгебра 39
- •Глава 6. Нормальные формы отношений 57
- •Глава 7 Нормальные формы более высоких порядков 74
- •Глава 8. Элементы модели «сущность-связь» 83
- •Глава 5. Элементы языка sql 110
- •Ранние подходы к организации бд. Системы, основанные на инвертированных списках, иерархические и сетевые субд. Примеры. Сильные места и недостатки ранних систем
- •Основные особенности систем, основанных на инвертированных списках
- •Структуры данных
- •Манипулирование данными
- •Ограничения целостности
- •Иерархические системы
- •Иерархические структуры данных
- •Манипулирование данными
- •Ограничения целостности
- •Сетевые системы
- •Сетевые структуры данных
- •Манипулирование данными
- •Ограничения целостности
- •Достоинства и недостатки
- •Элементы теории множеств Множества
- •Операции над множествами
- •Декартово произведение множеств
- •Отношение
- •Примеры отношений Бинарные отношения (отношения степени 2)
- •Отношение эквивалентности
- •Отношения порядка
- •Функциональное отношение
- •Еще пример бинарного отношения
- •Транзитивное замыкание отношений
- •Глава 2 Базовые понятия реляционной модели данных Общая характеристика реляционной модели данных
- •Типы данных
- •Простые типы данных
- •Структурированные типы данных
- •Ссылочные типы данных
- •Типы данных, используемые в реляционной модели
- •Отношения, атрибуты, кортежи отношения Определения и примеры
- •Свойства отношений
- •Первая нормальная форма
- •Глава 3. Целостность реляционных данных
- •Null-значения
- •Трехзначная логика (3vl)
- •Потенциальные ключи
- •Целостность сущностей
- •Внешние ключи
- •Целостность внешних ключей
- •Замечания к правилам целостности сущностей и внешних ключей
- •Операции, могущие нарушить ссылочную целостность
- •Для родительского отношения
- •Для дочернего отношения
- •Стратегии поддержания ссылочной целостности
- •Применение стратегий поддержания ссылочной целостности
- •При обновлении кортежа в родительском отношении
- •При удалении кортежа в родительском отношении
- •При вставке кортежа в дочернее отношение
- •При обновлении кортежа в дочернем отношении
- •Глава 4. Реляционная алгебра Обзор реляционной алгебры
- •Замкнутость реляционной алгебры
- •Отношения, совместимые по типу
- •Оператор переименования атрибутов
- •Теоретико-множественные операторы Объединение
- •Пересечение
- •Вычитание
- •Декартово произведение
- •Специальные реляционные операторы Выборка (ограничение, селекция)
- •Проекция
- •Соединение
- •Общая операция соединения
- •Тэта-соединение
- •Экви-соединение
- •Естественное соединение
- •Деление
- •Примеры использования реляционных операторов
- •Невыразимость транзитивного замыкания реляционными операторами
- •Кросс-таблицы
- •Реляционное исчисление
- •Кортежные переменные и правильно построенные формулы
- •Целевые списки и выражения реляционного исчисления
- •Реляционное исчисление доменов
- •Глава 6. Нормальные формы отношений Этапы разработки базы данных
- •Критерии оценки качества логической модели данных
- •Адекватность базы данных предметной области
- •Легкость разработки и сопровождения базы данных
- •Скорость операций обновления данных (вставка, обновление, удаление)
- •Скорость операций выборки данных
- •Основной пример
- •1Нф (Первая Нормальная Форма)
- •Аномалии обновления
- •Аномалии вставки (insert)
- •Аномалии обновления (update)
- •Аномалии удаления (delete)
- •Функциональные зависимости
- •Определение функциональной зависимости
- •Функциональные зависимости отношений и математическое понятие функциональной зависимости
- •2Нф (Вторая Нормальная Форма)
- •Анализ декомпозированных отношений
- •Оставшиеся аномалии вставки (insert)
- •Оставшиеся аномалии обновления (update)
- •Оставшиеся аномалии удаления (delete)
- •3Нф (Третья Нормальная Форма)
- •Алгоритм нормализации (приведение к 3нф)
- •Анализ критериев для нормализованных и ненормализованных моделей данных Сравнение нормализованных и ненормализованных моделей
- •Oltp и olap-системы
- •Корректность процедуры нормализации – декомпозиция без потерь. Теорема Хеза
- •Глава 7 Нормальные формы более высоких порядков
- •Нфбк (Нормальная Форма Бойса-Кодда)
- •4Нф (Четвертая Нормальная Форма)
- •5Нф (Пятая Нормальная Форма)
- •Продолжение алгоритма нормализации (приведение к 5нф)
- •Глава 8. Элементы модели «сущность-связь»
- •Основные понятия er-диаграмм
- •Нормальные формы er-схем
- •Более сложные элементы er-модели
- •Получение реляционной схемы из er-схемы
- •Пример разработки простой er-модели
- •Концептуальные и физические er-модели
- •Внутренняя организация реляционных субд Cтруктуры внешней памяти, методы организации индексов
- •Хранение отношений
- •Индексы
- •Хэширование
- •Журнальная информация
- •Служебная информация
- •Управление транзакциями, сериализация транзакций
- •Транзакции и целостность баз данных
- •Изолированность пользователей
- •Сериализация транзакций
- •Методы сериализации транзакций
- •Синхронизационные захваты
- •Гранулированные синхронизационные захваты
- •Предикатные синхронизационные захваты
- •Тупики, распознавание и разрушение
- •Метод временных меток
- •Журнализация изменений бд
- •Журнализация и буферизация
- •Индивидуальный откат транзакции
- •Восстановление после мягкого сбоя
- •Физическая согласованность базы данных
- •Восстановление после жесткого сбоя
- •Глава 5. Элементы языка sql
- •Предварительные сведения о работе с sql сервером.
- •InterBase сервер
- •Выполнение в ibConsole
- •Р егистрация псевдонима (алиаса).
- •Пользователи.
- •С оздание модельных бд.
- •Сеанс sql
- •Структура учебных баз данных
- •Операторы sql
- •Операторы ddl (Data Definition Language) - операторы определения объектов базы данных
- •Операторы dml (Data Manipulation Language) - операторы манипулирования данными
- •Операторы dql (Data Query Language) – операторы запросов к данным
- •Операторы dcl (Data Control Language) - защиты и управления данными
- •Основные типы данных
- •Строки фиксированной длины
- •Строки переменной длины
- •Числовые значения
- •Десятичные значения
- •Десятичные значения с плавающей точкой
- •Значения даты и времени
- •Буквальные значения
- •Значения null
- •Значения типа boolean
- •Пользовательские типы данных
- •Типы данных InterBase
- •Управление объектами базы данных
- •Что такое объекты базы данных?
- •Что такое схема?
- •Поля и столбцы
- •Оператор create database
- •Синтаксис
- •Примеры
- •Оператор create table
- •Синтаксис
- •Примеры
- •Ключевое слово storage (в InterBase не действует!)
- •Соглашения о присвоении имен
- •Команда alter table
- •Синтаксис
- •Примеры
- •Модификация элементов таблицы
- •Добавление столбцов, требующих обязательного ввода данных
- •Пример:
- •Изменение столбцов
- •Создание таблицы на основе уже существующей
- •Удаление таблиц
- •Условия целостности
- •Ключевые поля
- •Требования уникальности
- •Внешние ключи
- •Атрибут not null
- •Использование условий проверки
- •Удаление условий
- •Определение представлений
- •Оператор create view (InterBase) Описание
- •Синтаксис
- •Примеры
- •Определение привилегий
- •Оператор grant (InterBase) Описание
- •Синтаксис
- •Примеры
- •Вопросы и ответы
- •Практикум
- •Примеры
- •Манипуляция данными
- •Обзор возможностей манипуляции данными
- •Заполнение таблиц новыми данными
- •Ввод данных в таблицу
- •Ввод данных в определенные столбцы таблицы
- •Ввод данных из другой таблицы
- •Ввод значений null
- •Обновление уже имеющихся данных
- •Обновление значений одного столбца
- •Обновление нескольких столбцов в одной или нескольких записях
- •Удаление данных из таблиц
- •Примеры использования операторов манипулирования данными
- •Знакомство с запросами
- •Что такое запрос?
- •Оператор select
- •Синтаксис оператора выборки данных (select)
- •Синтаксис оператора выборки
- •Синтаксис
- •Примеры
- •Ключевое слово select
- •Ключевое слово from
- •Использование условий для отбора данных
- •Сортировка вывода
- •Учет регистра символов
- •Примеры простых запросов
- •Подсчет записей в таблице
- •Получение данных из таблиц других пользователей
- •Псевдонимы столбцов
- •Упражнения
- •Операции в условиях для отбора данных
- •Что такое операции в sql?
- •Операции сравнения
- •Равенство
- •Неравенство
- •«Меньше» и «больше»
- •Примеры комбинирования операций сравнения
- •Логические операции
- •Использование операторов exists, any, all, и some Описание учебной базы данных
- •Операции конъюнкции и дизъюнкции
- •Отрицание условий с помощью операции отрицания
- •Неравенство
- •Деление
- •Комбинирование арифметических операций
- •Вопросы и ответы
- •Подведение итогов по данным запроса
- •Что такое итоговые функции?
- •Функция count
- •Функция sum
- •Функция avg
- •Функция max
- •Функция min
- •Описание
- •Синтаксис
- •Примеры
- •Описание
- •Примеры
- •Описание
- •Синтаксис
- •Примеры
- •Описание
- •Синтаксис
- •Примеры
- •Описание
- •Синтаксис
- •Примеры
- •Сортировка и группирование данных
- •Зачем группировать данные?
- •Ключевое слово group by
- •Группирование выбранных данных
- •Создание групп и использование итоговых функций
- •Представление имен столбцов числами
- •Ключевое слово having
- •Объединение таблиц в запросах
- •Отбор данных из нескольких таблиц
- •Типы связывания
- •Компоненты условия связывания
- •Связывание по равенству
- •Естественное связывание
- •Использование псевдонимов для имен таблиц
- •Связывание по неравенству
- •Внешнее связывание
- •Рекурсивное связывание
- •Связывание по нескольким ключам
- •Вопросы связывания
- •Использование связующей таблицы
- •Декартово произведение
- •Вопросы и ответы
- •Практикум
- •Упражнения
- •Использование подзапросов
- •Что такое подзапрос?
- •Подзапросы в операторе select
- •Подзапросы в операторе insert
- •Подзапросы в операторе update
- •Подзапросы в операторе delete
- •Подзапросы внутри подзапросов
- •Связанные подзапросы
- •Объединение запросов
- •Обычные и составные запросы
- •Зачем использовать составные запросы?
- •Команды построения сложных запросов
- •Команда union
- •Команда union all
- •Команда intersect
- •Команда except
- •Использование order by в составных запросах
- •Использование group by в составных запросах
- •Обеспечение правильности результатов
- •Примеры использования оператора select
- •Отбор данных из одной таблицы
- •Отбор данных из нескольких таблиц
- •Использование имен корреляции (алиасов, псевдонимов)
- •Использование агрегатных функций в запросах
- •Использование агрегатных функций с группировками
- •Использование подзапросов
- •Использование объединения, пересечения и разности
- •Синтаксис соединенных таблиц
- •Синтаксис условных выражений раздела where
- •Порядок выполнения оператора select
- •Стадия 1. Выполнение одиночного оператора select
- •Стадия 2. Выполнение операций union, except, intersect
- •Стадия 3. Упорядочение результата
- •Как на самом деле выполняется оператор select
- •Оператор соединения
- •Оператор пересечения
- •Оператор деления
- •Использование индексов для ускорения поиска данных
- •Что такое индекс?
- •Принцип работы индексов
- •Команда create index
- •Типы индексов
- •Простые индексы
- •Уникальные индексы
- •Составные индексы
- •Простые и составные индексы
- •Неявные индексы
- •Когда следует создавать индекс?
- •Когда не следует создавать индекс?
- •Удаление индексов
- •Повышение эффективности работы с базой данных
- •Что означает оптимизация операторов sql?
- •Оптимизация базы данных и оптимизация операторов sql
- •Форматирование операторов sql
- •Форматирование операторов для лучшего восприятия
- •Правильный порядок таблиц в выражении from
- •Правильный порядок условий связывания
- •Наиболее ограничительное условие
- •Полное сканирование таблиц
- •Когда и как избегать полного сканирования таблиц
- •Другие аспекты оптимизации
- •Использование like и знаков подстановки
- •Замена операций or выражением с ключевым словом in
- •Недостатки использования выражения с ключевым словом having
- •Долгие операции сортировки
- •Использование готовых процедур
- •Отмена использования индексов в больших пакетных операциях
- •Средства для анализа производительности
- •Создание и использование представлений и синонимов
- •Что такое представление?
- •Использование представлений для защиты данных
- •Использование представлений для управления выводом данных
- •Хранение представлений
- •Создание представлений
- •Создание представления для данных одной таблицы
- •Создание представления для данных нескольких таблиц
- •Создание представления на основе другого представления
- •Уровни зависимости представлений
- •Опция with check option
- •Опции cascaded и local
- •Синтаксис
- •Примеры
- •Обновление данных представления
- •Представления и выражение order by
- •Удаление представлений
- •Что такое синонимы? (InterBase не поддержвается)
- •Управление синонимами
- •Создание синонимов
- •Удаление синонимов
- •Триггеры и хранимые процедуры (InterBase) sql для триггеров и хранимых процедур в InterBase
- •Обработка исключений
- •Обработка ошибок sql
- •Обработка ошибок InterBase
- •Комментарий
- •Триггеры и их назначение
- •Синтаксис create trigger
- •Примеры
- •Дополнительные сведения по работе с генераторами
- •Хранимые процедуры и их назначение
- •Процедуры для работы с датой и временем
Использование операторов exists, any, all, и some Описание учебной базы данных
В дальнейшем изложении будем использовать в качестве примера небольшую БД отражающую учет успеваемости студентов ВУЗа. В ней содержится четыре таблицы.
В таблице СТУДЕНТЫ (STUDENTS) содержится пять полей с информацией о студентах:
SNUM - номер студенческого билета;
SFAM - фамилия студента;
SIMA - имя студента;
SOTCH - отчество студента;
STIP - размер получаемой студентом стипендии.
В таблице ПРЕДМЕТЫ (PREDMET), состоящей из пяти полей, содержится информация об учебных предметах. Назначение полей таблицы следующее:
PNUM - номер (код) учебного предмета;
PNAME - наименование учебного предмета:
TNUM - номер (код) преподавателя;
HOURS - продолжительность учебной дисциплины в часах:
COURS - курс, на котором ведется данный учебный предмет.
В таблице ПРЕПОДАВАТЕЛИ (TEACHERS), состоящей из пяти полей, содержится информация о преподавателях. Поля таблицы следующие:
TNUM - код преподавателя;
TFAM - фамилия преподавателя;
TIMA - имя преподавателя;
TOTCH - отчество преподавателя;
TDATE - дата принятия преподавателя на работу.
В таблице УСПЕВАЕМОСТЬ (USP), состоящей из пяти полей, хранится информация об успеваемости студентов по учебным дисциплинам. Поля таблицы следующие:
UNUM - код факта сдачи учебной дисциплины;
OCENKA - оценка, полученная студентом по учебному предмету;
UDATE - дата сдачи;
SNUM - номер студенческого билета;
PNUM - код учебного предмета.
Таблица 1 PREDMET
PNUM |
PNAME |
TNUM |
HOURS |
COURS |
2001 |
Физика |
4001 |
34 |
1 |
2002 |
Химия |
4002 |
68 |
1 |
2003 |
Математика |
4003 |
68 |
1 |
2004 |
Философия |
4004 |
17 |
2 |
2005 |
Экономика |
4005 |
17 |
3 |
Таблица 2 STUDENTS
SNUM |
SFAM |
SIMA |
SOTCH |
STIP |
3412 |
Поляков |
Анатолий |
Алексеевич |
25.50 |
3413 |
Старова |
Любовь |
Михайловна |
17.00 |
3414 |
Гриценко |
Владимир |
Николаевич |
0.00 |
3415 |
Котенко |
Анатолий |
Николаевич |
0.00 |
3416 |
Нагорный |
Евгений |
Васильевич |
25.50 |
Таблица 3 TEACHERS
TNUM |
TFAM |
TIMA |
TOTCH |
TDATE |
4001 |
Викулина |
Валентина |
Ивановна |
01/04/1984 |
4002 |
Костыркин |
Олег |
Владимирович |
01/09/1997 |
4003 |
Казанко |
Виталий |
Владимирович |
01/09/1988 |
4004 |
Позднякова |
Любовь |
Алексеевна |
01/09/1988 |
4005 |
Загарийчук |
Игорь |
Дмитриевич |
10/05/1989 |
Таблица 4 USP
UNUM |
OCENKA |
UDATE |
SNUM |
PNUM |
1001 |
5 |
10/06/1999 |
3412 |
2001 |
1002 |
4 |
10/06/1999 |
3413 |
2003 |
1003 |
3 |
11/06/1999 |
3414 |
2005 |
1004 |
4 |
12/06/1999 |
3412 |
2003 |
1005 |
5 |
12/06/1999 |
3416 |
2004 |
Необходимо поговорить о некоторых специальных операторах, которые всегда берут подзапросы в качестве аргументов – это EXISTS, ANY, ALL, и SOME.
Оператор EXISTS используется для указания предикату на то, производится или не производится вывод в подзапросе, при этом EXISTS дает в качестве результата значение ИСТИНА или ЛОЖЬ. Это в свою очередь означает, что он может работать в предикате или в комбинации с другими булевскими выражениями – AND, OR, и NOT. Другими словами, EXISTS берет подзапрос как аргумент и оценивает его как истинный, если он осуществляет любой вывод, или как ложный, если он не делает этого. Например, можно решить, извлекать ли данные из таблицы успеваемости, если в ней присутствуют отличные оценки. Это реализуется следующим образом:
SELECT * FROM USP WHERE USP.OCENKA = 4
AND EXISTS (SELECT * FROM USP WHERE USP.OCENKA = 5);
Результаты запроса будут следующие:
UNUM OCENKA UDATE SNUM PNUM
1001 5 10/06/1999 3412 2001
1005 5 12/06/1999 3416 2004
При этом внутренний запрос выбирает все данные для всех студентов, получивших оценку 5. Оператор EXISTS во внешнем предикате отмечает, что некоторый вывод в подзапросе имел место, значит, это делает предикат верным. Подзапрос был выполнен только один раз для всего внешнего запроса, и, следовательно, имеет одно значение во всех случаях – по этой причине EXISTS делает предикат верным или неверным для всех строк сразу. В последнем примере, если строго говорить, EXISTS должен быть установлен так, чтобы выбрать только один столбец. Однако он выбирает все столбцы во вложенном предложении SELECT *. Это не вызывает ошибки, поскольку при выборе EXISTS как одного столбца, так и всех столбцов, он просто замечает выполнение вывода из подзапроса, а полученные значения не использует.
В соотнесенном подзапросе, предложение EXISTS оценивается отдельно для каждой строки таблицы, имя которой указано во внешнем запросе, точно так же, как и другие операторы предиката, когда используется соотнесенный подзапрос. Это дает возможность использовать EXISTS как предикат, который генерирует различные значения для каждой записи таблицы, указанной в основном запросе. Следовательно, информация из внутреннего запроса будет сохраняться. Например, с помощью следующего запроса выведем информацию о студентах, которые имеют несколько оценок:
SELECT DISTINCT SNUM FROM USP FIRST WHERE EXISTS (SELECT *
FROM USP SECOND
WHERE SECOND.SNUM = FIRST.SNUM AND SECOND.PNUM <> FIRST.PNUM);
Вывод запроса следующий:
SNUM
3412
Здесь для каждой текущей строки внешнего запроса внутренний запрос находит записи, которые совпадают со значением поля номера студента SNUM, но не совпадают со значением кода предмета PNUM. Если любые такие строки будут найдены подзапросом, это означает, что имеются, по крайней мере, две оценки, полученные текущим студентом. Если бы во внешнем запросе DISTINCT не был указан, то каждый из студентов, имеющий несколько оценок, был бы выбран столько раз, сколько у него оценок.
Для иллюстрации возможности использования комбинации из EXISTS и объединения, усовершенствуем последний пример таким образом, чтобы выводилась более подробная информация о студентах:
SELECT DISTINCT FIRST.SNUM, FIRST.SFAM, FIRST.SIMA, FIRST.SOTCH
FROM STUDENTS FIRST, USP SECOND WHERE EXISTS (SELECT *
FROM USP THIRD
WHERE SECOND.SNUM = THIRD.SNUM
AND SECOND.PNUM <> THIRD.PNUM) AND FIRST.SNUM = SECOND.SNUM;
В результате будет получено:
SNUM SFAM SIMA SOTCH
3412 Поляков Анатолий Алексеевич
В этом примере внутренний запрос, как и в предыдущем варианте, сообщает, что студент получил несколько оценок. Внешний запрос – это объединение таблиц успеваемости и студентов. Появившееся новое предложение основного предиката AND F1RST.SNUM = SECOND.SNUM оценивается на том же самом уровне, что и предложение EXISTS, т. к. это элемент предиката самого объединения двух таблиц из внешнего запроса.
С учетом того, что EXISTS может работать в комбинации с булевскими операторами, наиболее очевидным способом его использования является сочетание с оператором NOT. Например, для получения информации о студентах, имеющих только одну оценку, можно воспользоваться следующим запросом:
SELECT DISTINCT FIRST.SNUM, FIRST.SFAM, FIRST.SIMA, FIRST.SOTCH
FROM STUDENTS FIRST, USP SECOND WHERE NOT EXISTS (SELECT *
FROM USP THIRD
WHERE SECOND.SNUM = THIRD.SNUM
AND SECOND.PNUM <> THIRD.PNUM) AND FIRST.SNUM = SECOND.SNUM;
Вывод этого запроса приведен ниже:
SNUM SFAM SIMA SOTCH
3413 Старова Любовь Михайловна
3414 Гриценко Владимир Николаевич
3416 Нагорный Евгений Васильевич
Важным свойством EXISTS является то, что он не может взять агрегатную функцию в подзапросе, т. к. если агрегатная функция нашла какие-либо записи для операций с ними, то EXISTS будет верен в любом случае. Выходом из такой ситуации является использование вложенного подзапроса в подзапросе, в предикате которого присутствует EXISTS. Это позволяет тщательно структурировать запросы, делая их более понятными. Возвращаясь к примеру с нахождением информации о студентах, имеющих более одной оценки, можно предложить такой вариант запроса:
SELECT *
FROM STUDENTS FIRST WHERE EXISTS (SELECT *
FROM USP SECOND
WHERE FIRST.SNUM = SECOND.SNUM AND 1 <
(SELECT COUNT (*) FROM USP WHERE USP.SNUM = SECOND.SNUM));
В результате будет получено:
SNUM SFAM SIMA SOTCH STIP
3412 Поляков Анатолий Алексеевич 25.50
Такая конструкция работает следующим образом: внешний запрос выбирает из таблицы студентов STUDENTS текущую строку и выполняет подзапросы. Для текущей строки средним запросом берется в соответствие каждая строка из таблицы успеваемости USP. Всякий раз, когда обнаруживается информация в среднем запросе, который совпадает по номеру студенческого билета с текущей строкой во внешнем запросе. SQL должен рассматривать внутренний подзапрос для того, чтобы определить, будет ли предикат среднего запроса верен. Внутренний запрос считает количество оценок текущего студента, и, если это число больше, чем 1, делает предикат среднего запроса верным. Это, в свою очередь, делает EXISTS-предикат внешнего запроса верным для текущей строки таблицы.
Таким образом, несмотря на кажущуюся простоту, EXISTS может оказаться одним из самых трудных с точки зрения использования операторов в SQL. Существуют еще три специальных оператора, ориентируемых на подзапросы – это ANY. ALL и SOME, напоминающие EXISTS, которые воспринимают подзапросы, как аргументы. Однако эти операторы отличаются от EXISTS тем, что используются совместно с реляционными операторами, аналогично IN в подзапросах
Операторы SOME и ANY достаточно часто взаимозаменяемы, и в наших примерах будут работать одинаково. Различие в терминологии состоит в том, чтобы позволить пользователям употреблять тот термин, который наиболее однозначен. Поэтому все сказанное относительно ANY в равной степени относится и к SOME.
Рассмотрим следующий способ нахождения студентов, которые получали оценки по разным учебным предметам:
SELECT * FROM STUDENTS WHERE SNUM = ANY (SELECT SNUM FROM USP);
Вывод этого запроса приведен ниже:
SNUM SFAM SIMA SOTCH STIP
3412 Поляков Анатолий Алексеевич 25.50
3413 Старова Любовь Михайловна 17.00
3414 Гриценко Владимир Николаевич 0.00
3416 Нагорный Евгений Васильевич 25.50
Оператор ANY берет все значения, выведенные подзапросом, т. е. в примере – все значения поля SNUM, и оценивает их как верные, если любое из их равняется номеру студенческого билета текущей строки внешнего запроса. Отсюда следует, что подзапрос должен выбирать значения такого же типа, как и те, которые сравниваются в основном предикате. В этом его отличие от EXISTS, который просто определяет, производит ли вывод подзапрос или нет, фактически не используя эти результаты.
Вообще говоря, в ряде случаев допускается использование операторов IN или EXISTS вместо оператора ANY. Например, используя оператор IN, можно создать запрос, аналогичный предыдущему:
SELECT * FROM STUDENTS WHERE SNUM IN (SELECT SNUM FROM USP);
Вывод этого запроса такой, как в предыдущем примере, по этому приводить его не будем.
Интересен тот факт, что оператор ANY может использовать другие реляционные операторы, за исключением равняется, и. таким образом, реализовывать сравнения, которые недоступны с IN. Например, можно выполнить следующий запрос:
SELECT PNAME FROM PREDMET WHERE HOURS > ANY (SELECT HOURS FROM PREDMET);
Результат этого запроса следующий:
PNAME
Физика
Химия
Математика
Здесь выводятся название учебных предметов, для которых существует хотя бы одна учебная дисциплина с количеством часов, меньшим, чем у текущей.
В принципе, этот же запрос может быть реализован с использованием EXISTS, следующим образом:
SELECT PNAME
FROM PREDMET FIRST WHERE EXISTS (SELECT *
FROM PREDMET SECOND WHERE FIRST.HOURS > SECOND.HOURS);
В любом случае запрос, который может быть реализован с ANY и ALL, может быть также сформулирован с EXISTS, но не наоборот. Правда, в ряде случаев, из-за различий в обработке NULL значений, вариант с EXISTS не абсолютно идентичен, чем при использовании ANY, поэтому необходимо в таких случаях применять команду IS NULL.
Основное преимущество в использовании ANY и ALL по сравнению с EXISTS заключается в том, что последний требует соотнесенных подзапросов, порой сложных для понимания. Кроме того, подзапросы с ANY или ALL могут выполняться один раз и иметь вывод, используемый для определения предиката для каждой строки основного запроса, a EXISTS требует, чтобы весь подзапрос повторно выполнялся для каждой строки основного запроса.
Оператор ALL работает таким образом, что предикат является верным, если каждое значение, выбранное подзапросом, удовлетворяет условию в предикате внешнего запроса.
Например, если необходимо вывести только тех студентов, чьи оценки выше или равны полученным 10/06/1999, то можно воспользоваться следующим запросом:
SELECT * FROM USP
WHERE OCENKA >= ALL (SELECT OCENKA FROM USP WHERE UDATE = 10/06/1999);
Вывод этого запроса такой:
UNUM OCENKA UDATE SNUM PNUM
1001 5 10/06/1999 3412 2001
1005 5 12/06/1999 3416 2004
Запрос работает так: подзапрос проверяет значения оценок за 10/06/1999 для всех студентов. Затем он находит студентов с оценкой большей или равной по сравнению с оценками за 10/06/1999. Поскольку самая высокая оценка в этот день – отлично, то выбираются только записи с оценкой 5.
Как и в случае с ANY, допускается использовать EXISTS для альтернативной формулировки такого же запроса:
SELECT *
FROM USP FIRST WHERE EXISTS (SELECT * FROM USP SECOND
WHERE FIRST.OCENKA >= SECOND.OCENKA AND SECOND.UDATE = 10/06/1999);
Основное применение ALL находит со знаком неравенства, т. к. предикат может быть верным, если сравниваемое значение равно для всех, т. е. все записи, фактически, идентичны. Например, запрос
SELECT * FROM USP
WHERE OCENKA = ALL (SELECT OCENKA FROM USP WHERE UDATE = 10/06/1999);
является допустимым, но вывод будет только в случае, если все оценки за 10/06/1999 окажутся идентичными. Вероятно, не очень хорошо использовать запросы, которые работают только в определенных ситуациях.
Однако ALL гораздо более эффективно используется со знаком неравенства, т. е. с оператором < >. При этом обязательно надо учитывать, что если подзапрос возвращает много различных значений, то это означает неравенство любому результату. Иначе говоря, предикат верен, если данное значение не найдено среди результатов подзапроса. Рассмотрим такой запрос:
SELECT * FROM USP
WHERE OCENKA <> ALL (SELECT OCENKA FROM USP WHERE UDATE = 10/06/1999);
Вывод этого запроса таков:
UNUM OCENKA UDATE SNUM PNUM
1003 3 11/06/1999 3414 2005
Рассматриваемый запрос сделает следующее: подзапрос выберет все оценки за 10/06/1999 – это будут 5 и 4. После этого, основной запрос выведет все записи с оценкой, не совпадающей ни с одной из них. Аналогичный запрос можно сформулировать с использование оператора NOT IN:
SELECT * FROM USP
WHERE OCENKA NOT IN (SELECT OCENKA FROM USP WHERE UDATE = 10/06/1999);
или используя оператор ANY:
SELECT * FROM USP
WHERE NOT OCENKA = ANY (SELECT OCENKA FROM USP WHERE UDATE = 10/06/1999);
Вывод этих запросов такой же, как и первого. Таким образом, в SQL дать запрос на сравнение с использованием команды ANY для набора значений – то же самое, что произвести сравнение с любым отдельным значением из набора. Если запросить значения с помощью команды ALL не равные набору значений, то это то же самое, что определить факт отсутствия этого значения во всем наборе.
Как уже было сказано, имеются некоторые различия между EXISTS и операторами ANY и ALL с точки зрения работы с неизвестными и отсутствующими данными. Кроме того, важное различие между ALL и ANY – это способ действия в ситуации, когда подзапрос не возвращает никаких значений. Вообще говоря, во всех случаях, когда допустимый подзапрос не делает вывода. ALL автоматически возвращает значение ИСТИНА, a ANY –ЛОЖЬ. Например, это означает, что запрос:
SELECT * FROM USP
WHERE OCENKA >= ANY (SELECT OCENKA FROM USP WHERE UDATE = 10/06/2000);
не произведет никакого вывода, в то время как запрос
SELECT * FROM USP
WHERE OCENKA >= ALL (SELECT OCENKA FROM USP WHERE UDATE = 10/06/2000);
выведет всю таблицу USP. Действительно, если нет никаких оценок за 10/06/2000 то, естественно, ни одно из этих сравнений не имеет значения.
NULL значения имеют свои особенности при их обработке этими операторами. Когда SQL сравнивает два значения в предикате, одно из которых NULL, очевидно, результат этого неизвестен. Неизвестный предикат, аналогично неверному, является причиной того, что запись не выбирается, однако работать он будет несколько иначе, в зависимости от того, используется ALL или ANY. Рассмотрим предыдущий пример с ANY и такой запрос:
SELECT * FROM USP FIRST WHERE EXISTS (SELECT *
FROM USP SECOND
WHERE FIRST.OCENKA >= SECOND.OCENKA AND SECOND.UDATE = 10/06/2000);
Пока NULL значений в таблице нет, оба запроса будут вести себя одинаково. Но в случае появления NULL значения в поле OCENKA таблицы успеваемости, в варианте с ANY значение предиката при обработке этой строки станет неизвестным и вывода для нее не будет в любом случае, однако другие строки будут обрабатываться обычным образом. В варианте с EXISTS, значение NULL используется в предикате подзапроса, делая его неизвестным в каждом случае, а это означает, что подзапрос не будет производить никаких значений, и запрос не произведет вывода вообще. Это является важным фактором в пользу использования варианта с ANY.