为什么 UNIQUE 约束只允许一个 NULL?

use*_*166 37 null database-design sql-server constraint unique-constraint

从技术上讲,NULL = NULL 是 False,根据该逻辑,没有 NULL 等于任何 NULL,并且所有 NULL 都是不同的。这不应该意味着所有 NULL 都是唯一的并且唯一索引应该允许任意数量的 NULL 吗?

Aar*_*and 58

为什么它以这种方式工作?因为在很久以前,有人在不知道或不关心标准说什么的情况下做出了设计决定(毕竟,我们确实对NULLs有各种奇怪的行为,并且可以随意强制不同的行为)。该决定规定,在这种情况下,NULL = NULL.

这不是一个非常明智的决定。他们应该做的是让默认行为符合 ANSI 标准,如果他们真的想要这种特殊行为,请通过 DDL 选项(如WITH CONSIDER_NULLS_EQUAL或 )允许它WITH ALLOW_ONLY_ONE_NULL

当然,事后看来是 20/20。

无论如何,我们现在有一个解决方法,即使它不是最干净或最直观的。

通过创建唯一的筛选索引,您可以在 SQL Server 2008 及更高版本中获得正确的 ANSI 行为。

CREATE UNIQUE INDEX foo ON dbo.bar(key) WHERE key IS NOT NULL;
Run Code Online (Sandbox Code Playgroud)

这允许多个NULL值,因为这些行完全被排除在重复检查之外。作为额外的好处,如果NULL允许多个s(特别是当它不是索引中的唯一列,它有INCLUDE列等时),这最终将是一个比由整个表组成的索引更小的索引。但是,您可能希望了解过滤索引的其他一些限制:


Ken*_*her 9

正确的。sql server 中唯一约束或索引的实现只允许一个NULL。也纠正这在技术上不符合 NULL 的定义,但这是他们为使其更有用而做的事情之一,即使它在“技术上”不正确。注意 PRIMARY KEY(也是唯一索引)不允许 NULL(当然)。