БД: Круговая зависимость в базе данных - PullRequest
0 голосов
/ 25 января 2010

РЕДАКТИРОВАТЬ: Это дубликат Сначала я его не нашел.

Я создаю веб-сайт для управления событиями в группах пользователей.

Members : Name, Id  
Events : DateTime, Topic, OrganizerId (from FK to Members table)
EventRegistrations : MemberId (FK), EventId (FK)

Описание (избыточно):
Участник может создавать и событие, и становится организатором этого события.
Любой участник может зарегистрироваться на событие, и создается запись в EventRegistrations.

Проблема:
Когда я создаю зависимость PK-FK между таблицами, я получаю сообщение об ошибке:

Введение ограничения FOREIGN KEY 'reg_evt_fk' в таблицу 'eventregistrations' может привести к циклам или нескольким каскадным путям. Укажите ON DELETE NO ACTION или ON UPDATE NO ACTION, либо измените другие ограничения FOREIGN KEY.

Вопрос:
Какой хороший способ справиться с этим? У меня есть два решения для начала:

  1. Ввести 4-ю (ассоциированную) таблицу «Организаторы: MemberId -> EventId».
  2. Отключите CASCADE DELETE на одной из зависимостей и проверяйте программно перед операциями DELETE.

Я ищу предложения или отзывы по вышеуказанному. Дополнительные объяснения / комментарии приветствуются.

Примечание : БД - это SQL Server 2008, но, думаю, это не должно иметь значения.

РЕДАКТИРОВАТЬ: Предположим, что удаление события IS необходимое поведение (пример упрощен).

Ответы [ 4 ]

2 голосов
/ 25 января 2010

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

Ваши столы ...

SQL> create table members
  2      ( name varchar2(10)
  3          , id  number not null primary key   )
  4  /

Table created.

SQL> create table events
  2      ( id  number not null primary key
  3          , datetime date
  4          , topic varchar2(10)
  5          , organizerid  number not null )
  6  /

Table created.

SQL> create table eventregistrations
  2      ( memberid  number not null
  3          , eventid  number not null)
  4  /

Table created.

SQL>

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

SQL> alter table events
  2      add constraint evt_mbr_fk foreign key ( organizerid )
  3      references members (id) on delete cascade
  4  /

Table altered.

SQL>

Участник может зарегистрироваться на любое количество событий ...

SQL> alter table eventregistrations
  2      add constraint reg_mbr_fk foreign key ( memberid )
  3      references members (id) on delete cascade
  4  /

Table altered.

SQL>

Событие может иметь любое количество зарегистрированных участников ...

SQL> alter table eventregistrations
  2      add constraint reg_evt_fk foreign key ( eventid )
  3      references events (id) on delete cascade
  4  /

Table altered.

SQL>

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

редактировать

Я разделяю озабоченность других по поводу использования ON CASCADE DELETE, но я думаю, что это не совсем относится к вопросу. Принудительное изменение органайзера для события является бизнес-правилом. В некоторых сценариях ON DELETE CASACDE подходит, а в некоторых - нет.

редактировать 2

Это признак того, что вид базы данных все-таки имеет значение. Oracle весьма рада передать кассовый отказ от ЧЛЕНОВ на СОБЫТИЯ и СОБЫТИЯ без жалоб.

2 голосов
/ 25 января 2010

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

Решение, которое я бы предпочел, состоит в том, чтобы удалить OrganizerId CASCADE DELETE, так как удаление организующего участника не должно автоматически удалять события участника и реализовывать эту часть как SP.

Вы все еще можете реализовать удаление дочерней записи в триггере INSTEAD OF DELETE или в SP.

1 голос
/ 25 января 2010

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

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

0 голосов
/ 25 января 2010

«БД - это SQL Server 2008, но, думаю, это не должно иметь значения».

Это имеет значение все. Ваша СУБД слишком повреждена, чтобы предложить достойную поддержку для решения вашей проблемы. Кстати, любая альтернатива SQL.

Вы можете дополнительно:

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

  2. Отключите каскадное удаление и замените его активированным кодом. Не забывайте также думать о каскадном обновлении.

...