Допустимо ли иметь круговую ссылку между двумя таблицами в поле внешнего ключа?
Если нет, как можно избежать этих ситуаций?
Если да, то как можно вставить данные?
Ниже приведен пример того, где (по моему мнению) круговая ссылка будет приемлемой:
CREATE TABLE Account
(
ID INT PRIMARY KEY IDENTITY,
Name VARCHAR(50)
)
CREATE TABLE Contact
(
ID INT PRIMARY KEY IDENTITY,
Name VARCHAR(50),
AccountID INT FOREIGN KEY REFERENCES Account(ID)
)
ALTER TABLE Account ADD PrimaryContactID INT FOREIGN KEY REFERENCES Contact(ID)
database-design
foreign-key
rdbms
KidCode
источник
источник
Ответы:
Поскольку вы используете пустые поля для внешних ключей, вы можете создать систему, которая будет работать правильно, как вы ее себе представляете. Для вставки строк в таблицу «Учетные записи» необходимо, чтобы в таблице «Контакты» присутствовала строка, если только вы не разрешаете вставки в «Учетные записи» с нулевым PrimaryContactID. Чтобы создать строку контакта, в которой еще нет строки «Учетная запись», необходимо разрешить использование столбца «AccountID» в таблице «Контакты». Это позволяет Учетным записям не иметь контактов, и позволяет Контактам не иметь учетной записи. Возможно это желательно, возможно нет.
Сказав это, мое личное предпочтение будет иметь следующую настройку:
Это дает возможность:
IX_AccountsContactsXRef_Primary
индекса. Этот индекс содержит фильтр, поэтому он будет работать только на платформах, которые их поддерживают. Поскольку этот индекс указывается с помощьюUNIQUE
опции, для каждой учетной записи может быть только один основной контакт.Например, если вы хотите отобразить список всех контактов с колонкой, обозначающей «основной» статус, с указанием основных контактов в верхней части списка для каждой учетной записи, вы можете сделать следующее:
Отфильтрованный индекс предотвращает вставку более одного основного контакта для каждой учетной записи, одновременно обеспечивая быстрый способ возврата списка основных контактов. Можно легко представить другой столбец
IsActive
с неуникальным отфильтрованным индексом для ведения истории контактов для учетной записи, даже после того, как этот контакт больше не связан с учетной записью:источник
Нет, недопустимо иметь круговые ссылки на внешние ключи. Не только потому, что было бы невозможно вставить данные без постоянного удаления и воссоздания ограничения. но потому что это принципиально некорректная модель любой и каждой области, о которой я могу думать. В вашем примере я не могу представить ни одного домена, в котором отношения между Учетной записью и Контактом не являются NN, требуя таблицы соединений со ссылками FK обратно на Учетную запись и Контакт.
источник
Ваш внешний объект может указывать на основной контакт, а не на учетную запись. Ваши данные будут выглядеть так:
источник