2009-07-17 1 views
1

http://weblogs.sqlteam.com/jeffs/archive/2008/08/13.aspx:Чтобы полностью Принудительно модель данных или не полностью Принудительно модель данных

Рассмотрим следующую логическую модель данных:
* Есть несколько компаний
* Каждая компания имеет много проектов
* Каждый проект имеет много задач
* Каждая задача имеет статус, выбранный из глобального списка предварительно определенных статусов.

Скажем, мы решили, что первичный ключ компаний, проектов, задач и состояния - это все столбцы Identity (auto-number), поскольку мы хотели бы автоматически генерировать первичные ключи для этих таблиц.

Так в основном, у нас есть 4 таблицы:
Статус (PK: StatusID)
компаний (PK: CompanyID)
Проекты (PK: ProjectID, FK: [Компании] .CompanyID)
Задачи (PK: TaskID, FK: [Projects] .ProjectID, [Status] .StatusID).

Теперь позвольте мне добавить одну маленькую морщинку. Предположим, что доступные статусы для каждой задачи не определены глобально, а на уровне Компании. То есть каждая компания имеет свой собственный список статусов, которым может быть назначена задача.

Это означает, что таблица состояния теперь нужен ключ иностранных ссылку на таблицу компаний (указать, какие каждая Статус компании принадлежит):

Компании (PK: CompanyID)
Статус (PK: StatusID, FK: [Компании] .CompanyID)
Проекты (PK: ProjectID, FK: [Компании] .CompanyID)
Задачи (PK: TaskID, FK: [Projects] .ProjectID, [Status] .StatusID).

Есть ли какие-либо другие изменения, которые нам необходимо внести в эту модель данных? Или просто добавьте столбец CompanyID в таблицу состояния, чтобы облегчить это изменение? Помните, что наша цель, как всегда, является полной ссылочной целостностью с использованием ограничений первичного и внешнего ключей, где это возможно.

Ну, есть вопрос:

Ничто в этой модели данных не останавливает нас от присвоения статуса к задаче, которая не определена для материнской компании этой задачи. У нас нет возможности применить это прямо сейчас с нашими текущими ограничениями. Наша физическая модель данных ошибочна.

Это очень легко фиксируется, но это может быть сделано только путем нарушения правила «все таблицы, требующие только первичного ключа идентификации».

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

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

компаний (PK: CompanyID)
Статус (PK: CompanyID, StatusID , FK: [Компании] .CompanyID)
Проекты (PK: CompanyID, ProjectID, FK: [Компании] .CompanyID)
Задачи (PK: TaskID, FK: [Projects]. (CompanyID, ProjectID), [Status] . (CompanyID, StatusID)).

Я давно поклонник полностью соблюдения/сдерживая свои модели данных, однако, часто я оказываюсь в ситуациях, подобных вышеупомянутому и я прихожу к перекрестку:

Чтобы полностью обеспечить соблюдение или не полностью обеспечивать соблюдение.

Очевидным препятствием для этого является, казалось бы, сложный дизайн.

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

Преимущества, недостатки и общие соображения по этому дизайну или полное соблюдение дизайна модели данных?

** Обратите внимание, что этот вопрос может породить дискуссию о том, где ответственность лежит в обеспечении соблюдения вашей модели данных (базы данных или приложения или обоих). Для обсуждения я считаю, что ваша модель данных должна обеспечивать себя в жизнь - ответьте на это по презумпции. **

+0

Приложение И уровень базы данных должен обеспечивать соблюдение правил модели данных. Это облегчает поиск ошибок в том, что правила * должны быть подкреплены другим. –

+0

Исходная статья имеет ошибку нормализации (как указывал OrbMan); оставит комментарий автору, но не увидит опцию комментариев –

ответ

2

Я бы создал таблицу CompanyStatus, которая является многого между Company и Status и описывает, какие статусы применимы к данной компании. Затем задания присваиваются CompanyStatusID, а не StatusID.

Это также предотвращает появление дублированных статусов в вашей Status таблицы - многие компании могут совместно использовать один и тот же Закрытого статус, например, что лучше нормализации.

Таким образом, вам не нужно использовать составные клавиши для правильного применения ограничений. Я предпочитаю использовать одиночные первичные ключи автоинкремента, которые не имеют смысла (суррогатные ключи). Это более устойчиво, чем предположение о том, что ключ будет уникальным (например, SSN), когда всегда есть вероятность, что это окажется не так, но вы все равно должны хранить данные, поскольку приложение требует его (так уникальное ограничение здесь не помогает).

+0

, это правильный/нормализованный дизайн, а не тот, который указан в вопросе, хотя использование StatusId в таблице Task будет в порядке, если не лучше (CompanyStatus только что используется для фильтрации начального присвоение) –

+0

Я бы не делал то же самое с проектами, если более одного предприятия могут быть связаны с одним и тем же Проектом, и я не получил этого от требований. Я понимаю основную предпосылку, что вы можете использовать составные ключи для лучшей целостности, чем вы можете получить с суррогатами.Это нужно учитывать при разработке вашей модели; лично, мне еще предстоит найти случай, когда я решил пойти по этому пути - я подозреваю, что у меня будет больше шансов получить ошибки от опечаток длинных составных клавиш в моих запросах, чем я могу получить через потерю ограничений, которые могут дать вам ключи с суррогатом. – RedFilter

+0

Добавление таблицы CompanyStatus позволит вам иметь задачу с проектом из одной компании и статусом другой компании. Кроме того, я считаю, что я действительно думаю о лучших практиках с точки зрения полного применения вашей модели данных. –