Простой вопрос нормализации базы данных - PullRequest
2 голосов
/ 13 июня 2010

У меня есть быстрый вопрос относительно базы данных, которую я проектирую и проверяю, чтобы она нормализовалась ...

У меня есть таблица клиентов с первичным ключом customerId. Он имеет столбец StatusCode, который имеет код, который отражает статус учетной записи клиента, т.е. 1 = открыто, 2 = закрыто, 3 = приостановлено и т. Д. *

Теперь я хотел бы иметь еще одно поле в таблице клиентов, которое указывает, разрешено ли приостановление учетной записи или нет ... некоторые клиенты будут автоматически приостановлены, если они нарушат условия торговли ... другие нет ... поэтому соответствующие поля таблицы будут выглядеть так:

Клиенты (CustomerId (PK): StatusCode: IsSuspensionAllowed)

Теперь оба поля зависят от первичного ключа, так как вы не можете определить статус или разрешить приостановки для конкретного клиента, если вы не знаете конкретного клиента, за исключением, конечно, когда для поля IsSuspensionAllowed установлено значение YES, клиент никогда не должен иметь StatusCode 3 (Приостановлено).

Как видно из приведенного выше дизайна таблицы, это возможно, если в мою таблицу не добавлено контрольное ограничение. Я не вижу, как можно добавить еще одну таблицу в реляционный дизайн, чтобы реализовать это, поскольку это только в случае, когда IsSuspensionAllowed установлен в YES, а StatusCode установлен в 3, когда эти две имеют зависимость друг от друга.

Итак, после моего многословного объяснения мой вопрос таков: это проблема нормализации, и я не вижу реляционного дизайна, который будет обеспечивать это ... или это на самом деле просто бизнес-правило, которое следует применять с помощью проверки противоречие и таблица фактически все еще нормализована.

Приветствия,

Steve

1 Ответ

0 голосов
/ 13 июня 2010

Да, это возможно.Вы можете сделать это с помощью проверочного ограничения и оператора Case:

Create Table Customer   (
        CustomerId <datatype> not null Primary Key
        , StatusCode int not null
        , IsSuspensionAllowed int not null Default( 1 )
        , Constraint CK_Customer_IsSuspensionAllowed 
                    Check ( IsSuspensionAllowed In(0,1) )
        , Constraint CK_Customer_StatusCodeRange 
                    Check ( StatusCode Between 0 And ?? )
        , Constraint CK_Customer_StausCodeValid 
                    Check ( Case
                When StatusCode = 3 And IsSuspensionAllowed = 1 Then 0
                                                                Else 1
                                                                End = 1 )
        , ....
        )

Вы не упомянули тип данных PK, поэтому я просто вставил заполнитель.Если вы используете SQL Server, вы можете использовать битовый столбец вместо int и проверить ограничение, которое я упоминал выше (bit не является частью спецификации ANSI).

Это хороший примергде суррогатные ключи для таких вещей, как коды состояния, не всегда работают хорошо.Было бы лучше иметь строковые значения, представляющие коды состояния, в этом случае оператор Case будет читать When StatusCode = 'Suspended' And IsSuspendedAllowed = 0....

С точки зрения нормализации я не вижу ничего плохого.Допустимо ли приостановление - это атрибут, специфичный для Клиента, а не другой атрибут.То, что вы говорите с проверочным ограничением, что некоторые состояния значений атрибутов не могут существовать, и это нормально.

Кстати, не имеет смысла говорить, что статус «Приостановлено» не разрешен, когда IsSuspensionAllowed =0?Используя ваши данные, не должно ли государство, которое не разрешено, быть StatusCode = 3 and IsSuspensionAllowed = 0?

...