当我有一个非唯一索引时违反了唯一约束

时间:2016-05-10 09:42:36

标签: sql oracle unique-constraint unique-index

在我的数据仓库中,我的列TABLE_UK上有唯一键(ID,IDATE,NAME,GENERATION,O_ID,NODE_ID),列PER_INDEX上有非唯一索引(ID,NAME,GENERATION,STRUCTURE_AREA,O_ID)

从源表加载数据时,我收到错误:

  

ORA-00001:违反了唯一约束(PER_INDEX)

我检查了唯一的列,但没有重复。

为什么我在非唯一索引上遇到此唯一约束违规错误?

另外,为了将数据加载到目标表中,我是否需要删除此索引,还是有其他方法可以执行此操作?

1 个答案:

答案 0 :(得分:1)

如果首先创建索引,则可以使用由非唯一索引备份的唯一约束:

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                    

请注意,如果您通过两个步骤创建约束,则约束不必与索引具有相同的名称 - 当您添加约束时,它将使用与约束所针对的列匹配的任何索引。当自动创建索引时,约束和索引具有相同的名称。

您无法加载违反该约束条件的数据,除非您将其删除,但因为它可能因为某些原因而无法轻易做到。您需要了解约束存在的原因,以及数据违反的原因 - 其中一个可能是错误的,但我们无法帮助您确定哪个。这既是商业决策,也是技术决策。