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