11

可以在可以包含 NULL 的列上创建唯一约束。但是,最多只有一行可能在该列中包含 NULL。

我不明白为什么会这样,因为根据定义,一个 NULL 不等于另一个 NULL(因为 NULL 实际上是一个未知值,一个未知值不等于另一个未知值)。

我的问题: 1. 为什么会这样?2. 这是特定于 MsSQL 的吗?

我有一种预感,这是因为唯一约束可以充当外键的引用字段,并且如果存在多个具有 NULL 的记录,FK 将不知道它所引用的引用表中的哪条记录。但是,这只是一种预感。

(是的,我知道 UC 可以跨多个列,但这并没有改变问题;相反,它只是让它变得复杂了一点。)

4

2 回答 2

11

是的,它是 Microsoft SQL Server 的“特定”(因为其他一些数据库系统具有相反的方法,即您所期望的方法 - 以及 ANSI 标准中定义的方法,但我相信还有其他数据库系统与 SQL 相同服务器)。

如果您正在使用支持筛选索引的 SQL Server 版本,则可以应用其中之一:

CREATE UNIQUE INDEX IX_T ON [Table] ([Column]) WHERE [Column] IS NOT NULL

(但请注意,该索引不能成为 FK 约束的目标)


它的“为什么”实际上只是归结为,这就是它很久以前的实施方式(可能是预标准),这是现在更改它可能会破坏许多现有系统的尴尬情况之一。

NULL回复:外键 - 如果不是因为外键列中的值导致不检查外键这一事实,那么你是正确的- (在 SQL Server 中)无法NULL用作实际键。

于 2013-07-05T09:15:38.250 回答
5

是的,它是违反 ISO SQL 标准的 SQL Server 功能(以及其他一些 DBMS 的功能)。考虑到应用于 SQL 中其他地方的空值的逻辑,这可能没有多大意义——但是 ISO SQL 标准对于空值的处理也不是很一致。标准 SQL 中可空唯一性约束的行为不是很有帮助。这样的约束根本不一定是“唯一的”,因为它们允许重复的行。例如,约束UNIQUE(foo,bar)允许表中同时存在以下行:

foo    bar
------ ------
999    NULL
999    NULL

(!)

避免可为空的唯一性约束。将列作为不可为空的列移动到新表并将唯一性约束放在那里通常很简单。通过用空值填充这些列来表示的信息可以(大概)通过根本不填充新表中的那些列来表示。

于 2013-07-05T09:37:14.790 回答