Модель базы данных с циклическими ссылками, можно ли ее избежать?

У меня есть следующие таблицы:

  • Человек
  • Членство
  • person_membership (для многих ко многим между человеком и членством)
  • Отношение

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

Чтобы вышеизложенное работало, я поместил следующие поля в таблицу отношений:

  • id
  • person1_id
  • person2_id
  • членство_идентификатор

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

Пример: Джон и Марри входят в число членов 1234. Джон и Адам входят в число членов 5678.

В членстве 1234 Джон - муж Марии.

В членстве 5678 Джон является братом Адама.


person zoro74    schedule 01.10.2014    source источник
comment
Почему у вас есть member_id в таблице отношений? Отношения объединяют людей, а членство человека объединяет каждого человека с членством. Разве это не правильно?   -  person Chris Barlow    schedule 01.10.2014
comment
Спасибо за ответ Крис. Я объяснил, что я сделал ниже.   -  person zoro74    schedule 01.10.2014


Ответы (1)


Нет технических причин избегать циклических ссылок в реляционной модели данных. SQL отлично справляется с этим, и рекомендуется соответствующим образом моделировать отношения для представления объектов в одной таблице, если они относятся к одному и тому же типу объектов. В некоторых базах данных есть даже специальные ключевые слова для поддержки рекурсивных/иерархических отношений.

Если вам это неудобно, просто привыкните к псевдонимам ваших таблиц в SQL-запросах, например, когда вы обращаетесь к таблице Person по разным причинам (на разных уровнях), чтобы представить уровень доступа.

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

select Children.*, Parent.name from person Children
  left join person Parents
    on Children.parentID = Parents.ID

Теперь вы как будто выбираете из двух разных таблиц и присоединяетесь к ним. SQL не волнует, сколько раз вы ссылаетесь на одну и ту же таблицу в запросе, он каждый раз обрабатывает ее так, как если бы это была уникальная таблица (для целей того, что я говорю). Вы можете выбрать из Person как p1, p2, p3, p4 и т. д. и соединить их всех, как вам нужно.

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

Представления — еще один полезный инструмент для упрощения циклических ссылок, в зависимости от того, можете ли вы назначить идентификаторы роли или типа записи для Person. Во многих случаях представление может нарезать/фильтровать базовую таблицу по функции.

person codenheim    schedule 01.10.2014
comment
Спасибо за ответ Мелвин. Я фактически закончил тем, что удалил member_id из таблицы Relationship, как указал Крис. Чтобы получить отношения для 2 человек, которые принадлежат к членству (2 — это максимальное количество людей на членство), я просто запрашиваю таблицу отношений для этих 2 человек. Я думаю, что это достаточно легко. - person zoro74; 01.10.2014