27

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

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

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

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

这个问题是针对 SQL Server 的,我希望答案不一样: 如何创建一个也允许空值的唯一约束?

4

2 回答 2

37

我们可以使用基于函数的索引来做到这一点。如您所知,以下使用NVL2()它,如果表达式不为空,则返回一个值,如果为空,则返回不同的值。你可以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> 
于 2009-09-03T17:21:56.320 回答
2

我不知道有多少人仍然被引导到这个答案,但至少在最新版本的 oracle 中,您可以在唯一索引上拥有多行 null 并且不需要接受的答案

于 2018-11-01T19:15:50.503 回答