
- •Глава 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
- •Примеры
- •Дополнительные сведения по работе с генераторами
- •Хранимые процедуры и их назначение
- •Процедуры для работы с датой и временем
Примеры
Следующая инструкция предоставляет SELECT и DELETE привилегии пользователю. Опция WHITH GRANT OPTION дает пользователю GRANT полномочия:
GRANT SELECT, DELETE ON COUNTRY TO CHLOE WITH GRANT OPTION;
Следующая инструкция предоставляет EXECUTE привилегии на процедуру другим процедурам и пользователю:
GRANT EXECUTE ON PROCEDURE GET_EMP_PROJ TO PROCEDURE ADD_EMP_PROJ_LUIS;
Вопросы и ответы
При создании таблицы обязательно ли в ее имени использовать суффикс _tbl?
Определенно нет. Вас ничего не принуждают его использовать. Например, таблице с информацией о служащих можно назначить либо одно из следующих имен, либо любое другое, которое будет соответствовать хранимым в этой таблице данным:
EMPLOYEE EMP_TBL EMPLOYEE TBL EMPLOYEE^TABLE WORKER
Почему при удалении таблицы так важно указывать имя соответствующей схемы?
Вот вам непридуманная история о молодом администраторе базы данных, удалившем таблицу. Один программист создал в рамках своей схемы таблицу с именем точно таким же, как у таблицы с производственной информацией. Прошло некоторое время, и он из компании уволился. При попытке ликвидации его учетной записи оператор DROP USER вернул ошибку из-за каких-то принадлежащих программисту объектов, оставшихся в базе данных. Исследование проблемы показало, что таблица, созданная тем программистом, не нужна и по отношению к ней был применен оператор DROP TABLE.
Все прошло прекрасно, но возникла другая проблема – оказалось, что администратор применил оператор DROP TABLE, войдя в базу данных под именем производственной схемы. Как было бы хорошо, если бы администратор указал имя схемы или владельца удаляемой таблицы. Да, была удалена не та таблица из не той схемы. На восстановление производственной базы данных потребовалось почти восемь часов.
Практикум
Тесты
Будет ли работать следующий оператор CREATE TABLE? Если нет, то что нужно в нем исправить?
CREATE TABLE EMPLOYEE_TBL AS (
SSN NUMBER(9) NOT NULL,
LAST_NAME VARCHAR(20) NOT NULL
FIRST_NAME VARCHAR(20) NOT NULL,
MIDDLE_NAME VARCHAR(20) NOT NULL,
ST ADDRESS VARCHAR2(30) NOT NULL,
CITY CHAR(20) NOT NULL,
STATE CHAR(2) NOT NULL,
ZIP NUMBER(4) NOT NULL,
DATE HIRED DATE;
Можно ли удалить столбец из таблицы?
Примеры
SET NAMES WIN1251;
SET SQL DIALECT 3;
CREATE DATABASE 'C:\Temp\FifthOcean.gdb' USER 'boss' PASSWORD 'ray8)bow' PAGE_SIZE 1024 DEFAULT CHARACTER SET WIN1251;
CREATE TABLE customer (
id_customer INTEGER NOT NULL,
sity VARCHAR(40) NOT NULL,
company_name VARCHAR(100) NOT NULL,
juridical_person VARCHAR(200) NOT NULL,
bank_properties BLOB SUB_TYPE 1,
adress VARCHAR(100) NOT NULL,
account_adress VARCHAR(100) NOT NULL,
comment BLOB SUB_TYPE 1
);
ALTER TABLE customer
ADD PRIMARY KEY (id_customer);
GRANT ALL ON customer TO ACCOUNTANT;
GRANT ALL ON customer TO MANAGER;
CREATE TABLE how_to_contact_customer (
id_contact INTEGER NOT NULL,
id_customer INTEGER NOT NULL,
contact_method VARCHAR(50) NOT NULL,
contact VARCHAR(50) NOT NULL,
comment BLOB SUB_TYPE 1
);
ALTER TABLE how_to_contact_customer
ADD PRIMARY KEY (id_contact);
ALTER TABLE how_to_contact_customer
ADD FOREIGN KEY (id_customer)
REFERENCES customer (id_customer)
ON UPDATE CASCADE
ON DELETE CASCADE;
GRANT ALL ON how_to_contact_customer TO ACCOUNTANT;
GRANT ALL ON how_to_contact_customer TO MANAGER;
CREATE TABLE contact_person (
id_person INTEGER NOT NULL,
id_customer INTEGER NOT NULL,
last_name VARCHAR(50),
first_name VARCHAR(50),
second_name VARCHAR(50),
place VARCHAR(100),
comment BLOB SUB_TYPE 1
);
ALTER TABLE contact_person
ADD PRIMARY KEY (id_person);
ALTER TABLE contact_person
ADD FOREIGN KEY (id_customer)
REFERENCES customer (id_customer)
ON UPDATE CASCADE
ON DELETE CASCADE;
GRANT ALL ON contact_person TO ACCOUNTANT;
GRANT ALL ON contact_person TO MANAGER;
CREATE TABLE how_to_contact_person (
id_contact INTEGER NOT NULL,
id_person INTEGER NOT NULL,
contact_method VARCHAR(50) NOT NULL,
contact VARCHAR(50) NOT NULL,
comment BLOB SUB_TYPE 1
);
ALTER TABLE how_to_contact_person
ADD PRIMARY KEY (id_contact);
ALTER TABLE how_to_contact_person
ADD FOREIGN KEY (id_person)
REFERENCES contact_person (id_person)
ON UPDATE CASCADE
ON DELETE CASCADE;
GRANT ALL ON how_to_contact_person TO ACCOUNTANT;
GRANT ALL ON how_to_contact_person TO MANAGER;
CREATE TABLE beer_delivery (
id_delivery INTEGER NOT NULL,
id_customer INTEGER NOT NULL,
delivery_date TIMESTAMP NOT NULL,
delivery_account_number VARCHAR(50) NOT NULL,
mtb_number VARCHAR(20) NOT NULL,
mtb_volume DECIMAL(8,2) NOT NULL,
delivery_account_volume DECIMAL(8,2) NOT NULL,
beer_type VARCHAR(20) NOT NULL,
gift DECIMAL(8,2) NOT NULL,
sale_price DECIMAL(6,2) NOT NULL,
swap_beer DECIMAL(8,2) NOT NULL,
lack_beer DECIMAL(8,2) NOT NULL,
mtd_empty_date TIMESTAMP,
ablution_period INTEGER NOT NULL,
comment BLOB SUB_TYPE 1
);
ALTER TABLE beer_delivery
ADD PRIMARY KEY (id_delivery);
ALTER TABLE beer_delivery
ADD FOREIGN KEY (id_customer)
REFERENCES customer (id_customer)
ON UPDATE CASCADE
ON DELETE CASCADE;
GRANT ALL ON beer_delivery TO ACCOUNTANT;
GRANT ALL ON beer_delivery TO MANAGER;
CREATE TABLE sale (
id_sale INTEGER NOT NULL,
id_delivery INTEGER NOT NULL,
sale_date TIMESTAMP NOT NULL,
sale_volume DECIMAL(12,2) NOT NULL,
comment BLOB SUB_TYPE 1
);
ALTER TABLE sale
ADD PRIMARY KEY (id_sale);
ALTER TABLE sale
ADD FOREIGN KEY (id_delivery)
REFERENCES beer_delivery (id_delivery)
ON UPDATE CASCADE
ON DELETE CASCADE;
GRANT ALL ON sale TO ACCOUNTANT;
GRANT ALL ON sale TO MANAGER;
CREATE TABLE payment (
id_payment INTEGER NOT NULL,
id_delivery INTEGER NOT NULL,
pay_date TIMESTAMP NOT NULL,
pay_amount DECIMAL(12,2) NOT NULL,
comment BLOB SUB_TYPE 1
);
ALTER TABLE payment
ADD PRIMARY KEY (id_payment);
ALTER TABLE payment
ADD FOREIGN KEY (id_delivery)
REFERENCES beer_delivery (id_delivery)
ON UPDATE CASCADE
ON DELETE CASCADE;
GRANT ALL ON payment TO ACCOUNTANT;
GRANT SELECT, REFERENCES ON payment TO MANAGER;
CREATE TABLE ablution (
id_ablution INTEGER NOT NULL,
id_delivery INTEGER NOT NULL,
ablution_date TIMESTAMP NOT NULL,
ablution_volume DECIMAL(6, 2) NOT NULL,
comment BLOB SUB_TYPE 1
);
ALTER TABLE ablution
ADD PRIMARY KEY (id_ablution);
ALTER TABLE ablution
ADD FOREIGN KEY (id_delivery)
REFERENCES beer_delivery (id_delivery)
ON UPDATE CASCADE
ON DELETE CASCADE;
GRANT ALL ON ablution TO ACCOUNTANT;
GRANT ALL ON ablution TO MANAGER;
CREATE PROCEDURE SUM_ABLUTION (ID INTEGER)
RETURNS (SUMMA DECIMAL(8, 2))
AS
DECLARE VARIABLE SUM_TEMP DECIMAL(8, 2);
BEGIN
SELECT SUM(ablution_volume)
FROM ablution a
WHERE a.id_delivery = :ID
INTO :SUM_TEMP;
IF(SUM_TEMP IS NULL) THEN SUM_TEMP = 0;
SUMMA = SUM_TEMP;
SUSPEND;
END;
GRANT EXECUTE ON PROCEDURE SUM_ABLUTION TO ACCOUNTANT, MANAGER;
ALTER TABLE beer_delivery
ADD total_ablution DECIMAL(8,2) COMPUTED BY
((SELECT SUMMA
FROM SUM_ABLUTION(beer_delivery.id_delivery)));
ALTER TABLE beer_delivery
ADD total_price DECIMAL(8,2) COMPUTED BY
(((delivery_account_volume - gift - total_ablution) * sale_price));
CREATE TABLE equipment_delivery (
id_delivery INTEGER NOT NULL,
id_customer INTEGER NOT NULL,
delivery_date TIMESTAMP NOT NULL,
delivery_account_number VARCHAR(50) NOT NULL,
co2_quantity INTEGER NOT NULL,
co2_sale_price DECIMAL(6,2) NOT NULL,
glass_05_quantity INTEGER NOT NULL,
glass_05_sale_price DECIMAL(6,2) NOT NULL,
glass_033_quantity INTEGER NOT NULL,
glass_033_sale_price DECIMAL(6,2) NOT NULL,
birdekel_quantity INTEGER NOT NULL,
birdekel_sale_price DECIMAL(6,2) NOT NULL,
serviette_quantity INTEGER NOT NULL,
serviette_sale_price DECIMAL(6,2) NOT NULL,
flag_quantity INTEGER NOT NULL,
flag_sale_price DECIMAL(6,2) NOT NULL,
total_price DECIMAL(8,2) COMPUTED BY
(co2_quantity * co2_sale_price +
glass_05_quantity * glass_05_sale_price +
glass_033_quantity * glass_033_sale_price +
birdekel_quantity * birdekel_sale_price +
serviette_quantity * serviette_sale_price +
flag_quantity * flag_sale_price),
comment BLOB SUB_TYPE 1
);
ALTER TABLE equipment_delivery
ADD PRIMARY KEY (id_delivery);
ALTER TABLE equipment_delivery
ADD FOREIGN KEY (id_customer)
REFERENCES customer (id_customer)
ON UPDATE CASCADE
ON DELETE CASCADE;
GRANT ALL ON equipment_delivery TO ACCOUNTANT;
GRANT ALL ON equipment_delivery TO MANAGER;
CREATE TABLE equipment_delivery_full (
id_delivery INTEGER NOT NULL,
id_customer INTEGER NOT NULL,
delivery_date TIMESTAMP NOT NULL,
delivery_account_number VARCHAR(50) NOT NULL,
comment BLOB SUB_TYPE 1
);
ALTER TABLE equipment_delivery_full
ADD PRIMARY KEY (id_delivery);
ALTER TABLE equipment_delivery_full
ADD FOREIGN KEY (id_customer)
REFERENCES customer (id_customer)
ON UPDATE CASCADE
ON DELETE CASCADE;
GRANT ALL ON equipment_delivery_full TO ACCOUNTANT;
GRANT ALL ON equipment_delivery_full TO MANAGER;
CREATE TABLE accessories (
id_accessories INTEGER NOT NULL,
id_delivery INTEGER NOT NULL,
accessories_name VARCHAR(100) NOT NULL,
accessories_quantity DECIMAL(8,2) NOT NULL,
accessories_price DECIMAL(8,2) NOT NULL,
full_price DECIMAL(9,2) COMPUTED BY
(accessories_quantity * accessories_price),
comment BLOB SUB_TYPE 1
);
ALTER TABLE accessories
ADD PRIMARY KEY (id_accessories);
ALTER TABLE accessories
ADD FOREIGN KEY (id_delivery)
REFERENCES equipment_delivery_full (id_delivery)
ON UPDATE CASCADE
ON DELETE CASCADE;
GRANT ALL ON accessories TO ACCOUNTANT;
GRANT ALL ON accessories TO MANAGER;
CREATE PROCEDURE EQUIPMENT_DELIV_PRICE (ID INTEGER)
RETURNS (PRICE DECIMAL(12, 2))
AS
DECLARE VARIABLE PRICE_TEMP DECIMAL(12, 2);
BEGIN
SELECT SUM(full_price)
FROM accessories a
WHERE a.id_delivery = :ID
INTO :PRICE_TEMP;
IF(PRICE_TEMP IS NULL) THEN PRICE_TEMP = 0;
PRICE = PRICE_TEMP;
SUSPEND;
END;
GRANT EXECUTE ON PROCEDURE EQUIPMENT_DELIV_PRICE TO ACCOUNTANT, MANAGER;
CREATE PROCEDURE SALE_VOLUME (ID INTEGER)
RETURNS (VOL DECIMAL(12, 2))
AS
DECLARE VARIABLE VOL_TEMP DECIMAL(12, 2);
BEGIN
SELECT MAX(sale_volume)
FROM sale a
WHERE a.id_delivery = :ID
INTO :VOL_TEMP;
IF(VOL_TEMP IS NULL) THEN VOL_TEMP = 0;
VOL = VOL_TEMP;
SUSPEND;
END;
GRANT EXECUTE ON PROCEDURE SALE_VOLUME TO ACCOUNTANT, MANAGER;
ALTER TABLE beer_delivery
ADD last_sale_volume DECIMAL(12,2) COMPUTED BY
((SELECT VOL
FROM SALE_VOLUME(beer_delivery.id_delivery)));
CREATE PROCEDURE SUM_PAY (ID INTEGER)
RETURNS (SUMMA DECIMAL(12, 2))
AS
DECLARE VARIABLE SUM_TEMP DECIMAL(12, 2);
BEGIN
SELECT SUM(pay_amount)
FROM payment a
WHERE a.id_delivery = :ID
INTO :SUM_TEMP;
IF(SUM_TEMP IS NULL) THEN SUM_TEMP = 0;
SUMMA = SUM_TEMP;
SUSPEND;
END;
GRANT EXECUTE ON PROCEDURE SUM_PAY TO ACCOUNTANT, MANAGER;
ALTER TABLE beer_delivery
ADD pay_amount DECIMAL(12,2) COMPUTED BY
((SELECT SUMMA
FROM SUM_PAY(beer_delivery.id_delivery)));
ALTER TABLE beer_delivery
ADD debt DECIMAL(12,2) COMPUTED BY
(total_price - pay_amount);
CREATE PROCEDURE IS_ACTIVE (ID INTEGER)
RETURNS (ACTIVE_DELIV SMALLINT)
AS
DECLARE VARIABLE DATE_TEMP TIMESTAMP;
BEGIN
SELECT mtd_empty_date
FROM beer_delivery a
WHERE a.id_delivery = :ID
INTO :DATE_TEMP;
ACTIVE_DELIV = 0;
IF(DATE_TEMP IS NULL) THEN ACTIVE_DELIV = 1;
SUSPEND;
END;
GRANT EXECUTE ON PROCEDURE IS_ACTIVE TO ACCOUNTANT, MANAGER;
ALTER TABLE beer_delivery
ADD active_delivery SMALLINT COMPUTED BY
((SELECT ACTIVE_DELIV
FROM IS_ACTIVE(beer_delivery.id_delivery)));
CREATE PROCEDURE IS_EXPIRED (ID INTEGER, PERIOD INTEGER)
RETURNS (PAY_EXP SMALLINT)
AS
DECLARE VARIABLE DATE_TEMP TIMESTAMP;
DECLARE VARIABLE LAST_PAY_DATE_TEMP TIMESTAMP;
DECLARE VARIABLE DEBT_TEMP DECIMAL(12,2);
BEGIN
SELECT delivery_date, debt
FROM beer_delivery a
WHERE a.id_delivery = :ID
INTO :DATE_TEMP, :DEBT_TEMP;
SELECT MAX(pay_date)
FROM payment a
WHERE a.id_delivery = :ID
INTO :LAST_PAY_DATE_TEMP;
PAY_EXP = 0;
IF((((current_timestamp - DATE_TEMP) > PERIOD) AND (DEBT_TEMP > 0))
OR
((LAST_PAY_DATE_TEMP - DATE_TEMP) > PERIOD)) THEN PAY_EXP = 1;
SUSPEND;
END;
GRANT EXECUTE ON PROCEDURE IS_EXPIRED TO ACCOUNTANT, MANAGER;
CREATE PROCEDURE ABLUTION_IS_EXPIRED (ID INTEGER)
RETURNS (ABLUTION_EXP SMALLINT)
AS
DECLARE VARIABLE DATE_TEMP TIMESTAMP;
DECLARE VARIABLE END_DATE_TEMP TIMESTAMP;
DECLARE VARIABLE PERIOD_TEMP INTEGER;
BEGIN
SELECT MAX(ablution_date)
FROM ablution a
WHERE a.id_delivery = :ID
INTO :DATE_TEMP;
SELECT ablution_period
FROM beer_delivery a
WHERE a.id_delivery = :ID
INTO :PERIOD_TEMP;
SELECT mtd_empty_date
FROM beer_delivery a
WHERE a.id_delivery = :ID
INTO :END_DATE_TEMP;
IF(DATE_TEMP IS NULL)
THEN
BEGIN
SELECT delivery_date
FROM beer_delivery a
WHERE a.id_delivery = :ID
INTO :DATE_TEMP;
END
ABLUTION_EXP = 0;
IF(((current_timestamp - DATE_TEMP) > PERIOD_TEMP) AND
(END_DATE_TEMP IS NULL))
THEN ABLUTION_EXP = 1;
EXIT;
END;
GRANT EXECUTE ON PROCEDURE ABLUTION_IS_EXPIRED TO ACCOUNTANT, MANAGER;
CREATE PROCEDURE SET_TIMESTAMP_NULL_BEER_DELIVERY (ID INTEGER)
AS
BEGIN
UPDATE beer_delivery a
SET mtd_empty_date = NULL
WHERE a.id_delivery = :ID;
EXIT;
END;
GRANT EXECUTE ON PROCEDURE SET_TIMESTAMP_NULL_BEER_DELIVERY TO ACCOUNTANT, MANAGER;
CREATE PROCEDURE IS_NULL_MTD_EMPTY_DATE (ID INTEGER)
RETURNS (IS_NULL INTEGER)
AS
DECLARE VARIABLE DATA_TEMP TIMESTAMP;
BEGIN
SELECT mtd_empty_date
FROM beer_delivery a
WHERE a.id_delivery = :ID
INTO :DATA_TEMP;
IS_NULL = 0;
IF(DATA_TEMP IS NULL) THEN IS_NULL = 1;
SUSPEND;
END;
GRANT EXECUTE ON PROCEDURE IS_NULL_MTD_EMPTY_DATE TO ACCOUNTANT, MANAGER;
CREATE PROCEDURE IS_NULL_DELIVERY_DATE (ID INTEGER)
RETURNS (IS_NULL INTEGER)
AS
DECLARE VARIABLE DATA_TEMP TIMESTAMP;
BEGIN
SELECT delivery_date
FROM beer_delivery a
WHERE a.id_delivery = :ID
INTO :DATA_TEMP;
IS_NULL = 0;
IF(DATA_TEMP IS NULL) THEN IS_NULL = 1;
SUSPEND;
END;
GRANT EXECUTE ON PROCEDURE IS_NULL_DELIVERY_DATE TO ACCOUNTANT, MANAGER;
CREATE PROCEDURE IS_NULL_SALE_DATE (ID INTEGER)
RETURNS (IS_NULL INTEGER)
AS
DECLARE VARIABLE DATA_TEMP TIMESTAMP;
BEGIN
SELECT sale_date
FROM sale a
WHERE a.id_sale = :ID
INTO :DATA_TEMP;
IS_NULL = 0;
IF(DATA_TEMP IS NULL) THEN IS_NULL = 1;
SUSPEND;
END;
GRANT EXECUTE ON PROCEDURE IS_NULL_SALE_DATE TO ACCOUNTANT, MANAGER;
CREATE PROCEDURE IS_NULL_PAY_DATE (ID INTEGER)
RETURNS (IS_NULL INTEGER)
AS
DECLARE VARIABLE DATA_TEMP TIMESTAMP;
BEGIN
SELECT pay_date
FROM payment a
WHERE a.id_payment = :ID
INTO :DATA_TEMP;
IS_NULL = 0;
IF(DATA_TEMP IS NULL) THEN IS_NULL = 1;
SUSPEND;
END;
GRANT EXECUTE ON PROCEDURE IS_NULL_PAY_DATE TO ACCOUNTANT, MANAGER;
CREATE PROCEDURE IS_NULL_ABLUTION_DATE (ID INTEGER)
RETURNS (IS_NULL INTEGER)
AS
DECLARE VARIABLE DATA_TEMP TIMESTAMP;
BEGIN
SELECT ablution_date
FROM ablution a
WHERE a.id_ablution = :ID
INTO :DATA_TEMP;
IS_NULL = 0;
IF(DATA_TEMP IS NULL) THEN IS_NULL = 1;
SUSPEND;
END;
GRANT EXECUTE ON PROCEDURE IS_NULL_ABLUTION_DATE TO ACCOUNTANT, MANAGER;
CREATE PROCEDURE IS_NULL_EQ_DELIVERY_DATE (ID INTEGER)
RETURNS (IS_NULL INTEGER)
AS
DECLARE VARIABLE DATA_TEMP TIMESTAMP;
BEGIN
SELECT delivery_date
FROM equipment_delivery a
WHERE a.id_delivery = :ID
INTO :DATA_TEMP;
IS_NULL = 0;
IF(DATA_TEMP IS NULL) THEN IS_NULL = 1;
SUSPEND;
END;
GRANT EXECUTE ON PROCEDURE IS_NULL_EQ_DELIVERY_DATE TO ACCOUNTANT, MANAGER;
CREATE PROCEDURE IS_NULL_EQ_DELIVERY_DATE_FULL (ID INTEGER)
RETURNS (IS_NULL INTEGER)
AS
DECLARE VARIABLE DATA_TEMP TIMESTAMP;
BEGIN
SELECT delivery_date
FROM equipment_delivery_full a
WHERE a.id_delivery = :ID
INTO :DATA_TEMP;
IS_NULL = 0;
IF(DATA_TEMP IS NULL) THEN IS_NULL = 1;
SUSPEND;
END;
GRANT EXECUTE ON PROCEDURE IS_NULL_EQ_DELIVERY_DATE_FULL TO ACCOUNTANT, MANAGER;
ALTER TABLE equipment_delivery_full
ADD equipment_price DECIMAL(12,2) COMPUTED BY
((SELECT PRICE
FROM EQUIPMENT_DELIV_PRICE(equipment_delivery_full.id_delivery)));
ALTER TABLE beer_delivery
ADD payment_expired SMALLINT COMPUTED BY
((SELECT PAY_EXP
FROM IS_EXPIRED(beer_delivery.id_delivery, 30)));
ALTER TABLE customer
ADD number_total_deliveries INTEGER COMPUTED BY
((SELECT COUNT(*)
FROM beer_delivery
WHERE beer_delivery.id_customer=customer.id_customer));
ALTER TABLE customer
ADD number_active_deliveries INTEGER COMPUTED BY
((SELECT COUNT(*)
FROM beer_delivery
WHERE (beer_delivery.id_customer=customer.id_customer
AND beer_delivery.mtd_empty_date IS NULL)));
ALTER TABLE customer
ADD total_sale_volume DECIMAL(12,2) COMPUTED BY
((SELECT SUM(last_sale_volume)
FROM beer_delivery
WHERE (beer_delivery.id_customer=customer.id_customer)));
ALTER TABLE customer
ADD total_active_sale_volume DECIMAL(12,2) COMPUTED BY
((SELECT SUM(last_sale_volume)
FROM beer_delivery
WHERE (beer_delivery.id_customer=customer.id_customer
AND beer_delivery.mtd_empty_date IS NULL)));
ALTER TABLE customer
ADD total_pay_amount DECIMAL(12,2) COMPUTED BY
((SELECT SUM(pay_amount)
FROM beer_delivery
WHERE (beer_delivery.id_customer=customer.id_customer)));
ALTER TABLE customer
ADD total_active_pay_amount DECIMAL(12,2) COMPUTED BY
((SELECT SUM(pay_amount)
FROM beer_delivery
WHERE (beer_delivery.id_customer=customer.id_customer
AND beer_delivery.mtd_empty_date IS NULL)));
ALTER TABLE customer
ADD number_expired_deliveries INTEGER COMPUTED BY
((SELECT COUNT(*)
FROM beer_delivery
WHERE (beer_delivery.id_customer=customer.id_customer
AND beer_delivery.payment_expired = 1)));
ALTER TABLE customer
ADD total_debt_amount DECIMAL(12,2) COMPUTED BY
((SELECT SUM(debt)
FROM beer_delivery
WHERE (beer_delivery.id_customer=customer.id_customer)));
ALTER TABLE customer
ADD total_active_debt_amount DECIMAL(12,2) COMPUTED BY
((SELECT SUM(debt)
FROM beer_delivery
WHERE (beer_delivery.id_customer=customer.id_customer
AND beer_delivery.mtd_empty_date IS NULL)));
ALTER TABLE customer
ADD beer_on_sale DECIMAL(8,2) COMPUTED BY
((SELECT SUM(delivery_account_volume - gift)
FROM beer_delivery
WHERE (beer_delivery.id_customer=customer.id_customer
AND beer_delivery.mtd_empty_date IS NULL)));
CREATE VIEW general_info AS
SELECT sity, company_name, total_sale_volume, total_active_sale_volume,
total_pay_amount, total_active_pay_amount, total_debt_amount,
total_active_debt_amount, beer_on_sale, number_expired_deliveries
FROM customer;
GRANT ALL ON general_info TO ACCOUNTANT;
GRANT ALL ON general_info TO MANAGER;
CREATE ASCENDING INDEX customer_sity_ind ON customer(sity);
CREATE ASCENDING INDEX customer_company_name_ind ON customer(company_name);
CREATE ASCENDING INDEX customer_sity_company_name_ind ON customer(sity, company_name);
CREATE ASCENDING INDEX how_to_contact_customer_contact_method_ind ON how_to_contact_customer(contact_method);
CREATE ASCENDING INDEX contact_person_last_name_ind ON contact_person(last_name);
CREATE ASCENDING INDEX contact_person_place_ind ON contact_person(place);
CREATE ASCENDING INDEX contact_person_place_last_name_ind ON contact_person(place, last_name);
CREATE ASCENDING INDEX how_to_contact_person_contact_method_ind ON how_to_contact_person(contact_method);
CREATE ASCENDING INDEX beer_delivery_delivery_date_ind ON beer_delivery(delivery_date);
CREATE ASCENDING INDEX sale_sale_date_ind ON sale(sale_date);
CREATE ASCENDING INDEX payment_pay_date_ind ON payment(pay_date);
CREATE ASCENDING INDEX equipment_delivery_delivery_date_ind ON equipment_delivery(delivery_date);
CREATE ASCENDING INDEX sale_id_delivery_sale_date_ind ON sale(id_delivery, sale_date);
CREATE ASCENDING INDEX how_to_contact_customer_customer_id_contact_method_ind ON how_to_contact_customer(id_customer, contact_method);
CREATE ASCENDING INDEX contact_person_customer_id_place_last_name_ind ON contact_person(id_customer, place, last_name);
CREATE ASCENDING INDEX how_to_contact_person_id_person_contact_method_ind ON how_to_contact_person(id_person, contact_method);
CREATE ASCENDING INDEX beer_delivery_id_customer_delivery_date_ind ON beer_delivery(id_customer, delivery_date);
CREATE ASCENDING INDEX payment_id_delivery_pay_date_ind ON payment(id_delivery, pay_date);
CREATE ASCENDING INDEX equipment_delivery_id_customer_delivery_date_ind ON equipment_delivery(id_customer, delivery_date);
CREATE ASCENDING INDEX ablution_id_delivery_ablution_date_ind ON ablution(id_delivery, ablution_date);
CREATE ASCENDING INDEX equipment_delivery_full_delivery_date_ind ON equipment_delivery_full(delivery_date);
CREATE ASCENDING INDEX equipment_delivery_full_id_customer_delivery_date_ind ON equipment_delivery_full(id_customer, delivery_date);
CREATE ASCENDING INDEX equipment_delivery_full_id_delivery_delivery_date_ind ON equipment_delivery_full(id_delivery, delivery_date);
CREATE ASCENDING INDEX accessories_accessories_name_ind ON accessories(accessories_name);
CREATE ASCENDING INDEX accessories_id_accessories_accessories_name_ind ON accessories(id_accessories, accessories_name);
CREATE ASCENDING INDEX accessories_id_delivery_accessories_name_ind ON accessories(id_delivery, accessories_name);
CREATE GENERATOR GEN_EQUIPMENT_DELIVERY_FULL_ID_DELIVERY;
SET GENERATOR GEN_EQUIPMENT_DELIVERY_FULL_ID_DELIVERY TO 10;
CREATE PROCEDURE GET_ID_DELIVERY_EQUIPMENT_DELIVERY_FULL
RETURNS (ID INTEGER)
AS
BEGIN
ID = GEN_ID(GEN_EQUIPMENT_DELIVERY_FULL_ID_DELIVERY, 1);
END;
GRANT EXECUTE ON PROCEDURE GET_ID_DELIVERY_EQUIPMENT_DELIVERY_FULL TO ACCOUNTANT, MANAGER;
CREATE GENERATOR GEN_ACCESSORIES_ID_ACCESSORIES;
SET GENERATOR GEN_ACCESSORIES_ID_ACCESSORIES TO 10;
CREATE PROCEDURE GET_ID_ACCESSORIES_ACCESSORIES
RETURNS (ID INTEGER)
AS
BEGIN
ID = GEN_ID(GEN_ACCESSORIES_ID_ACCESSORIES, 1);
END;
GRANT EXECUTE ON PROCEDURE GET_ID_ACCESSORIES_ACCESSORIES TO ACCOUNTANT, MANAGER;
CREATE GENERATOR GEN_CUSTOMER_ID_CUSTOMER;
SET GENERATOR GEN_CUSTOMER_ID_CUSTOMER TO 10;
CREATE PROCEDURE GET_ID_CUSTOMER
RETURNS (ID INTEGER)
AS
BEGIN
ID = GEN_ID(GEN_CUSTOMER_ID_CUSTOMER, 1);
END;
GRANT EXECUTE ON PROCEDURE GET_ID_CUSTOMER TO ACCOUNTANT, MANAGER;
CREATE GENERATOR GEN_BEER_DELIVERY_ID_DELIVERY;
SET GENERATOR GEN_BEER_DELIVERY_ID_DELIVERY TO 10;
CREATE PROCEDURE GET_ID_BEER_DELIVERY
RETURNS (ID INTEGER)
AS
BEGIN
ID = GEN_ID(GEN_BEER_DELIVERY_ID_DELIVERY, 1);
END;
GRANT EXECUTE ON PROCEDURE GET_ID_BEER_DELIVERY TO ACCOUNTANT, MANAGER;
CREATE GENERATOR GEN_CONTACT_PERSON_ID_PERSON;
SET GENERATOR GEN_CONTACT_PERSON_ID_PERSON TO 10;
CREATE PROCEDURE GET_ID_PERSON
RETURNS (ID INTEGER)
AS
BEGIN
ID = GEN_ID(GEN_CONTACT_PERSON_ID_PERSON, 1);
END;
GRANT EXECUTE ON PROCEDURE GET_ID_PERSON TO ACCOUNTANT, MANAGER;
CREATE GENERATOR GEN_EQUIPMENT_DELIVERY_ID_DELIVERY;
SET GENERATOR GEN_EQUIPMENT_DELIVERY_ID_DELIVERY TO 10;
CREATE PROCEDURE GET_ID_EQUIPMENT_DELIVERY
RETURNS (ID INTEGER)
AS
BEGIN
ID = GEN_ID(GEN_EQUIPMENT_DELIVERY_ID_DELIVERY, 1);
END;
GRANT EXECUTE ON PROCEDURE GET_ID_EQUIPMENT_DELIVERY TO ACCOUNTANT, MANAGER;
CREATE GENERATOR GEN_HOW_TO_CONTACT_CUSTOMER_ID_CONTACT;
SET GENERATOR GEN_HOW_TO_CONTACT_CUSTOMER_ID_CONTACT TO 10;
CREATE PROCEDURE GET_ID_CUSTOMER_CONTACT
RETURNS (ID INTEGER)
AS
BEGIN
ID = GEN_ID(GEN_HOW_TO_CONTACT_CUSTOMER_ID_CONTACT, 1);
END;
GRANT EXECUTE ON PROCEDURE GET_ID_CUSTOMER_CONTACT TO ACCOUNTANT, MANAGER;
CREATE GENERATOR GEN_HOW_TO_CONTACT_PERSON_ID_CONTACT;
SET GENERATOR GEN_HOW_TO_CONTACT_PERSON_ID_CONTACT TO 10;
CREATE PROCEDURE GET_ID_PERSON_CONTACT
RETURNS (ID INTEGER)
AS
BEGIN
ID = GEN_ID(GEN_HOW_TO_CONTACT_PERSON_ID_CONTACT, 1);
END;
GRANT EXECUTE ON PROCEDURE GET_ID_PERSON_CONTACT TO ACCOUNTANT, MANAGER;
CREATE GENERATOR GEN_PAYMENT_ID_PAYMENT;
SET GENERATOR GEN_PAYMENT_ID_PAYMENT TO 10;
CREATE PROCEDURE GET_ID_PAYMENT
RETURNS (ID INTEGER)
AS
BEGIN
ID = GEN_ID(GEN_PAYMENT_ID_PAYMENT, 1);
END;
GRANT EXECUTE ON PROCEDURE GET_ID_PAYMENT TO ACCOUNTANT, MANAGER;
CREATE GENERATOR GEN_SALE_ID_SALE;
SET GENERATOR GEN_SALE_ID_SALE TO 10;
CREATE PROCEDURE GET_ID_SALE
RETURNS (ID INTEGER)
AS
BEGIN
ID = GEN_ID(GEN_SALE_ID_SALE, 1);
END;
GRANT EXECUTE ON PROCEDURE GET_ID_SALE TO ACCOUNTANT, MANAGER;
CREATE GENERATOR GEN_ABLUTION_ID_ABLUTION;
SET GENERATOR GEN_ABLUTION_ID_ABLUTION TO 10;
CREATE PROCEDURE GET_ID_ABLUTION
RETURNS (ID INTEGER)
AS
BEGIN
ID = GEN_ID(GEN_ABLUTION_ID_ABLUTION, 1);
END;
GRANT EXECUTE ON PROCEDURE GET_ID_ABLUTION TO ACCOUNTANT, MANAGER;