Рассмотрим простой пример базы данных платежных поручений. Именно платежные поручения были взяты мной, т.к. это достаточно короткий пример, чтобы можно было не расплываться по древу во время повествования, здесь можно показать на примере все нормальные формы таблицы, можно показать основные принципы работы в Delphi при создании программ баз данных.
Вот как может выглядеть таблица с платежными поручениями в первой нормальной форме:
S короткое целое;
I целое число;
F дробное число;
D дата;
B BLOB массив, например текст.
Таблица в первой нормальной форме, но у нас многие значения в строке с платежкой будут повторяться. Давайте приведем ее ко второй нормальной форме. Сразу договоримся не включать в рассмотрение поля, начиная с вида оплаты и ниже. Почему? Далее я поясню, что бывают исключения из правил. Как говориться нормализуй, но не переусердствуй!
Таблица находится во второй нормальной форме (2НФ), если она удовлетворяет определению 1НФ и все ее поля, не входящие в первичный ключ, связаны полной функциональной зависимостью с первичным ключом.
Информацию о плательщике и получателе вынесем в отдельную таблицу организаций, т.к. структура этой информации одинакова. Сразу договоримся, что будем использовать для связи таблиц суррогатные ключи на основе последовательности целых чисел.
Как будто все хорошо. Мы можем указать в списке платежек код плательщика и код получателя, но теперь справочник организаций не удовлетворяет второй нормальной форме. Приведем ко второй нормальной форме справочник организаций. Для этого выделим информацию о банках в справочник банков. Опять используем суррогатный ключ.
Итак, вроде бы, все таблицы во второй нормальной форме. Посмотрим, что можно сделать дальше.
Таблица находится в третьей нормальной форме (3НФ), если она удовлетворяет определению 2НФ и не одно из ее не ключевых полей не зависит функционально от любого другого не ключевого поля.
Для начала запишем наши определения таблиц в виде, более приближенном к тому, с чем имеет дело программист.
Заметьте, что я изменил размеры полей некоторых таблиц и добавил несколько новых полей в таблицы. Увеличение длины строкового поля продиктовано стремлением к возможности подстраиваться к новым условиям при изменении отчетности. Так уже несколько раз было. На моей памяти уже три раза за два года. Поля OKONH и OKPO добавлены как информационные. Они ни как не участвуют в процессе создания платежки, но почему бы ни хранить их в справочниках, ведь платежка √ это оплата по договору или по накладной, а для их составления неплохо знать ОКОНХ и ОКПО организации. В справочник банков было добавлено еще три корсчета. Это связано с тем, что валютный платеж проходит не напрямую из банка в банк, а через несколько посредников. В таком случае, нужно внести в наименование банка все наименования посредников и напечатать их корреспондентские счета. Это несколько неправильно с точки зрения нормализации, но сравним плату за нормализацию с потерями от ненормальной формы. При соблюдении нормальной формы, нам потребуется создать новую таблицу с корреспондентскими счетами банка, и указывать их все для создания валютной платежки, т.е. хранить эту информацию в списке платежек. Это увеличит потребность в системных ресурсах. Т.к. банков будет явно меньше, чем платежек, то оставив лишних три поля в таблице справочника банков, мы наоборот сэкономим системные ресурсы, тем более, что можно объявить поля как VARCHAR(25). Эти же рассуждения справедливы и для полей Opl_Type, Nazn_Type, Kod_Type, Och_Type. Выделив их в отдельную таблицу, мы только усложним структуру базы данных, а эта плата неприемлемо высока.
Теперь, обратим внимание на справочник организаций. Здесь поле с расчетным счетом в банке зависит от кода банка. Это значит, что нужно перевести таблицу в третью форму нормализации. Выделим код банка и расчетный счет в отдельную таблицу.
Опять используем суррогатный первичный ключ. Связь таблиц организации и ее реквизитов организуем по внешнему ключу ID_Company. Обратите внимание, что формально соблюдая законы нормализации, мы получили более правильное представление об организации. Добиваясь третьей нормальной формы, мы пришли к тому, что организация может иметь несколько счетов в одном банке или в нескольких банках, что, вообще-то говоря, соответствует реальному положению дел. Поле ID_Rec оставлено в справочнике организаций, чтобы при создании новой платежки, автоматически выбирались реквизиты по умолчанию. Теперь, нам нужно пересмотреть список платежек, т.к. в этой таблице нет информации о реквизитах организации.
Полной декомпозицией таблицы называют такую совокупность произвольного числа ее проекций, соединение которых полностью совпадает с содержимым таблицы.
Обратите внимание, что на каком-то этапе, мы потеряли часть данных в списке платежек, но впоследствии восстановили правильное представление, так вот, мы добились полной декомпозиции. Как правило, при переводе таблицы в третью нормальную форму при соблюдении полной декомпозиции, мы получаем пятую нормальную форму автоматически.
Таблица находится в пятой нормальной форме (5НФ) тогда и только тогда, когда в каждой ее полной декомпозиции все проекции содержат возможный ключ. Таблица, не имеющая ни одной полной декомпозиции, также находится в 5НФ.
Обратите внимание на то, что поля ID_Plat, ID_Rec_Plat, ID_Pol, ID_Rec_Pol связывают список платежек со справочниками по первичному ключу, а это и есть пятая нормальная форма. На этом можно было бы остановиться, но я думаю, что пользователю неудобно выбирать плательщика и получателя из справочника организаций, т.к. справочник организаций √ это и плательщики, и получатели вместе. База данных с организациями, возможно, будет использоваться как справочник и в других программах, поэтому, там могут появиться и другие организации, которые не имеют никакого отношения к получателям и плательщикам. Эти рассуждения подвигают нас к тому, чтобы создать еще две таблицы с плательщиками и получателями. В этих таблицах будут храниться только коды плательщиков и получателей соответственно.
На этом, мы закончим. Я думаю, что старт дан, а более подробно Вы познакомитесь с методами проектирования конкретных баз данных из специальной литературы. Не забудьте, что клиент серверная архитектура подразумевает исполнение работы с данными, в основном, на стороне сервера, а поэтому мой пример неполон. Здесь нет триггеров и процедур для работы с данными, что очень важно.