如何在NULL列上创build唯一索引?

我正在使用SQL Server 2005.我想约束列中的值是唯一的,同时允许NULLS。

我目前的解决scheme涉及一个独特的索引,如下所示:

CREATE VIEW vw_unq WITH SCHEMABINDING AS SELECT Column1 FROM MyTable WHERE Column1 IS NOT NULL CREATE UNIQUE CLUSTERED INDEX unq_idx ON vw_unq (Column1) 

任何更好的想法?

很确定你不能这样做,因为它违背了唯一的目的。

不过,这个人似乎有一个体面的工作: http : //sqlservercodebook.blogspot.com/2008/04/multiple-null-values-in-unique-index-in.html

使用SQL Server 2008,您可以创build一个筛选的索引: http : //msdn.microsoft.com/en-us/library/cc280372.aspx 。 (我看到西蒙补充说这是一个评论,但认为这是值得它自己的答案,因为评论很容易错过)

另一个选项是检查唯一性的触发器,但这可能会影响性能。

计算的专栏技巧被广为人知地称为“黑名单”。 我的笔记信用史蒂夫卡斯:

 CREATE TABLE dupNulls ( pk int identity(1,1) primary key, X int NULL, nullbuster as (case when X is null then pk else 0 end), CONSTRAINT dupNulls_uqX UNIQUE (X,nullbuster) ) 

严格来说,一个唯一可空的列(或一组列)可以是NULL(或一个NULL的logging)只有一次,因为具有相同的值(包括NULL)不止一次明显违反了唯一约束。

但是,这并不意味着“唯一可空列”的概念是有效的; 为了在任何关系数据库中实际实现它,我们必须牢记这种数据库是为了正常工作而规范化的,规范化通常包括添加几个(非实体)额外表来build立实体之间的关系。

我们来看一个基本的例子,只考虑一个“独特的可空列”,很容易将其扩展到更多的列。

假设我们用这样的表格表示的信息:

 create table the_entity_incorrect ( id integer, uniqnull integer null, /* we want this to be "unique and nullable" */ primary key (id) ); 

我们可以通过将uniqnull分开,并添加第二个表来build立uniqnull值和the_entity之间的关系(而不是在the_entity内部有uniqnull“):

 create table the_entity ( id integer, primary key(id) ); create table the_relation ( the_entity_id integer not null, uniqnull integer not null, unique(the_entity_id), unique(uniqnull), /* primary key can be both or either of the_entity_id or uniqnull */ primary key (the_entity_id, uniqnull), foreign key (the_entity_id) references the_entity(id) ); 

要将uniqnull的值关联到the_entity中的行,我们还需要在参考中添加一行。

对于在the_entity中的行没有uniqnull值是相关联的(即我们将NULL放在the_entity_incorrect中),我们只是不要在参数中添加一行。

请注意,uniqnull的值对于所有的相关性都是唯一的,并且还要注意,对于the_entity中的每个值,在相关中最多只能有一个值,因为其上的主键和外键都强制执行此操作。

那么,如果将uniqnull的值设为5与3的the_entity_id相关联,则需要:

 start transaction; insert into the_entity (id) values (3); insert into the_relation (the_entity_id, uniqnull) values (3, 5); commit; 

而且,如果the_entity的id值为10,那么我们只做:

 start transaction; insert into the_entity (id) values (10); commit; 

为了使这个信息非规范化并获得像the_entity_incorrect这样的表格,我们需要:

 select id, uniqnull from the_entity left outer join the_relation on the_entity.id = the_relation.the_entity_id ; 

“left outer join”操作符确保来自the_entity的所有行都将出现在结果中,在相关列中不存在匹配列时,将uniqnull列中的值放入NULL。

请记住,在devise一个规范化的数据库(以及相应的反规范化视图和程序)的过程中,花费数天(或数周或数月)的努力将为您节省数年(或数十年)的痛苦和浪费的资源。