http://weblogs.sqlteam.com/jeffs/archive/2008/08/13.aspx:
Рассмотрим следующую логическую модель данных:
* Есть несколько компаний
* У каждой компании есть много проектов
* У каждого проекта много задач
* Каждая задача имеет статус, выбранный из глобального списка предварительно определенных статусов.
Допустим, мы решили, что первичным ключом компаний, проектов, задач и статуса являются все столбцы Identity (auto-number), поскольку мы хотели бы автоматически генерировать первичные ключи для этих таблиц.
Итак, в основном у нас есть 4 таблицы:
Статус (PK: StatusID)
Компании (PK: CompanyID)
Проекты (ПК: ProjectID, FK: [Компании] .CompanyID)
Задачи (ПК: TaskID, FK: [Проекты] .ProjectID, [Статус] .StatusID).
Теперь позвольте мне добавить одну маленькую морщинку. Предположим, что доступные Статусы для каждой Задачи определены не глобально, а на уровне Компании. То есть каждая компания имеет свой собственный список статусов, которым может быть назначено задание.
Это означает, что для таблицы состояния теперь требуется ссылка внешнего ключа на таблицу компаний (чтобы указать, к какой компании принадлежит каждый статус):
Компании (PK: CompanyID)
Статус (PK: StatusID, FK: [Companies] .CompanyID)
Проекты (ПК: ProjectID, FK: [Компании] .CompanyID)
Задачи (ПК: TaskID, FK: [Проекты] .ProjectID, [Статус] .StatusID).
Есть ли какие-либо другие изменения, которые мы должны внести в эту модель данных? Или достаточно просто добавить столбец CompanyID в таблицу Status, чтобы облегчить это изменение? Помните, что нашей целью, как всегда, является полная ссылочная целостность с использованием ограничений первичного и внешнего ключей, где это возможно.
Ну, есть проблема:
Ничто в этой модели данных не мешает нам присвоить статус Задаче, которая не определена для компании-учредителя этой Задачи. У нас нет способа обеспечить это прямо сейчас с нашими нынешними ограничениями. Наша физическая модель данных имеет недостатки.
Это очень легко исправить, но это можно сделать, только нарушив правило "всем таблицам нужен только первичный ключ идентификации".
Во-первых, запомните: только то, что столбец идентификаторов является уникальным, не означает, что этот столбец не может быть частью первичного ключа.
Далее он указывает, как составные ключи можно использовать для полного применения и ограничения вашей модели данных примерно так:
Компании (PK: CompanyID)
Статус (PK: CompanyID, StatusID, FK: [Companies] .CompanyID)
Проекты (ПК: CompanyID, ProjectID, FK: [Companies] .CompanyID)
Задачи (ПК: TaskID, FK: [Проекты]. (CompanyID, ProjectID), [Status]. (CompanyID, StatusID)).
Я давно являюсь поклонником полного применения / ограничения моих моделей данных, однако, часто я оказываюсь в ситуациях, подобных вышеупомянутым, и я нахожусь на перекрестке:
Для обеспечения полного или не полного применения.
Очевидным недостатком этого является, казалось бы, слишком сложный дизайн.
Теперь я знаю, что не обязательно «правильный» дизайн, но для подобных ситуаций ... Я ищу отзывы с точки зрения лучших практик.
Преимущества, недостатки и общие соображения по поводу этого дизайна или полного обеспечения реализации вашей модели данных?
** Обратите внимание, что этот вопрос может породить дискуссию о том, где лежат обязанности с точки зрения обеспечения соблюдения вашей модели данных (базы данных или приложения или обоих). Ради обсуждения, я считаю, что ваша модель данных должна обеспечивать себя - пожалуйста, ответьте в соответствии с этим предположением. **