制約とインデックスは別個の論理エンティティです。たとえば、一意の制約はUSER_CONSTRAINTS
(またはALL_CONSTRAINTS
またはDBA_CONSTRAINTS
) に表示されます。インデックスはUSER_INDEXES
(またはALL_INDEXES
またはDBA_INDEXES
) に表示されます。
一意性制約はインデックスによって適用されますが、非一意性インデックスを使用して一意性制約を適用することは可能です (必要な場合もあります)。たとえば、遅延可能なユニーク制約は、非ユニーク インデックスを使用して適用されます。列に一意でないインデックスを作成し、その後で一意制約を作成する場合、その一意でないインデックスを使用して一意制約を適用することもできます。
実際には、一意のインデックスは、一意の制約の実装でインデックスが使用されるため、一意の制約で発生するのと同じエラーが発生するという点で、一意の遅延不可能な制約と非常によく似た動作をします。しかし、制約がないため、まったく同じではありません。ご覧のとおり、一意の制約がないため、列を参照する外部キー制約を作成できません。
ユニークインデックスは作成できても、ユニーク制約は作成できない場合があります。たとえば、条件付きの一意性を強制する関数ベースのインデックス。論理削除をサポートするテーブルを作成したいが、COL1
削除されていないすべての行に対して一意で あることを確認したい場合
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.
しかし、単純な一意の非関数ベースのインデックスについて話している場合、制約を作成するよりもインデックスを作成する方が本当に理にかなっているケースは比較的少ないでしょう。一方で、実際に大きな違いが生じるケースは比較的少ないです。主キー制約ではなく一意制約を参照する外部キー制約を宣言することはほとんどないため、インデックスを作成するだけで制約を作成しないことで何かが失われることはほとんどありません。