web-dev-qa-db-fra.com

Comment créer un index unique dans Oracle sans ignorer les valeurs NULL?

J'essaie de créer une contrainte unique sur deux champs d'une table. Cependant, il est fort probable que l'une d'elles sera nulle. Je demande seulement qu'ils soient uniques si les deux ne sont pas nuls (name ne sera jamais nul).

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

Ignorer la sémantique des noms de table et de champ et savoir si cela a un sens - je viens d’en inventer quelques-uns.

Existe-t-il un moyen de créer une contrainte unique sur ces champs qui imposera l'unicité pour deux valeurs non nulles, mais ignorer s'il existe plusieurs entrées où name n'est pas null et email est null?

Cette question s'adresse à SQL Server et j'espère que la réponse ne sera pas la même: Comment créer une contrainte unique qui autorise également les valeurs NULL?

23
Brian Ramsay

Nous pouvons le faire avec un index basé sur une fonction. Ce qui suit utilise NVL2() qui, comme vous le savez, renvoie une valeur si l'expression n'est pas null et une valeur différente si elle est null. Vous pouvez utiliser CASE() à la place. 

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, '[email protected]')
  2  /

1 row created.

SQL> insert into blah values (null, '[email protected]')
  2  /

1 row created.

SQL> insert into blah values ('APC', '[email protected]')
  2  /

1 row created.

SQL> insert into blah values ('APC', '[email protected]')
  2  /
insert into blah values ('APC', '[email protected]')
*
ERROR at line 1:
ORA-00001: unique constraint (APC.BLAH_UIDX) violated


SQL>

Modifier

Parce que dans votre nom de scénario sera toujours rempli, vous aurez seulement besoin d'un index comme celui-ci:

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

Index created.

SQL> 
34
APC

Je ne sais pas combien de personnes sont toujours dirigées vers cette réponse, mais au moins dans la dernière version d'Oracle, vous êtes autorisé à avoir plusieurs lignes avec null sur un index unique et la réponse acceptée n'est pas nécessaire

0
broll