Другой способ (без нулей и без циклов в FOREIGN KEY
отношениях) - создать третью таблицу для хранения «любимых детей». В большинстве СУБД вам понадобится дополнительное UNIQUE
ограничение TableB
.
@ Аарон был быстрее, чтобы определить, что соглашение об именах, приведенное выше, довольно громоздко и может привести к ошибкам. Обычно лучше (и будет держать вас в здравом уме), если у вас нет 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-Server, заключается в том, что шаблон круговых путей в ссылках на внешний ключ имеет некоторые проблемы.
Прочитайте довольно старую статью: SQL By Design: циркулярная ссылка
Вставляя или удаляя строки из двух таблиц, вы столкнетесь с проблемой «курица и яйцо». Какую таблицу я должен вставить первым - без нарушения каких-либо ограничений?
Чтобы решить эту проблему, вы должны определить хотя бы один столбец, который можно обнулять. (Хорошо, технически вам не нужно, вы можете иметь все столбцы как, NOT NULL
но только в СУБД, таких как Postgres и Oracle, в которых реализованы отложенные ограничения. См. Ответ @ Erwin на аналогичный вопрос: Сложное ограничение внешнего ключа в SQLAlchemy о том, как это можно сделать в Postgres). Тем не менее, эта установка ощущается как катание на коньках по тонкому льду
Проверьте также почти идентичный вопрос в SO (но для MySQL). В SQL нормально ли для двух таблиц ссылаться друг на друга? где мой ответ почти такой же. В MySQL нет частичных индексов, поэтому единственными возможными вариантами являются обнуляемый FK и решение с дополнительными таблицами.