4.6. Процедура нормализации
Как уже говорилось, нормализация – это разбиение таблицы на несколько, обладающих лучшими свойствами при обновлении, включении и удалении данных. Теперь можно дать и другое определение: нормализация – это процесс последовательной замены таблицы ее полными декомпозициями до тех пор, пока все они не будут находиться в 5НФ. На практике же достаточно привести таблицы к НФБК и с большой гарантией считать, что они находятся в 5НФ. Разумеется, этот факт нуждается в проверке, однако пока не существует эффективного алгоритма такой проверки. Поэтому остановимся лишь на процедуре приведения таблиц к НФБК.
Эта процедура основывается на том, что единственными функциональными зависимостями в любой таблице должны бытьзависимости вида K->F, где K – первичный ключ, а F – некоторое другое поле. Заметим, что это следует из определения первичного ключа таблицы, в соответствии скоторым K->F всегда имеет место для всех полей данной таблицы. "Один факт в одном месте" говорит о том, что не имеют силы никакие другие функциональные зависимости. Цель нормализации состоит именно в том, чтобы избавиться от всех этих "других" функциональных зависимостей, т.е. таких, которые имеют иной вид, чемK->F.
Если воспользоваться рекомендацией п. 4.5 и подменить на время нормализации коды первичных (внешних) ключей на исходные ключи, то, по существу, следует рассмотреть лишь два случая:
1. Таблица имеет составной первичный ключ вида, скажем, (К1,К2), и включает также поле F, которое функционально зависит от части этого ключа, например, от К2, но не от полного ключа. В этом случае рекомендуется сформировать другую таблицу, содержащую К2 и F (первичный ключ – К2), и удалить F из первоначальной таблицы:
Заменить T(K1,K2,F), первичный ключ (К1,К2), ФЗК2->F
на T1(K1,K2), первичный ключ (К1,К2),
и T2(K2,F), первичный ключ К2.
2. Таблица имеет первичный (возможный) ключ К, не являющееся возможным ключом поле F1, которое, конечно, функционально зависит от К, и другое неключевое поле F2, которое функционально зависит от F1. Решение здесь, по существу, то же самое, что и прежде – формируется другая таблица, содержащая F1 и F2, с первичным ключом F1, и F2 удаляется из первоначальной таблицы:
Заменить T(K,F1,F2), первичный ключ К, ФЗF1->F2
на T1(K,F1), первичный ключ К,
и T2(F1,F2), первичный ключ F1.
Для любой заданной таблицы, повторяя применение двух рассмотренных правил, почти во всех практических ситуациях можно получить в конечном счете множество таблиц, которые находятся в "окончательной" нормальной форме и, таким образом, не содержат каких-либо функциональных зависимостей вида, отличного отK->F.
Для выполнения этих операций необходимо первоначально иметь в качестве входных данных какие-либо "большие" таблицы (например, универсальные отношения). Но нормализация ничего не говорит о том, как получить эти большие таблицы. В следующей главе будет рассмотрена процедура получения таких исходных таблиц, а здесь приведем примеры нормализации.
Пример 4.1.
Применим рассмотренные правила для полной нормализации универсального отношения "Питание" (рис. 4.2).
Шаг 1. Определение первичного ключа таблицы.
Предположим, что каждое блюдо имеет уникальное название, относится к единственному виду и приготавливается по единственному рецепту, т.е. название блюда однозначно определяет его вид и рецепт. Предположим также, что название организации поставщика уникально для того города, в котором он расположен, и названия городов уникальны для каждой из стран, т.е. название поставщика и город однозначно определяют этого поставщика, а город – страну его нахождения. Наконец, предположим, что поставщик может осуществлять в один и тот же день только одну поставку каждого продукта, т.е. название продукта, название организации поставщика, город и дата поставки однозначно определяют вес и цену поставленного продукта. Тогда в качестве первичного ключа отношения "Питание" можно использовать следующий набор атрибутов:
Блюдо, Дата_Р, Продукт, Поставщик, Город, Дата_П.
Шаг 2. Выявление полей, функционально зависящих от части состваного ключа.
Поле Вид функционально зависит только от поля Блюдо, т.е.
Блюдо->Вид.
Аналогичным образом можно получить зависимости:
Блюдо->Рецепт
(Блюдо, Дата_Р)->ПорцийПродукт->Калорийность
(Блюдо,Продукт)->Вес
Город->Страна (Поставщик, Город,Дата_П)->Цена
Шаг 3. Формирование новых таблиц.
Полученные функциональные зависимости опредляют состав таблиц, которые можно сформировать из данных универсального отношения:
Блюда (Блюдо, Вид)
Рецепты (Блюдо, Рецепт)
Расход (Блюдо, Дата_Р, Порций)
Продукты (Продукт, Калорийность)
Состав (Блюдо, Продукт, Вес (г))
Города (Город, Страна)
Поставки (Поставщик, Город, Дата_П, Вес (кг), Цена).
Шаг 4. Корректировка исходной таблицы.
После выделения из состава универсального отношения указанных выше таблиц, там остались лишь сведения о поставщиках, для хранения которых целесообразно создать таблицу
Поставщики (Поставщик, Город),
т.е. использовать часть исходного первичного ключа, так как остальные его части уже ничего не определяют.
Таким образом, процедура последовательной нормализации позволила получить проект, лучший, чем приведен на рис. 4.3.
Пример 4.2.
Для улучшения проекта, приведенного на рис. 4.4, нужно определить первичные ключи таблиц и выявить, нет ли в таблицах полей, зависящих лишь от части этих ключей. Такое поле есть только в одной таблице. Это поле Страна в таблице Поставщики. Выделяя его вместе с ключем Город в таблицу Страны, получим проект, приведенный на рис. 3.2.
Содержание