Як розробити цю базу даних, щоб уникнути циклічної залежності?


12

Є дві таблиці:

  1. Користувач
  2. Адреса

Користувач містить посилання на адресу.

Адреса містить стовпці CreatedBy та ModifiedBy, що посилаються на Користувача.

Як створити цю базу даних, щоб уникнути циклічної залежності?


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

Який із них створимо першим. Оскільки CreatedBy ANd Modifiedby є обов'язковими даними. І таблиця користувача не повинна мати addressid як null .. Проблема з курячим яйцем. Як я вирішу це, створивши нову таблицю UserAddress, яка містить посилання на userid та addressid
Shashi

2
Ви завжди можете використовувати відкладені обмеження, якщо ваші СУБД їх підтримують.
Colin 't Hart

Примітка: Реляційна модель підтримує два вставки або оновлення як одну атомну операцію, це справді шкода, що це не підтримується в 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

У вас немає іншого вибору, як створити циклічну залежність у двох операціях, як показано нижче, оскільки одна таблиця не існує при створенні першої.

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
Видалення обмежень знімає циклічну залежність від визначення, але не від конструкції. Ви можете додати таблицю подій для запису UserID та AddressID, які останній раз створили або змінили адресу, але це просто переміщує залежність на крок далі. Якщо піти іншим шляхом, якби таблиця користувачів мала стовпці CreateBy та ModifiedBy, циклічна залежність існувала б в одній таблиці. Це схоже на таблицю працівника зі стовпцем керівника, де керівник також є працівником. Як зазначив Філ - Не проблема.
Лі Ріффер

@LeighRiffel Я згоден. Але запропонована вами таблиця подій фактично усуває всі циклічні залежності.
ypercubeᵀᴹ

@ypercube Дійсно це робить; не впевнений, як я перекреслив цей провід. Щоб було зрозуміло, ви, ймовірно, не повинні створювати таблицю подій, навіть якщо вона усуває циклічну залежність.
Лі Риффель

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