Oracle
 sql >> Base de données >  >> RDS >> Oracle

Contrainte unique Oracle et index unique

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 d'unicité est appliquée par un index bien qu'il soit possible (et parfois nécessaire) d'appliquer une contrainte d'unicité à l'aide d'un index non unique. Une contrainte d'unicité différée, par exemple, est appliquée à l'aide d'un index non unique. Si vous créez un index non unique sur une colonne, puis créez une contrainte d'unicité, vous pouvez également utiliser cet index non unique pour appliquer la contrainte d'unicité.

En pratique, un index unique agit comme une contrainte unique non reportable en ce sens qu'il génère la même erreur qu'une contrainte unique, car la mise en œuvre de contraintes uniques utilise l'index. Mais ce n'est pas tout à fait pareil car il n'y a pas de contrainte. Ainsi, comme vous l'avez vu, il n'y a pas de contrainte unique, vous ne pouvez donc pas créer de contrainte de clé étrangère faisant référence à la colonne.

Il existe des cas où vous pouvez créer un index unique alors que vous ne pouvez pas créer de contrainte unique. Un index basé sur une fonction, par exemple, qui applique l'unicité conditionnelle. Si je voulais créer une table prenant en charge les suppressions logiques mais en veillant à 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 index unique non basé sur une fonction, il y a probablement relativement peu de cas où il est vraiment plus logique de créer l'index plutôt que de créer la contrainte. En revanche, il y a relativement peu de cas où cela fait une grande différence dans la pratique. Vous ne voudriez presque jamais déclarer une contrainte de clé étrangère faisant référence à une contrainte unique plutôt qu'à une contrainte de clé primaire, vous perdez donc rarement quelque chose en créant uniquement l'index et en ne créant pas la contrainte.