2011-09-22 2 views
34

Quelqu'un pourrait clarifier quel est le but d'avoir un index unique sans contrainte unique (Oracle)? Par exemple,Oracle contrainte unique et index unique

create table test22(id int, id1 int, tmp varchar(20)); 
create unique index idx_test22 on test22(id); 
insert into test22(id, id1, tmp) values (1, 2, 'aaa'); // ok 
insert into test22(id, id1, tmp) values (1, 2, 'aaa'); // fails, ORA-00001: unique 
    // constraint (TEST.IDX_TEST22) violated 

Jusqu'à présent, il semble qu'il y ait une contrainte. Mais

create table test33(id int not null primary key, 
test22_id int not null, 
foreign key(test22_id) references test22(id)); 

échoue également avec "ORA-02270: no matching unique or primary key for this column-list". Je suis totalement confus par ce comportement. Y a-t-il une contrainte ou pas?

De nombreux articles expliquent pourquoi il est possible d'avoir une contrainte unique sans index unique; c'est clair et c'est parfaitement logique. Cependant, je ne comprends pas la raison de l'index unique sans contrainte.

Répondre

39

Une contrainte et un index sont des entités logiques distinctes. Une contrainte unique, par exemple, est visible dans USER_CONSTRAINTS (ou ALL_CONSTRAINTS ou DBA_CONSTRAINTS). Un index est visible dans USER_INDEXES (ou ALL_INDEXES ou DBA_INDEXES).

Une contrainte unique est appliquée par un index bien qu'il soit possible (et parfois nécessaire) d'appliquer une contrainte unique en utilisant un index non unique. Une contrainte unique reportable, par exemple, est appliquée en utilisant un index non unique. Si vous créez un index non unique sur une colonne et créez ensuite une contrainte unique, vous pouvez également utiliser cet index non unique pour appliquer la contrainte unique.

En pratique, un index unique agit comme une contrainte unique non reportable en ce qu'il soulève la même erreur qu'une contrainte unique déclenche puisque l'implémentation de contraintes uniques utilise l'index. Mais ce n'est pas tout à fait la même chose car il n'y a pas de contrainte. Donc, comme vous l'avez vu, il n'y a pas de contrainte unique, donc vous ne pouvez pas créer une contrainte de clé étrangère qui fait référence à la colonne.

Il existe des cas où vous pouvez créer un index unique que vous ne pouvez pas créer une contrainte unique. Un index basé sur une fonction, par exemple, qui applique l'unicité conditionnelle. Si je voulais créer une table qui a soutenu des suppressions logiques, mais veiller à ce que COL1 est unique pour toutes les lignes non supprimées

SQL> ed 
Wrote file afiedt.buf 

    1 CREATE TABLE t (
    2 col1 number, 
    3 deleted_flag varchar2(1) check(deleted_flag in ('Y','N')) 
    4*) 
SQL>/

Table created. 

SQL> create unique index idx_non_deleted 
    2  on t(case when deleted_flag = 'N' then col1 else null end); 

Index created. 

SQL> insert into t values(1, 'N'); 

1 row created. 

SQL> insert into t values(1, 'N'); 
insert into t values(1, 'N') 
* 
ERROR at line 1: 
ORA-00001: unique constraint (SCOTT.IDX_NON_DELETED) violated 


SQL> insert into t values(1, 'Y'); 

1 row created. 

SQL> insert into t values(1, 'Y'); 

1 row created. 

Mais si nous parlons d'un indice unique de droit non-fonction, il y a probablement relativement Quelques cas où il est vraiment plus logique de créer l'index plutôt que de créer la contrainte. D'autre part, il y a relativement peu de cas où cela fait beaucoup de différence dans la pratique. Vous ne voudrez presque jamais déclarer une contrainte de clé étrangère qui fait référence à une contrainte unique plutôt qu'à une contrainte de clé primaire, de sorte que vous perdez rarement quelque chose en créant uniquement l'index et en ne créant pas la contrainte.

+0

Merci pour votre réponse, cela devient plus clair maintenant. Ce que je n'aime vraiment pas, c'est le même code d'erreur ('ORA-00001') pour les deux cas, avec une contrainte et un index unique. – a1ex07

+0

Excellent, merci pour le "dernier mot" sur si vous pouvez créer une contrainte unique sur un FBI unique. – orbfish

+0

Merci - c'est la seule explication claire de la différence entre les deux que j'ai trouvé. J'ai vu certains mentionner que déclarer une contrainte unique donne à l'optimiseur plus d'informations qu'un index unique ...est-ce vrai, et cela signifie-t-il qu'une contrainte unique pourrait apporter des avantages de performance par rapport à l'index unique sans la contrainte? – Mike

1

Un autre point qui peut être utile dans ce contexte est: La désactivation/suppression d'une contrainte unique existante ne supprime pas l'index unique sous-jacent. Vous devez supprimer l'index unique explicitement.

+2

Ce n'est pas correct (au moins pour 10g). En fait, vous devez spécifier 'KEEP INDEX' tout en supprimant la contrainte unique pour conserver l'index. En outre, l'index ne doit pas nécessairement être unique. – a1ex07

+0

Intéressant. Cependant, ce n'est pas le cas à partir de 11g. – Syamjith

Questions connexes