Как спроектировать эту базу данных, чтобы избежать циклической зависимости?


12

Есть две таблицы:

  1. пользователь
  2. Адрес

Пользователь содержит ссылку на адрес.

Адрес содержит столбцы CreatedBy и ModifiedBy, которые являются ссылкой на пользователя.

Как мне спроектировать эту базу данных, чтобы избежать циклической зависимости?


4
Вы уверены, что ModifiedBy - это не ссылка на пользователя базы данных, который внес изменение, а на пользователя приложений (который будет находиться в таблице User)? В любом случае, это не имеет значения. Я не понимаю, почему существует актуальная проблема?
Philᵀᴹ

Какой будет создан первым. Поскольку CreatedBy и Modifiedby являются обязательными данными. И таблица пользователя не должна иметь addressid как ноль. Проблема куриного яйца. Как я решаю это путем создания новой таблицы UserAddress, которая содержит ссылку на идентификатор пользователя и адрес
Шаши

2
Вы всегда можете использовать отложенные ограничения, если ваша СУБД их поддерживает.
Colin 't Hart

NB. Реляционная модель поддерживает две операции вставки или обновления как одну атомарную операцию, и это позор, что она не поддерживается в SQL (поскольку отложенные ограничения - хотя я их и предложил - довольно ужасны).
Colin 't Hart

Ответы:


7

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


факты

  • Пользователь(UserID) существует.
  • Адрес(AddressID) был создан пользователем(UserID) .
  • Адрес(AddressID) был создан на дату(DateCreated) .
  • Адрес(AddressID) был последний раз изменен пользователем(UserID) на дату(ModifiedOn) .
  • Пользователь(UserID) находится по адресу(AddressID) с даты(ValidFrom) .

Ограничения

  • Each Адрес был создан exactly one пользователем . It is possible that more than one Адрес был создан the same пользователем .

  • Each Адрес был создан на exactly one дату . It is possible that more than one Адрес был создан на the same дату .

  • For each Адрес and Дата , that адрес был изменен at most one пользователем на that дату .

  • For each Пользователь and Дата , that пользователь ПРЕБЫВАЕТ at most one Адрес поскольку that дата .


логический

введите описание изображения здесь


Что касается обязательного адреса, проверьте это на прикладном уровне и оберните операторы загрузки в транзакцию - так вы получите все или ничего.


5

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

CREATE TABLE A (A_ID INT PRIMARY KEY, B_FK INT);
CREATE TABLE B (B_ID INT PRIMARY KEY, A_FK INT REFERENCES A(A_ID));

ALTER TABLE A ADD B_FK INT;

Если вы хотите избежать циклической зависимости. Затем вам нужно удалить одно ограничение REFERENCES или вы можете добавить ссылку DELETE и UPDATE CASCADE одним способом. Вы также можете реализовать TRIGGER, если ваша логика несколько сложна.


1
Удаление ограничений удаляет циклическую зависимость из определения, но не дизайн. Вы можете добавить таблицу Events, чтобы записать UserID и AddressID, которые в последний раз создавали или изменяли адрес, но это просто перемещает зависимость на один шаг дальше. Иначе говоря, если бы в таблице User были столбцы CreatedBy и ModifiedBy, циклическая зависимость существовала бы в одной таблице. Это похоже на таблицу сотрудников со столбцом руководителя, где руководитель также является сотрудником. Как указал Фил - не проблема.
Ли Риффель

@LeighRiffel Я согласен. Но таблица «События», которую вы предлагаете, действительно удаляет все циклические зависимости.
ypercubeᵀᴹ

@ypercube Это действительно так; не уверен, как я получил этот провод пересек. Чтобы было ясно, вам, вероятно, не следует создавать таблицу Events, даже если она удаляет циклическую зависимость.
Ли Риффель

Во всяком случае, я не думаю, что этот ответ решает проблему. Вопрос (я думаю) заключается в том, как вообще избежать циклического пути, а не в том, как создавать FK с циклическим путем в первую очередь.
ypercubeᵀᴹ
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.