如何在Oracle中创建唯一索引但忽略空值?

时间:2009-09-03 17:09:39

标签: sql oracle ddl

我正在尝试在表中的两个字段上创建唯一约束。但是,很可能一个人将为空。如果两者都不为空,我只要求它们是唯一的(name永远不会为空)。

create unique index "name_and_email" on user(name, email);

忽略表和字段名称的语义以及这是否有意义 - 我只是做了一些。

有没有办法在这些字段上创建一个唯一约束来强制两个非空值的唯一性,但如果有多个条目name不为空并且email为空,则忽略?

这个问题适用于SQL Server,我希望答案不一样: How do I create a unique constraint that also allows nulls?

2 个答案:

答案 0 :(得分:34)

我们可以使用基于函数的索引来完成此操作。以下使用NVL2(),如果表达式不为null,则返回一个值,如果为null,则返回不同的值。您可以使用CASE()代替。

SQL> create table blah (name varchar2(10), email varchar2(20))
  2  /

Table created.

SQL> create unique index blah_uidx on blah
  2      (nvl2(email, name, null), nvl2(name, email, null))
  3  /

Index created.

SQL> insert into blah values ('APC', null)
  2  /

1 row created.

SQL> insert into blah values ('APC', null)
  2  /

1 row created.

SQL> insert into blah values (null, 'apc@example.com')
  2  /

1 row created.

SQL> insert into blah values (null, 'apc@example.com')
  2  /

1 row created.

SQL> insert into blah values ('APC', 'apc@example.com')
  2  /

1 row created.

SQL> insert into blah values ('APC', 'apc@example.com')
  2  /
insert into blah values ('APC', 'apc@example.com')
*
ERROR at line 1:
ORA-00001: unique constraint (APC.BLAH_UIDX) violated


SQL>

修改

因为在您的场景名称中将始终填充,您只需要这样的索引:

SQL> create unique index blah_uidx on blah
  2      (nvl2(email, name, null), email)
  3  /

Index created.

SQL> 

答案 1 :(得分:0)

我不知道仍然有多少人直接获得此答案,但是至少在最新版本的oracle中,允许您在唯一索引上包含多行为null的行,并且不需要接受答案