誰かが一意制約のない一意インデックスを持つことの目的を明確にできますか(Oracle)例えば、
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
これまでのところ、制約があるように見えます。しかし
create table test33(id int not null primary key,
test22_id int not null,
foreign key(test22_id) references test22(id) );
"ORA-02270: no matching unique or primary key for this column-list"
でも失敗します。私はこの振る舞いに完全に混乱しています。制約があるかどうか?
一意のインデックスなしで一意の制約を持つことができる理由を説明する多くの記事があります。それは明確であり、完全に理にかなっています。ただし、制約のない一意インデックスの理由はわかりません。
制約とインデックスは別個の論理エンティティです。たとえば、一意の制約は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.
しかし、まっすぐな一意の非関数ベースのインデックスについて話している場合、制約を作成するよりもインデックスを作成する方が本当に理にかなっているケースはおそらく比較的少ないでしょう。一方、実際に大きな違いを生むケースは比較的少ないです。主キー制約ではなく一意制約を参照する外部キー制約を宣言することはほとんどないため、インデックスを作成するだけで制約を作成しないことで何かを失うことはほとんどありません。
このコンテキストで役立つ可能性のある別のポイントは次のとおりです。既存の一意性制約を無効化/削除しても、基礎となる一意性インデックスは削除されません。一意のインデックスを明示的に削除する必要がありました。
一意性制約を宣言して条件付き一意性を作成することはできませんが、一意性インデックスを宣言して実行することはできます。
以下を実行しようとするとサポートされます:
alter table test22
add constraint test22_u
unique (id, case when tmp = 'aaa' then null else tmp end);
ORA-00904: : invalid identifier
ただし、一意のインデックスを使用して実行できる場合
create unique index test22_u
on test22 ( customer_id,
case when is_default = 'Y' then null else address_id end)