如何在具有唯一约束的字段中允许在SQL Server中输入大量空值

use*_*261 2 sql-server

create table test3
(
id int PRIMARY KEY,
id2 int
);

create unique index ndx_id2 on test3 (id2);
Run Code Online (Sandbox Code Playgroud)

出于唯一索引的目的,所有NULL值都被认为与所有其他NULL值不同,因此是唯一的.这是SQL-92标准的两种可能解释之一(标准中的语言含糊不清),并且是PostgreSQL,MySQL,Firebird和Oracle的解释.

Informix和Microsoft SQL Server遵循该标准的其他解释.

INSERT INTO test3(id, id2) VALUES (1, null);
INSERT INTO test3(id, id2) VALUES (2, null);
Run Code Online (Sandbox Code Playgroud)

第二次INSERT返回

无法将重复值插入唯一索引.[表名= test3,约束名= ndx_id2]

SQL Server出错但成功将记录添加到另一个DBMS,例如Sqlite.

如何在具有唯一约束的字段中允许在SQL Server中输入大量空值?

And*_*mar 7

从SQL Server 2008开始,您可以使用筛选索引:

create unique index UX_YourIndex
on YourTable(col1) 
where col1 is not null
Run Code Online (Sandbox Code Playgroud)

SQL Fiddle的例子.

对于SQL Server 2005及更早版本(9.0对应于2005),您可以使用代理列.代理列是计算列.计算方法如下:

  • 如果不是半唯一列null,则代理列等于该列
  • 当半唯一列时null,代理列等于唯一ID.唯一ID可以是标识列,rowguid或每行不同的任何内容.

换句话说,只要原始列,代理列就会使用唯一的字符串null.例如:

create table YourTable 
    (
    id int identity primary key
,   col1 int
,   surrogate1 as (coalesce(convert(varchar(20), col1), '_' + convert(varchar(20), id)))
    );

create unique index UX_YourIndex on YourTable(surrogate1);
Run Code Online (Sandbox Code Playgroud)

确保代理值不与实际值发生冲突是你的工作.在这个例子中,我假设col1不能以下划线开头.

SQL Fiddle的例子.