Ссылка внешнего ключа на определенный подтип

Этот вопрос связан с внешним ключом для нескольких таблиц, но я подумал, что моя разработка может использовать свой собственный предмет.

Скажем, у меня есть следующая схема (адаптированная из ответа @Nathan Skerl в приведенной выше ссылке):

    create table dbo.PartyType
(   
    PartyTypeId tinyint primary key,
    PartyTypeName varchar(10)
)

insert into dbo.PartyType
    values(1, 'User'), (2, 'Group');


create table dbo.Party
(
    PartyId int identity(1,1) primary key,
    PartyTypeid tinyint references dbo.PartyType(PartyTypeId),
    unique (PartyId, PartyTypeId)
)

CREATE TABLE dbo.[Group]
(
    ID int NOT NULL,
    Name varchar(50) NOT NULL,
    PartyTypeId as cast(2 as tinyint) persisted,
    foreign key (ID, PartyTypeId) references Party(PartyId, PartyTypeID)
)  

CREATE TABLE dbo.[User]
(
    ID int NOT NULL,
    Name varchar(50) NOT NULL,
    PartyTypeId as cast(1 as tinyint) persisted,
    foreign key (ID, PartyTypeId) references Party(PartyID, PartyTypeID)
)

CREATE TABLE dbo.Ticket
(
    ID int NOT NULL,
    [Owner] int NOT NULL references dbo.Party(PartyId),
    [Subject] varchar(50) NULL
)

И скажем, у меня было другое отношение, скажем, «Вещи», где «Пользователи» могли владеть многими элементами «Вещей», но для «Групп» не имело смысла иметь «Материалы». Могу ли я иметь внешний ключ в ссылке «Вещи» только «Пользователь»?

Если это возможно, то как это сделать? Или мне нужно делать все мои внешние ключи такого рода напрямую через «Party»? Я получил сообщение об ошибке (В ссылочной таблице 'dbo.Users' нет первичных ключей или ключей-кандидатов, соответствующих ссылочному столбцу 'ID' во внешнем ключе), когда я попробовал сам.

Заранее спасибо!


person daner    schedule 25.07.2015    source источник


Ответы (2)


Если я правильно понимаю, вы можете делать то, что хотите. Идея состоит в том, чтобы создать уникальный ключ на PartyTypeId, Id.

CREATE TABLE dbo.[User] (
    ID int NOT NULL,
    Name varchar(50) NOT NULL,
    PartyTypeId as cast(1 as tinyint) persisted,
    foreign key (ID, PartyTypeId) references Party(PartyID, PartyTypeID),
    unique (PartyTypeId, Id)
);

CREATE TABLE Stuff (
    StuffId int not null primary key,
    UserId int,
    PartyTypeId as cast(1 as tinyint)  persisted,
    Foreign Key (UserId) references user(PartyTypeId, userId)
);

Вот скрипт SQL. Это объясняется в документации.

person Gordon Linoff    schedule 25.07.2015
comment
Спасибо за очень полезный ответ и прикрепленные ссылки. Помогло и моему пониманию. Пара вещей: приведенный выше код не соответствует Fiddle; на самом деле приведенный выше код генерирует количество ссылочных столбцов во внешнем ключе, отличающееся от количества ссылочных столбцов таблицы «Вещи». ошибка. - person daner; 27.07.2015
comment
Во-вторых, мне было интересно узнать о плюсах и минусах утверждения уникальности только для поля ID в User, а затем иметь FK в Stuff только для поля UserId (таким образом, отбрасывая поле PartyTypeId) - person daner; 27.07.2015

Да, у вас может быть внешний ключ в ссылке Stuff только на пользователя:

CREATE TABLE Stuff (
    StuffId int not null primary key,
    UserId int,
    Foreign Key (UserId) references dbo.[User](ID)
);
person reaanb    schedule 25.07.2015