我可以设置一个(逻辑)PRIMARY KEY 约束,由(物理)NONCLUSTERED INDEX 提供服务,以便它只检查相关表中约束和索引列或另一列的某些值吗?
而且,如果是这样,是否可以将该列建立为从其他表引用的 FOREIGN KEY 约束?
我试图基本上看看我是否可以从父表中删除某些行而不从子表中删除这些行但仍然强制执行关系,例如:
IDs > 1000
, 或者CreatedDateTime > RemovalDate
.
例如,您可以有这种约束:
ALTER TABLE MyTable WITH NOCHECK ADD
CONSTRAINT PK_MyTable CHECK (Id > 1000)
但是您如何将此列设置为使用 NONCLUSTERED INDEX 固定的主键?
我可以做类似以下定义的事情吗:
ALTER TABLE MyTable WITH NOCHECK ADD
CONSTRAINT PK_MyTable CHECK (CreatedOn > '01/01/2010')
但是有一个名为的列的索引Id
?
您不能拥有仅适用于某些行的主键。那时它真的不再是主键。强调小学。
您可以为唯一索引使用过滤索引,并且该过滤器可以基于您指定的值。
但是有一个主键来强制唯一性,因此您不能只将表的某些部分作为键的一部分。
您可以在进行修复时禁用 FK,您可以在现有表上建立外键关系
NOCHECK
- 但这意味着不会检查任何关系。您有一个不受信任的外键,并且外键提供的一些好处(例如外键连接消除)无法以这种方式工作,因为 SQL 不能保证您的行在那里或不在那里。或者,您可以不定义这种关系并处理后果。但是你基本上是在要求 SQL Server 在一开始就通过制造异常来破坏参照完整性。如果您可以将这些异常转移到一个单独的表中并在视图或类似的东西中加入该表,您可以解决这个问题并保持“真实”表上的关系向前发展。
但请记住:过滤索引只能在过滤器的另一端为您提供一些唯一性。这不涉及 FK 甚至 PK。我认为更好的答案是解决数据问题。即使是仓库中常见的“未知”的 -1 主键值也比孤儿更好。
似乎有些混乱。这
CHECK (Id > 1000)
不是约束,而是约束。PRIMARY KEY
CHECK
你可以有一个部分(过滤*)唯一索引,如果那是你所追求的:(
UNIQUE (id) WHERE (id > 1000)
但这不是主键约束或可用于主键约束的索引)。创建它:这意味着所有
id
大于 1000 的值都只会在该列中出现一次。所有其他值(1000 和更低)将允许重复。日期列也类似:
这意味着对于
CratedOn
2010 年及之后的行,id
值将是唯一的。对于该唯一索引,将忽略所有其他行(CreatedOn
在 2009 年和更早的时候有 or )。因此,只要除一个以外的所有值都不符合索引的条件,NULL
您就可能有重复值。id
WHERE
这些索引当然是非聚集的——所有部分索引都是。
而且它们不能用作
FOREIGN KEY
约束的目标。*:请参阅 MSDN 上的
CREATE INDEX
和Fileterd 索引页面或使用和优点的详细信息。关于他们“为什么我们不能引用部分索引?”:
这就是 SQL 标准所说的以及它在 SQL Server 中的实现方式。FK 约束必须引用表的一列(或多列)。不是索引。根据定义,部分索引包含出现在列中的部分值,而不是全部。
我前段时间问过一个相关的问题:Are there DBMS that allow a Foreign Key that References a View (and not only base tables)?.
关系模型中不存在不允许定义此类 FK 的固有问题。但是 SQL(委员会和各种 DBMS)没有将此添加为功能。