Інший спосіб (без Нулів і без циклів у FOREIGN KEY
відносинах) - мати третю таблицю для зберігання "улюблених дітей". У більшості СУБД вам потрібно буде додаткове UNIQUE
обмеження TableB
.
@Aaron швидше визначив, що вищевказана угода про іменування є досить громіздкою і може призвести до помилок. Зазвичай це краще (і буде зберігати вас здорово), якщо у вас немає Id
стовпців по всьому столу і якщо стовпці (що з’єднуються) мають однакові назви у багатьох таблицях, що з'являються. Отже, ось перейменування:
Parent
ParentID INT NOT NULL PRIMARY KEY
Child
ChildID INT NOT NULL PRIMARY KEY
ParentID INT NOT NULL FOREIGN KEY REFERENCES Parent (ParentID)
UNIQUE (ParentID, ChildID)
FavoriteChild
ParentID INT NOT NULL PRIMARY KEY
ChildID INT NOT NULL
FOREIGN KEY (ParentID, ChildID)
REFERENCES Child (ParentID, ChildID)
У SQL-сервері (який ви використовуєте) у вас також є можливість IsFavorite
вказати бітову колонку. Унікальна улюблена дитина на одного батька може бути досягнута за допомогою відфільтрованого унікального індексу:
Parent
ParentID INT NOT NULL PRIMARY KEY
Child
ChildID INT NOT NULL PRIMARY KEY
ParentID INT NOT NULL FOREIGN KEY REFERENCES Parent (ParentID)
IsFavorite BIT NOT NULL
CREATE UNIQUE INDEX is_FavoriteChild
ON Child (ParentID)
WHERE IsFavorite = 1 ;
І головна причина того, що ваш варіант 1 не рекомендується, принаймні не в SQL-сервері, полягає в тому, що візерунок кругових шляхів у посиланнях іноземних ключів має деякі проблеми.
Прочитайте досить стару статтю: SQL By Design: Circular Reference
Вставляючи або видаляючи рядки з двох таблиць, ви стикаєтеся з проблемою "курка-яйце". Яку таблицю я повинен вставити першою - не порушуючи жодних обмежень?
Для того, щоб вирішити це, вам потрібно визначити принаймні один стовпчик, який є нульовим. (Гаразд, технічно цього не потрібно, ви можете мати всі стовпці як NOT NULL
тільки в СУБД, наприклад Postgres та Oracle, які реалізували відкладені обмеження. Див. Відповідь Ервіна в аналогічному запитанні: Складне обмеження зовнішнього ключа в SQLAlchemy про те, як це можна зробити в Postgres). І все-таки ця установка відчуває себе катанням на тонкому льоду.
Перевірте також майже однакове запитання на SO (але для MySQL) У SQL, чи добре, щоб дві таблиці посилалися одна на одну? де моя відповідь майже однакова. Однак MySQL не має часткових індексів, тому єдиними життєздатними варіантами є нульовий FK та додаткове рішення таблиці.