如果您先创建索引,则可以有一个由非唯一索引支持的唯一约束:
create table t42 (id number);
Table T42 created.
create index per_index on t42(id);
Index PER_INDEX created.
alter table t42 add constraint per_unique unique (id);
Table T42 altered.
select index_name, uniqueness
from user_indexes where table_name = 'T42';
INDEX_NAME UNIQUENES
------------------------------ ---------
PER_INDEX NONUNIQUE
select constraint_name, constraint_type, status, deferrable, index_name
from user_constraints where table_name = 'T42';
CONSTRAINT_NAME C STATUS DEFERRABLE INDEX_NAME
------------------------------ - -------- -------------- ------------------------------
PER_UNIQUE U ENABLED NOT DEFERRABLE PER_INDEX
从名称看来,它很可能是先作为索引添加的,然后再将约束置于顶部。
分两步执行此操作的一个原因是,如果您知道现有数据不是唯一的,但您希望所有新数据都是唯一的;然后您可以创建一个非唯一索引,并使用 novalidate 子句添加约束:
alter table t42 add constraint per_unique unique (id) novalidate;
添加新行时,仍然可以使用非唯一索引快速检查是否已经存在匹配条目,如果存在,约束可以抛出异常。对于该检查,索引是否唯一并不重要。唯一真正的区别是检查可能得到不止一个现有匹配,但约束只关心它是非零的。
如果您使唯一约束可延迟,Oracle 也会自动创建非唯一索引;使用唯一索引会立即引发异常,因为无法推迟检查:
create table t42 (id number);
Table T42 created.
alter table t42 add constraint per_unique unique (id) deferrable;
Table T42 altered.
select index_name, uniqueness
from user_indexes where table_name = 'T42';
INDEX_NAME UNIQUENES
------------------------------ ---------
PER_UNIQUE NONUNIQUE
select constraint_name, constraint_type, status, deferrable, index_name
from user_constraints where table_name = 'T42';
CONSTRAINT_NAME C STATUS DEFERRABLE INDEX_NAME
------------------------------ - -------- -------------- ------------------------------
PER_UNIQUE U ENABLED DEFERRABLE PER_UNIQUE
请注意,如果您分两步创建约束,则约束不必与索引具有相同的名称 - 当您添加约束时,它将使用与约束所针对的列匹配的任何索引。自动创建索引时,约束和索引具有相同的名称。
除非您将其删除,否则您无法加载违反该约束的数据,但由于它的存在可能是有原因的,因此不能轻易采取行动。您需要了解约束存在的原因,以及您的数据违反约束的原因——其中一个可能是错误的,但我们无法真正帮助您确定哪个。这是一项业务决策,也是一项技术决策。