Создайте ограничение One-to-Optional-One в SQL Server
У меня есть "главный стол", назовите его Customers
:
CREATE TABLE Customers (
CustomerID int PRIMARY KEY NOT NULL,
FirstName nvarchar(50),
LastName nvarchar(50)
)
И у меня есть "спутниковый стол", назовите его Customer_IllegallyObtainedInformation
:
CREATE TABLE Customer_IllegallyObtainedInformation (
CustomerID int PRIMARY KEY NOT NULL,
CellPhonePin int,
SexualOrientation varchar(20),
EmailPassword varchar(50)
)
Теперь, что я хочу, это ограничение внешнего ключа от Illegal
стол обратно на главную Customers
Таблица:
Другими словами:
- может быть
Customer
безIllegal
запись - но никогда не может быть
Illegal
вход безCustomer
Мой инстинкт был, чтобы в диаграмме базы данных SQL Server перетащить
- ОТ
Illegal
стол ДОCustomers
Таблица
Указывая SQL Server, что Customers_IllegallyObtainedInformation
это "ребенок" в отношениях. Вместо этого то, что происходит в этом SQL Server, делает его взаимно-однозначным:
Это означает, что если вы попытаетесь вставить Customer
, он потерпит неудачу, потому что не существует Illegal
Информация.
Как я могу создать отношения "Родитель-ребенок" или "Один-на-факультативный-один" в SQL Server?
Примечание: не путайте пример с вопросом. я мог бы создать жертвенный первичный суррогатный ключ в Illegal
Таблица:
Но это был не мой вопрос.
3 ответа
Другие уже указали, как вы можете достичь того, что вы хотите, установив отношения с помощью сценариев SQL. Я думал, что просто добавлю свои несколько центов о том, что делает дизайнер...
В основном вы тянете в неправильном направлении.
Внешний ключ всегда один-ко-многим. Это способ информирования СУБД, что у вас есть таблица (дочерняя таблица), в которой вы хотите, чтобы столбец (или комбинация столбцов) всегда соответствовал ключу из другой таблицы. Получив эту информацию, СУБД может взять на себя ответственность за то, чтобы каждая строка в дочерней таблице действительно удовлетворяла этому требованию.
Сделав столбец ключом также и в дочерней таблице, связь можно сделать де-факто One-To-One, но с точки зрения СУБД это на самом деле не является свойством отношения. Скорее это просто еще одно ограничение на данные, которые могут быть вставлены в дочернюю таблицу.
При создании отношений в конструкторе кажется, что кто-то решил, что первичный ключ следует перетащить в дочернюю таблицу. Поэтому, когда вы перетаскиваете информацию из Customers_IllegallyObtainedInformation в Customers, дизайнер полагает, что Customers_IllegallyObtainedInformation является таблицей, содержащей первичный ключ.
Но подождите, почему это работает со вторым образцом, где вы ввели суррогатный ключ? Возможно, потому что люди, делающие дизайнера, решили сделать его умным. В этом случае вы перетаскиваете столбец, который не является ключом в таблице. Это не может сформировать первичный ключ в отношении, поэтому разработчик проверяет, может ли отношение быть сформировано в противоположном направлении. И так как это может, это то, что он предлагает...
Кажется, дизайнер создает внешний ключ в обратном направлении.
Просто закодируй это сам:
CREATE TABLE Customers (
CustomerID int PRIMARY KEY NOT NULL,
FirstName nvarchar(50),
LastName nvarchar(50)
)
CREATE TABLE Customer_IllegallyObtainedInformation (
CustomerID int PRIMARY KEY NOT NULL,
CellPhonePin int,
SexualOrientation varchar(20),
EmailPassword varchar(50),
constraint fk_Customers foreign key (CustomerId) references dbo.Customers
)
-- succeeds:
insert into dbo.Customers
values(1, 'One', 'One'), (2, 'Two', 'Two')
--fails:
insert into dbo.Customer_IllegallyObtainedInformation
values(3, 1, '', '');
--succeeds:
insert into dbo.Customer_IllegallyObtainedInformation
values(1, 1, '', '');
PRIMARY KEY может участвовать в исходящем отношении FOREIGN KEY.
CREATE TABLE Customer_IllegallyObtainedInformation (
CustomerID int PRIMARY KEY NOT NULL,
CellPhonePin int,
SexualOrientation varchar(20),
EmailPassword varchar(50)
)
ALTER TABLE Customer_IllegallyObtainedInformation ADD FOREIGN KEY (CustomerId)
REFERENCES Customer(CustomerId)