Должен ли создаваться внешний ключ на родительской таблице или детской таблице?
Какая разница? Если у меня есть эти две таблицы:
CREATE TABLE Account (Id int NOT NULL)
CREATE TABLE Customer (AccountId int NOT NULL)
И я хочу, чтобы внешний ключ связывал два, какие из следующих я должен делать и почему?
Вариант 1:
ALTER TABLE [dbo].[Customer] WITH CHECK
ADD CONSTRAINT [FK_Accounts_Customers] FOREIGN KEY([AccountId])
REFERENCES [dbo].[Account] ([Id])
Вариант 2:
ALTER TABLE [dbo].[Account] WITH CHECK
ADD CONSTRAINT [FK_Accounts_Customers] FOREIGN KEY([Id])
REFERENCES [dbo].[Customer] ([Id])
Ответы
Ответ 1
Зависит от контекста. У каждого клиента есть клиент? Какой из них является родителем? Кажется, что Учетная запись имеет несколько Клиентов, и в этом случае ссылка принадлежит таблице Customer.
Теперь, пожалуйста, называйте сущности CustomerID
и AccountID
всюду. Это может показаться излишним в первичной таблице, но имя должно быть согласованным во всей модели.
Ответ 2
Я бы использовал внешний ключ от дочернего элемента к родительскому. Заданный вопрос: что произойдет, если вам нужно удалить одно из объектов?
Ответ 3
A FK (внешний ключ) сообщает СУБД, что значения для столбцов для списка столбцов должны появляться в другом месте в качестве значений для подстрок для списка столбцов. Всякий раз, когда это происходит (и это еще не подразумевается другими декларациями), объявляйте FK. Если в добавлении вы хотите применить действие CASCADE к указанной таблице при изменении таблицы ссылок, объявите это.
(В CASCADE нет ничего особенного, что он не может быть предложен для ситуаций, отличных от FK. Он часто встречается с FK, и там есть явный график FK, позволяющий разумно ограничивать их взаимодействия.)
Если существует цикл FK, вам нужно будет использовать триггеры. Ваше решение о том, какие ограничения принудительно применяются декларативно и которые по триггеру должны учитывать график (желаемых) ограничений.