通常我们只想从Table2
引用Table1
中满足某些谓词的行。像这样:
create table dbo.Table1
(
Id int not null primary key clustered,
IsActive bit not null
);
create table dbo.Table2
(
Id int not null,
Table1Id int not null
);
alter table dbo.Table2
add constraint FK_Table2_Table1
foreign key (Table1Id) references Table1(Id)
where IsActive = 1; -- unsupported
但是此代码不起作用。通常,在这种情况下,建议在IsActive
中添加列Table2
(始终等于1
)并添加FK:
alter table dbo.Table2
add constraint FK_Table2_Table1
foreign key (Table1Id, IsActive) references Table1(Id, IsActive);
此问题的示例:https://dba.stackexchange.com/questions/188379/filtered-foreign-keys
但是,如果我们在Table1
中有10行,在Table2
中有10亿行,则应该存储许多冗余数据。
我们可以解决这个问题吗?
答案 0 :(得分:0)
这里是解决此问题的另一种方法:
create table dbo.Table1 (
Id int not null primary key clustered,
IsActive bit not null,
ActiveIdForForeignKey as iif(IsActive = 1, Id, -Id) persisted not null,
constraint UQ_ActiveIdForForeignKey unique (ActiveIdForForeignKey)
);
go
create table dbo.Table2 (Id int not null, Table1Id int not null);
go
alter table dbo.Table2 add constraint FK_Table2_Table1 foreign key (Table1Id) references Table1(Id);
alter table dbo.Table2 add constraint FK_Table2_Table1_Active foreign key (Table1Id) references Table1(ActiveIdForForeignKey);
go
insert into dbo.Table1(Id, IsActive) values (1, 0);
insert into dbo.Table1(Id, IsActive) values (2, 1);
insert into dbo.Table1(Id, IsActive) values (3, 0);
go
insert into dbo.Table2(Id, Table1Id) values (1, 2); -- success
insert into dbo.Table2(Id, Table1Id) values (2, 1); -- fail
go
看起来很肮脏,但这没有数据存储开销。
我很高兴听到您的评论。