Нетрудно найти онлайн-учебник по созданию базы данных. Нетрудно найти учебник о том, как создавать запросы. На самом деле, нетрудно найти учебники по синтаксису для SQL, различиям типов данных и даже какой базы данных лучше всего подходит для каких целей. Однако трудно найти хорошие учебники по теориям проектирования, разработки и ведения качественной базы данных.
Проектирование и управление базой данных не очень сложно. Люди намного мудрее, чем мы, разработали некоторые очень упорядоченные и разумные правила, которым нужно следовать, и развили эти правила в так называемый процесс нормализации .
Используя этот процесс, вы можете создавать совершенно новые, полностью функциональные, точно настроенные базы данных или использовать текущие таблицы базы данных, выполнить их через эти шаги и получить готовые к использованию хорошо смазанные таблицы. Как бы вы ни использовали эти шаги, они являются основой качественного проектирования баз данных.
Функциональная зависимость
Прежде чем мы перейдем к процессу нормализации, я должен сделать шаг назад и кое-что прояснить. Во-первых, это не относится к какой-либо одной базе данных. Это правила, которые должны соблюдаться при использовании любой системы баз данных, будь то Oracle, MySQL, PostgreSQL, SQL Server и т. Д.
Давайте сначала обсудим функциональную зависимость, которая имеет решающее значение для понимания процесса нормализации. Это просто большой термин для относительно простой идеи. Чтобы проиллюстрировать это, давайте взглянем на небольшой пример таблицы.
Номер торгового представителя | Класс оплаты | Темп |
001 | 1 | +0,05 |
002 | 1 | +0,05 |
003 | 1 | +0,05 |
004 | 2 | +0,07 |
005 | 1 | +0,05 |
006 | 3 | +0,09 |
Эта относительно простая таблица является хорошим примером функциональной зависимости, ее также можно использовать для иллюстрации сути.
Определение: столбец функционально зависит от другого столбца, если значение «A» определяет одно значение для «B» в любой момент времени.
Звук сбивает с толку? Позволь мне объяснить. Поле «Ставка» функционально зависит от поля «Класс оплаты». Другими словами, класс оплаты определяет ставку.
Чтобы определить функциональную зависимость, вы можете думать об этом так: учитывая значение для поля A, можете ли вы определить одно значение для B? Если B полагается на A, то говорят, что A функционально определяет B.
Взяв ту же таблицу, что и выше, добавим к ней.
имя | Номер торгового представителя | Класс оплаты | Темп |
подопечный | 001 | 1 | +0,05 |
Максим | 002 | 1 | +0,05 |
камыш | 003 | 1 | +0,05 |
Beechum | 004 | 2 | +0,07 |
Коллинз | 005 | 1 | +0,05 |
консервный завод | 006 | 3 | +0,09 |
Теперь давайте посмотрим на эту таблицу и найдем еще несколько функциональных зависимостей. Мы уже знаем, что класс оплаты определяет ставку. Можно также сказать, что номер торгового представителя определяет фамилию. Только один номер торгового представителя для каждой фамилии. Это соответствует определению функциональной зависимости.
Но Фамилия функционально определяет что-нибудь? На первый взгляд, некоторые люди могут сказать «да», однако это не так. В настоящее время вы можете сказать, что Ward предоставит вам только один номер торгового представителя, однако, что если мы наняли другого человека с именем Ward? Тогда у вас будет два значения для вашего торгового представителя, а затем фамилия больше не будет ничего функционально определять.
На ключи
Теперь, когда мы знаем, что такое функциональная зависимость, мы можем уточнить ключи. Теперь, если вы работаете в базах данных, вы, вероятно, уже знаете, что такое первичные ключи. Но вы можете определить их?
Определение: столбец A является первичным ключом для таблицы T, если:
Свойство 1. Все столбцы в T функционально зависят от A
Свойство 2. Никакие вложенные коллекции столбцов в таблице T также не имеют свойства 1.
Это имеет смысл. Если все ваши поля в базе данных зависят от одного и только одного поля, то это поле является ключевым. Теперь иногда свойство 2 нарушается, и два поля являются кандидатами на первичный ключ. Эти ключи затем называются ключами-кандидатами. Из этих ключей-кандидатов выбирается один ключ, а другие называются альтернативными ключами.
Например, в той же таблице, что и раньше:
имя | Номер торгового представителя | Класс оплаты | Темп |
подопечный | 001 | 1 | +0,05 |
Максим | 002 | 1 | +0,05 |
камыш | 003 | 1 | +0,05 |
Beechum | 004 | 2 | +0,07 |
Коллинз | 005 | 1 | +0,05 |
консервный завод | 006 | 3 | +0,09 |
Наш первичный ключ — номер торгового представителя, так как он соответствует определению первичного ключа. Все в таблице зависит от номера торгового представителя, и ничто другое не может претендовать на то же самое. Теперь давайте сделаем еще один шаг и предположим, что в таблице также указан номер социального страхования сотрудника.
имя | Номер торгового представителя | Класс оплаты | Темп | Soc.Sec. нет. |
подопечный | 001 | 1 | +0,05 | 133-45-6789 |
Максим | 002 | 1 | +0,05 | 122-46-6889 |
камыш | 003 | 1 | +0,05 | 123-45-6999 |
Beechum | 004 | 2 | +0,07 | 113-75-6889 |
Коллинз | 005 | 1 | +0,05 | 121-44-6789 |
консервный завод | 006 | 3 | +0,09 | 111-45-9339 |
Теперь у нас есть два ключа-кандидата, номер торгового представителя и номер социального страхования. Итак, мы должны решить, какое поле использовать, так как оба будут уникальными. В конце концов, было бы лучше иметь номер торгового представителя в качестве первичного ключа по различным причинам.
Первая нормальная форма
Теперь, когда мы прояснили эти понятия, давайте перейдем к процессу нормализации. Первая нормальная форма определяется как таблица, которая не содержит повторяющихся групп.
Например:
Номер заказа | Дата заказа | номер части | Заказанный номер |
5245 | 3/02/99 | 35436 | 23 |
5246 | 3/02/99 | 32116 | 11 |
5247 | 4/02/99 | 32133 | 52 |
— | — | 12311 | 10 |
5248 | 4/02/99 | 46563 | 1 |
Теперь из этого примера вы должны легко увидеть проблему. Во-первых, в этой настройке номер заказа считается первичным ключом, но это не совсем так. Истинный первичный ключ — это номер заказа и номер детали. В каждом заказе деталь будет заказана только один раз (хотя заказанная сумма может быть больше 1). Тем не менее, несколько частей могут быть заказаны в номер заказа. Итак, когда мы переоснащаем эту таблицу, мы получаем следующее:
Номер заказа | Дата заказа | номер части | Заказанный номер |
5245 | 3/02/99 | 35436 | 23 |
5246 | 3/02/99 | 32116 | 11 |
5247 | 4/02/99 | 32133 | 52 |
5247 | 4/02/99 | 12311 | 10 |
5248 | 4/02/99 | 46563 | 1 |
Это гораздо проще для понимания и намного лучше, чем в предыдущей таблице. И на этот раз первичный ключ — это и номер заказа, и номер детали, и все остальное в таблице зависит от этого ключа.
Это была Форма Первой Нормы, или 1NF. Большинство людей могут сделать это правильно, однако я видел некоторые таблицы, разработанные без учета этого, и какое-то время кажется, что все в порядке, но когда вы начинаете заполнять таблицу большим количеством информации, она может стать довольно громоздкий. Определенно, не блестящая точка в чьей-либо карьере, но действительно самый ценный урок.
Вторая нормальная форма
Во-первых, давайте просто скажем это. Таблица автоматически становится 2NF, если ее первичный ключ содержит только один столбец. Это было легко, не так ли? Но тогда, если ваш первичный ключ имеет более одного столбца, продолжайте читать.
Давайте прыгнем прямо в стол здесь. Основными ключами являются номер заказа (номер заказа) и номер детали (номер детали).
Порядок # | Дата заказа | Часть # | Часть Desc. | Заказанный номер | Цена |
5245 | 3/02/99 | 35465 | Ключ газовый | 1 | $ 10 |
5246 | 3/02/99 | 65466 | Шезлонге | 4 | $ 25 |
5246 | 3/02/99 | 65473 | Стол для пикника | 1 | $ 30 |
5247 | 3/02/99 | 44654 | Газонные Дартс | 1 | $ 45 |
5248 | 4/02/99 | 44665 | Волейбол | 3 | $ 20 |
На первый взгляд, все в порядке с этим столом. Однако есть некоторые проблемы, которые необходимо решить. Давайте сначала наметим функциональные зависимости.
Order Number -> Order Date
Part Number -> Part Description
Order Number, Part Number -> Number Ordered, Price, Order Date, Part Description
Как видите, это большой беспорядок, и о нем нужно позаботиться. На самом деле, есть и другие проблемы с этой таблицей.
Во-первых, изменение описания детали в этой таблице также будет означать изменение в других таблицах, например в таблице «Продукты». Это явно громоздко для кода, и неудобно для запуска.
Во-вторых, у вас могут быть разные описания для одной и той же части. Это просто не приемлемо в деловой среде.
Это связано с тем, что описание детали зависит только от части первичного ключа, а именно от номера детали. Поэтому описание части является неключевым атрибутом. Неключевой атрибут — это просто столбец, который не является частью первичного ключа.
Это относится конкретно к определению 2NF, которое представляет собой таблицу в 1NF, и ни один неключевой атрибут не зависит только от части первичного ключа. Это, конечно, подтверждает тот факт, что если таблица содержит только один столбец в своем первичном ключе, она находится во второй нормальной форме.
Итак, как мы решаем эту проблему? Ну, мы уже решили эту проблему выше. Вот три новые таблицы для приведенной выше, первая часть которой является первичными ключами, а вторая часть — другими полями таблицы.
Order Number -> Order Date
Part Number -> Part Description
Order Number, Part Number -> Number Ordered, Price
Это наши новые таблицы. Обратите внимание, что я вынул Дата заказа и Описание детали, так как нет необходимости использовать данные, которые уже хранятся в других таблицах. Также обратите внимание, что у вас есть только одно описание для каждой части. Качественный дизайн базы данных не нуждается в избыточных данных.
Третья нормальная форма
Итак, вы думаете, что ваш стол свободен сейчас. Вы думаете, что он готов к высшей лиге? Нет, не сейчас. 3NF готов принять новые вызовы. Давайте перейдем прямо к нашему примеру таблицы:
Покупатель # | имя | Адрес | кредит | Торговый представитель # | Имя торгового представителя |
2343 | боб | Ул. 2343 Ви | $ 1000 | 03 | Дейв |
2344 | Даниил | Вау 1230 | $ 3000 | 04 | Pam |
2345 | Кейт | 33 Сохо | $ 5000 | 03 | Дейв |
2346 | Меньше | 99 больше | $ 1000 | 07 | Garrett |
2347 | Дэн | 1 меньше св. | $ 500 | 09 | Питер |
2348 | Bruno | 45 Candy Ln. | $ 2000 | 03 | Дейв |
Теперь вы, вероятно, признаете несколько проблем, но будьте уверены, это 2NF. Каждое поле зависит от номера клиента. Например, с номером клиента 2345 будет связано только одно имя, адрес, кредит, номер торгового представителя и имя торгового представителя. Однако это не означает, что таблица готова к прайм-тайм.
Во-первых, нам нужно определить определитель как любой столбец или набор столбцов, которые определяют другой столбец. По этому определению и первичный ключ, или любой кандидатный ключ будут определителем. Кроме того, это сделает Sales Rep Number определяющим фактором, но это не ключ-кандидат или первичный ключ.
Итак, как это относится к 3NF? Итак, определение 3NF — это таблица, которая соответствует 2NF (и, конечно, 1NF), и если единственные определяющие элементы, которые она содержит, являются ключами-кандидатами. Это, конечно, включает в себя первичный ключ.
Итак, вы только что обнаружили проблему с таблицей: определителем номера торгового представителя. Так как же избавиться от этого?
Во-первых, отследите все детерминанты, которые НЕ являются ключом-кандидатом. Затем удалите все поля, которые зависят от этого определяющего ключа, но сохраните определяющий ключ в таблице. Затем, со всеми удаленными полями, поместите их в таблицу, первичным ключом которой будет определяющий ключ, который вы оставили в основной таблице. Итак, это будет означать нашу оригинальную таблицу:
Customer #, Name, Address, Credit, Sales Rep #, Sales Rep Name
Будет превращен в эти две таблицы:
Customer #, Name, Address, Credit, Sales Rep #
Sales Rep #, Sales Rep Name
Качество.
Помните, что эти две новые таблицы должны также соответствовать 1NF, 2NF и 3NF, поэтому проверьте их дважды, хотя, если вы до этого момента, у вас все будет хорошо.
Четвертая нормальная форма
Наконец, мы дошли до большого. 4NF является отцом форм, так как это все и конец всему. Это решает любую проблему, которая может возникнуть. Давайте начнем с определения очень важного термина, многозначной зависимости (MD). MD — это когда поле B мультизависимо от A, если каждое значение A связано с конкретным списком значений для B, и эта коллекция не зависит от каких-либо значений C.
Давайте сделаем глубокий вдох и проиллюстрируем это простым столом. Предположим, что преподавательский состав представляет собой консультанта для любого числа студентов, представленных номером студента. Кроме того, мы можем предположить, что преподавательский состав будет частью любого числа комитетов, и мы хотим сохранить это также. Итак, это то, что мы придумали.
факультет | Количество студентов | Кодекс комитета |
1243 | 2343 | ADV |
 | 2345 | PER |
 |  | HSG |
1553 | 3243 | ADV |
4003 | 3408 | HSG |
 | 4095 |  |
 | 4403 |  |
Теперь, передав это 1NF, вы получите такой результат:
факультет | Количество студентов | Кодекс комитета |
1243 | 2343 | ADV |
1243 | 2345 | PER |
1243 | 2345 | HSG |
1553 | 3243 | ADV |
4003 | 3408 | HSG |
4003 | 4095 | HSG |
4003 | 4403 | HSG |
Но вы также можете ясно видеть, что проблема развивается и там. Это то, что MD. Если факультет № 1243 больше не консультирует Студента № 2345, и мы удалили данные, то информация Комитета также будет удалена. Это не качество.
4NF соответствует 3NF, и многозначных зависимостей нет.
Вы бы справились с этой проблемой, как в 2NF и 3NF, разбив таблицу на более мелкие таблицы, каждая из которых содержит поле, которое их определяло, и в этом случае это будет поле Faculty. Итак, новые таблицы будут:
Faculty, Student Number
Faculty, Committee Code
Вывод
Действительно, это было много работы, но оно того стоит. Убедитесь, что ваши таблицы оптимизированы — это ключ к качественному дизайну. Забота о проблеме прежде, чем она станет проблемой, жизненно важна для управления базой данных.
Прежде чем приступить к разработке базы данных, соберите всю информацию, которую вы хотите включить в базу данных. Я имею в виду все. Обойдите все отделы компании (или просто напишите сами, если это только для вас) и выясните, что каждый хочет в базе данных. Как только у вас будет все, принесите его обратно и создайте один огромный стол.
Оттуда разбейте эту таблицу до 1NF, затем 2NF и так далее. Вернитесь к каждому столу и убедитесь, что все они работают вместе и являются таблицами 4NF. Если это не так, то можно быть уверенным, что в будущем у столов будут проблемы.
Качество в дизайне. И для тех, кто знает, это помогает соблюдать первые 2 правила Кодда для действительно реляционной системы баз данных.
Удачного кодирования.