Создайте ограничение 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)
Другие вопросы по тегам