Unique Constraint列只能包含一个NULL值

时间:2013-07-05 09:08:20

标签: sql sql-server null

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

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

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

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

(是的,我知道UC可以跨多个列,但这不会改变问题;相反,它只会让它复杂化。)

2 个答案:

答案 0 :(得分:9)

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

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

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

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


它的“为什么”真正归结为,它就是很久以前的实施方式(可能是预标准),而现在改变它的尴尬局面之一可能会破坏现有的许多系统。 / p>

Re:外键 - 如果不是因为外键列中的NULL值导致外键不被检查这一事实你是对的 - 没有办法(在SQL Server中) )使用NULL作为实际密钥。

答案 1 :(得分:5)

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

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

(!)

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