允许多个 NULL 的 UNIQUE 'WHERE'索引是否可以用作外键关系的主键?



在Azure上使用SQL Server:12.0.2000.8

我为TablePrimary定义了以下唯一索引:

CREATE UNIQUE NONCLUSTERED INDEX [IX_TablePrimary_Id] 
ON [dbo].[TablePrimary] ([PrimaryId] ASC)
WHERE [PrimaryId] IS NOT NULL

WHERE子句允许多行在此列中具有NULL,但此列中的每个非NULL值都必须是唯一的。

TablePrimary中的索引列是否适合作为与TableForeign的外键关系的主键?每个非NULL值都必须是唯一的,并且外表中的NULL无论如何都不会创建外键关系。但是我在尝试将外键关系放置在TableForeign上时遇到了一个错误。

无法创建关系"FK_TableForeign_TablePrimary">
被引用表的dbo中没有主键或候选键。与外键"FK_TableForeign_TablePrimary"中的引用列列表匹配的TablePrimary。

在深入研究之前,我想验证一下我试图做的事情确实是可能的。基本上,并不是TablePrimary中的每一行都会在TableForeign中有子行。但是TableForeign中确实存在的那些行在TablePrimary中必须有一个匹配的PrimaryId(有其他方法可以完成这项工作,但在这种情况下,我需要第三个表作为TablePrimaryTableForeign之间的交叉引用,如果没有必要,我想避免这种情况,尽管如果有必要,那也是必要的(。

是否可以使用允许多个NULL的UNIQUE"WHERE"索引作为外键关系的主键?

否。外键不能引用经过筛选的唯一索引。外键可以引用唯一索引(即使包含列,但没有筛选器(。

edit:用于Nullability。外键可以引用具有NULLable列的唯一索引/约束。可为Null性不是创建外键的先决条件。但是,对于任何fk列中至少有一个空值的行,都不会检查外键:

create table dbo.parent
(
id1 int null,
id2 int null,
constraint id1id2 unique(id1, id2)
);
insert into dbo.parent(id1, id2)
values(1, 1), (2, 2), (3, null);
go
create table dbo.child
(
childid int identity,
parentid1 int,
parentid2 int,
constraint fkparent foreign key(parentid1, parentid2) references parent(id1, id2)
)
go

insert into dbo.child(parentid1, parentid2)
values (1, 1), (2, 2) --ok
go
insert into dbo.child(parentid1, parentid2)
values (4, 4) -- fk violation, there is no 4,4 parent row
go
insert into dbo.child(parentid1, parentid2)
values (3, null) --do not get tricked here.... because the fk has a null value, the fk is NOT checked at all
go
--fk with one null value, fk is not checked at all 
insert into dbo.child(parentid1, parentid2)
values (100, null) -- but there is no 100, null parent row
go
select *
from parent;
select *
from child;

相关内容

最新更新