Один из способов выразить 3NF:
Все атрибуты должны зависеть от ключа, всего ключа и только от ключа.
Транзитивная зависимость X-> Y-> Z нарушает этот принцип, приводя к избыточности данных и потенциальным аномалиям модификации.
Разобьем это:
- По определению для того, чтобы функциональная зависимость X-> Y-> Z также была транзитивной , X <-Y должен <strong>не удерживаться.
- Если бы Y был ключом, то X <-Y удерживал бы, поэтому Y не может быть ключом.<em> (FOOTNOTE1)
- Поскольку Y не является ключом, любой заданный Y может повторяться в нескольких строках.
- Y-> Z подразумевает, что все строки, содержащие одинаковыеY также должна содержать один и тот же Z. (FOOTNOTE2)
- Повторение одинакового одинакового (Y, Z) кортежа в нескольких строках не дает никакой полезной информации системе,Это избыточно .
Короче говоря, поскольку Y не является ключом, а Y-> Z, мы нарушили 3NF.
Избыточности приводят к модификациианомалии (например, обновление некоторых , но не всех Zs, «подключенных» к одному и тому же Y, по существу повреждает данные, поскольку вы больше не знаете, какая копия является правильной).Обычно это решается разделением исходной таблицы на две таблицы, одна из которых содержит {X, Y}, а другая - {Y, Z}. Таким образом, Y может быть ключом во второй таблице, а Z не повторяется.
С другой стороны, если X <-Y действительно удерживается (то есть X-> Y-> Z не является транзитивным), то мы можем сохранить одну таблицу, где X и Y являются ключами.В этом сценарии Z не будет излишне повторяться.
(FOOTNOTE1) Ключ - это (минимальный) набор атрибутов, которые функционально определяют все атрибуты в отношении.Обоснование: если K является ключом, не может быть нескольких строк с одинаковым значением K, поэтому любое заданное значение K всегда связано точно с одним значением каждого другого атрибута (при условии 1NF).По определению (см. FOOTNOTE2) «быть связанным именно с одним» означает то же самое, что и «быть в функциональной зависимости».
(FOOTNOTE2) По определению , Y-> Z тогда и только тогда, когда каждое значение Y связано только с одним значением Z.
Пример:
Предполагая каждоесообщение имеет ровно одного автора, и каждый автор имеет ровно один основной адрес электронной почты, попытка представить сообщения и пользователей в одной таблице приведет к повторению сообщений электронной почты:
MESSAGE USER EMAIL
------- ---- -----
Hello. Jon jon@gmail.com
Hi, how are you? Rob rob@gmail.com
Doing fine, thanks for asking. Jon jon@gmail.com
(На самом деле,это будет MESSAGE_ID
с, но давайте здесь все упростим.)
Теперь, что произойдет, если Джон решит сменить свою электронную почту, скажем, на "jon2@gmail.com"?Нам нужно обновить обе строки Джона.Если мы обновим только один, то у нас будет следующая ситуация ...
MESSAGE USER EMAIL
------- ---- -----
Hello. Jon jon2@gmail.com
Hi, how are you? Rob rob@gmail.com
Doing fine, thanks for asking. Jon jon@gmail.com
... и мы больше не будем знать, какой из писем Джона является правильным.Мы по существу потеряли данные!
Ситуация особенно плоха, поскольку нет декларативного ограничения, которое мы могли бы использовать, чтобы принудить СУБД к выполнению обоих обновлений для нас.Клиентский код будет содержать ошибки и, вероятно, написан без особого учета сложных взаимодействий, которые могут происходить в параллельной среде.
Однако, если вы разделите таблицу ...
MESSAGE USER
------- ----
Hello. Jon
Hi, how are you? Rob
Doing fine, thanks for asking. Jon
USER EMAIL
---- -----
Jon jon@gmail.com
Rob rob@gmail.com
... теперь есть только одна строка, которая знает об электронной почте Джона, поэтому двусмысленность невозможна.
Кстати, все это можно рассматривать как еще одно выражение DRYпринцип .