Правильная структура данных для поддержания отношений один-ко-многим - PullRequest
4 голосов
/ 03 сентября 2010

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

Например, допустим, у меня есть базовая таблица для документов ...

TABLE docs (
    ID
    title
    content
)

Теперь, допустим, у меня есть подмножество документов, которые могут принадлежать пользователю и которые могут иметьдополнительная информация, связанная с ними.Я мог бы сделать следующее ...

TABLE docs (
    ID
    userID -> users(ID)
    title
    content
    additionalInfo
)

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

TABLE ownedDocs (
    docID -> docs(ID)
    userID -> users(ID)
    additionalInfo
)

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

Заранее спасибо за помощь

Ответы [ 3 ]

3 голосов
/ 03 сентября 2010

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

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

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

2 голосов
/ 03 сентября 2010

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

Если вы сделаете OwnedDocs.DocId первичным ключом, будет совершенно ясно, что отношение 1: N невозможно.

Моделирование отношений ноль или один к одному является сложным делом. Если у нас есть только один подтип, то разумно использовать одну таблицу со столбцами NULL. Однако эффективная практика заключается в том, чтобы атрибуты подтипов заполнялись только тогда, когда это необходимо. В данном примере это будет означать проверочное ограничение для применения этого правила:

check (userID is not null or AdditionalInfo is null)

Или, может быть, даже это правило:

check ( (userID is not null and AdditionalInfo is not null)
        or (userID is null and AdditionalInfo is null) )

Связь между атрибутами не будет отображаться в ERD (если вы не используете соглашение об именах). Конечно, обязательный характер AdditionalInfo для принадлежащих документов не будет очевиден во втором случае.

Когда у нас есть несколько таких подтипов, случай для отдельных таблиц становится убедительным, особенно если подтипы составляют дугу, например, Документом может быть FinancialDocument, MedicalDocument или PersonnelDocument, но не более одной категории. Однажды я реализовал такую ​​модель, используя одну таблицу с множеством пустых столбцов, представлений и проверочных ограничений. Это было ужасно. Таблицы подтипов - это определенно правильный путь.

1 голос
/ 03 сентября 2010

Это зависит от уровня нормализации , который вы хотите достичь.Как правило, основываясь на описании, которое вы предоставляете, я бы структурировал свою БД следующим образом:

table docs (id, title, content);
table users (id, ...);
table users_docs (doc_id, user_id);
table doc_info(doc_id, additional_info);

Кто-то исправит меня, если я ошибаюсь, но это должна быть третья нормальная форма.Это делает структуру красивой и чистой и использует только биты, необходимые для хранения данных, как и ожидалось.Вы можете хранить все элементы независимо, но связанные, где это необходимо.

В зависимости от характера дополнительной информации, вам необходимо внести некоторые изменения.Например, будет ли дополнительная информация ВСЕГДА соответствовать пользователю?Будет ли он всегда предоставлен, если документ связан с пользователем?Если это так, то вы можете добавить его в таблицу users_docs.Но это должно как минимум показать нормализацию.

...