Дизайн базы данных: циклические ссылки - PullRequest
3 голосов
/ 08 апреля 2010

У меня есть три таблицы базы данных:

  • Пользователи
  • электронная почта
  • приглашения

Письма связаны с пользователями в поле user_id.

Приглашения также связаны с пользователями полем user_id

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

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

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

Это плохой дизайн, и если да, то как я могу его улучшить?

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

users
-----
id

emails
------
id
users_id

invitations
-----------
id
users_id
emails_id

Ответы [ 5 ]

2 голосов
/ 08 апреля 2010

Это не круговая ссылка .

Было бы, если бы электронные письма имели тесную связь целостности с приглашениями, а приглашения - независимые отношения сильной целостности обратно к электронным письмам (например).

РЕДАКТИРОВАТЬ: в отношении дизайна

Как отмечает Хенк Холтерман, вопрос в том, является ли ваш дизайн нормализованным в желаемой степени.

Ассимиляция таблиц: первичные ключи , такие как

пользователи: id
электронные письма: id, users_id
приглашения: id, users_id, emails_id

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

  • для каждого пользователя может быть несколько электронных писем, и вы не можете иметь электронные письма без соответствующей записи пользователя
  • для каждого электронного письма может быть несколько приглашений, и у вас не может быть приглашений без соответствующей электронной почты или записи пользователя (примечание: из приведенного выше определения мы не можем знать, относится ли user_id к записи в электронных письмах или в пользователях)

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

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

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

В противном случае может существовать приглашение, для которого user_id, записанный в приглашении, и user_id, записанный для почты, различаются.

Обычно, это должно заставить вас вспыхнуть красным светом с надписью «нормализуйте ваши данные». Но часто негласное предположение здесь состоит в том, что email_id определяет user_id, и это может быть неверно (!).

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

1 голос
/ 06 декабря 2011

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

Это сбивает с толку и не нужно.

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

Если это так, то просто удалите user_id из таблицы приглашений,это бесполезно.

1 голос
/ 08 апреля 2010

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

Может быть больше 1 invitation на email?Если нет, то ваш дизайн уже неправильный.

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

Неясно (для меня), относится ли user_id в invitation к одному и тому же пользователюuser_id в email.Если это так, то это избыточно и является денормализацией.Удалите его и используйте email в качестве таблицы ссылок, чтобы вернуться к user_id.Если вам это требуется для производительности или чего-то подобного, создайте unique constraint через email.(id, user_id) (уже уникальный, поскольку id - ваш первичный ключ) и внешний ключ для обоих столбцов.Это дает вам денормализацию без ущерба для целостности данных.

Если это отличается user_id, то вы можете немного улучшить свое именование.Что-то вроде invited_user_id и email.user_id становится email.sent_by_user_id.

1 голос
/ 08 апреля 2010

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

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

  • Если электронные письма могут существовать без пользователя, тогда они независимы от обоих пользователи и приглашения. В этом случае у вас должно быть поле "email-id" как в «пользователях», так и в «приглашениях» эта ссылка на таблицу «электронные письма». В в этом случае, однако, вы могли бы в конечном итоге с ситуацией, когда у пользователя есть один электронная почта, и его приглашение имеет отдельный (или дублирующий) адрес электронной почты.

1 голос
/ 08 апреля 2010

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

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

С другой стороны, вы правы, указав в приглашении как UserId, так и EmailId, не будет большой проблемой. Это также не дало бы большого преимущества.

...