Это отказ 1NF? - PullRequest
       7

Это отказ 1NF?

6 голосов
/ 31 декабря 2011

При рассмотрении отказа 1NF, нет повторяющихся групп элементов, что если вы хотите установить ограничение на количество повторяющихся групп?

Например, вы хотите, чтобы у ученика было только 3 телефонных номера.Больше не надо.Будет ли иметь следующую таблицу считаться ошибкой 1NF?

Student 1    Phone1    Phone2    Phone3
Sally        111-1111 222-2222   333-3333
John         555-5555 999-9999   NULL

Вы будете создавать лимит.Это приемлемый, эффективный дизайн базы данных?

Было бы лучше поместить телефонные номера в отдельную таблицу, так как вызовы 1NF требуют?Как бы вы создали ограничение в 3 номера на пользователя, если бы оно было в отдельной таблице?

Ответы [ 5 ]

7 голосов
/ 31 декабря 2011

Нет, это не нормализовано. Вы будете тратить впустую пространство в своей таблице, когда есть нулевые значения, и если вы хотите сделать такие вещи, как поиск определенного номера телефона, вам придется искать во всех трех столбцах. Вместо этого используйте отдельную таблицу (например, StudentPhoneNumbers), в которой они хранятся. Если вы хотите ограничить его тремя, используйте триггер, чтобы предотвратить более трех на каждого учащегося.

6 голосов
/ 31 декабря 2011

1NF запрещает повторять списки подряд. Ваш дизайн нарушает это, как и следующий дизайн:

Student     Phones
'John D'    '555-5555, 666-6666, 777-7777'
'Sally S'   '111-1111, 222-2222'

Следующая схема будет нарушать 2NF, поскольку единственным первичным ключом является Name, Phone, но атрибут Address не зависит от Phone:

Name        Phone       Address
'John D'    '555-5555'  '1 Square Village'
'John D'    '666-6666'  '1 Square Village'
'John D'    '777-7777'  '1 Square Village'
'Sally S'   '111-1111'  '999 Flash City'
'Sally S'   '222-2222'  '999 Flash City'

Следующий дизайн нарушит 3NF, поскольку AreaName не зависит от Name, а только от Area:

Name        Area    Phone   AreaName
'John D'    '555'   '5555'  '111name'
'John D'    '666'   '6666'  '666name'
'John D'    '777'   '7777'  '777name'
'Sally S'   '111'   '1111'  '111name'
'Sally S'   '222'   '2222'  '222name'

Даже если ваш дизайн нарушает 1NF, это отличный выбор. Сложность добавления таблицы PhoneNumber вряд ли когда-либо оправдана.

Подумайте о том, насколько сложным становится обновление для клиента, если вы соответствуете 1NF. Номера будут в отдельной таблице. Так что, если кто-то отправит форму с обновленным списком телефонных номеров, как бы вы изменили базу данных? Сначала вам нужно получить существующий список номеров. Затем вам нужно сравнить их с представленным списком. Тогда вам придется удалить или вставить строки на основе разницы. Один черт сложного решения.

Если вы придерживаетесь своего решения, вы можете просто обновить три столбца. Сэкономленное время можно потратить на реальные возможности! Или даже писать длинные ответы о переполнении стека.

3 голосов
/ 03 января 2012

Ваша переменная отношения (relvar) действительно нарушает 1NF, но, возможно, не по той причине, которую вы ожидаете: именно наличие нулевого значения нарушает 1NF. Если вы думаете, что ваш relvar содержит повторяющуюся группу, подумайте еще раз.

Первая нормальная форма, или просто «нормализованная», является минимальным требованием для реляционной модели. Цитировать Крис Дата:

по определению, ноль не является значением. Отсюда следует: «тип», который содержит значение null не является типом (поскольку типы содержат значения); «Кортеж» который содержит ноль, не является кортежем (потому что кортежи содержат значения); «отношение», содержащее нуль, не является отношением (потому что отношения содержат кортежи, а кортежи не содержат нулей). На самом деле, нули нарушать самый фундаментальный принцип отношения всех - а именно, Принцип информации. Суть всего этого в том, что если нули настоящее, тогда мы, конечно, не говорим о реляционной модели (Я не знаю, о чем мы говорим, но это не модель); все здание рушится, и все ставки сняты.

Вопрос о повторяющихся группах и 1NF сложно объяснить, и я не буду пытаться. Вместо этого я призываю вас прочитать Факты и заблуждения о первой нормальной форме , в частности, раздел «Неоднозначность повторяющихся групп».

Предполагая, что нулевое значение было исключено, relvar будет удовлетворять 1NF, но учтите, что нам потребуется дополнительная информация (например, ключи), чтобы определить, будет ли оно также удовлетворять более высоким нормальным формам.

1 голос
/ 04 января 2012

Как бы вы создали ограничение в 3 номера на пользователя, если бы оно было в отдельной таблице?

Я предполагаю, что у студента может быть ноль, один, два или три телефонных номера.

Если ваш продукт SQL поддерживает Full SQL-92:

CREATE TABLE Students
(
 student_name VARCHAR(20) NOT NULL UNIQUE
);

CREATE TABLE StudentPhonebook
(
 student_name VARCHAR(20) NOT NULL
    REFERENCES Students (student_name), 
 phone_number CHAR(8) NOT NULL
    CHECK (phone_number LIKE '[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]'), 
 UNIQUE (student_name, phone_number)
);

CREATE ASSERTION students_max_three_phone_numbers
   CHECK (
          NOT EXISTS (
                      SELECT *
                        FROM (
                              SELECT student_name, COUNT(*) AS tally
                                FROM StudentPhonebook
                               GROUP 
                                  BY student_name
                             ) AS DT1
                       WHERE tally > 3
                     )
         );

MySQL не поддерживает CHECK любого вида, и ни один продукт SQL не поддерживает CREATE ASSERTION, поэтому вышеприведенные ограничения должны быть написаны с использованиемпроцедурный код, например, триггеры.

Из интереса, если ваш продукт SQL поддерживает ограничения на уровне строк CHECK (как это делают большинство), можно использовать атрибут occurrence с ограничением BETWEEN 1 AND 3, затем включить этоатрибут в ключевом ограничении, например

CREATE TABLE StudentPhonebook
(
 student_name VARCHAR(20) NOT NULL
    REFERENCES Students (student_name), 
 phone_number CHAR(8) NOT NULL
    CHECK (phone_number LIKE '[0-9][0-9][0-9]-[0-9][0-9][0-9][0-9]'), 
 occurrence INTEGER DEFAULT 1 NOT NULL
    CHECK (occurrence BETWEEN 1 AND 3), 
 UNIQUE (student_name, phone_number), 
 UNIQUE (student_name, occurrence)
);
1 голос
/ 31 декабря 2011

user1122200, давайте предположим, что ваш дизайн базы данных растет.И вам необходимо назначить определенные данные каждому номеру телефона (например, местоположение телефона: «дом», «работа», ...).В этом случае вам будет нужен телефонный столик.Кроме того, предположим, что вам нужно найти студентов по номеру телефона (например, в пиццерии или такси, когда кто-то звонит), это более простой запрос в хорошо нормализованном дизайне, чем этот запрос:

select *
from students
where 
  Phone1 = '91112223' or
  Phone2 = '91112223' or
  Phone3 = '91112223'
...