2016-05-10 109 views
-1

在我的數據倉庫中,我有一個表,其中列(ID,IDATE,NAME,GENERATION,O_ID,NODE_ID)上的唯一鍵TABLE_UK和列(ID,NAME,GENERATION,STRUCTURE_AREA,O_ID)上的非唯一索引PER_INDEX當我有一個非唯一索引時違反了唯一約束條件

雖然從源表裝載數據我收到一個錯誤:

ORA-00001: unique constraint (PER_INDEX) violated

我查了獨特的列,但沒有重複。

爲什麼我在非唯一索引上得到這個唯一的約束違規錯誤?

另外,爲了將數據加載到目標表中,我是否需要刪除此索引或者是否有其他方法來執行此操作?

+1

您可以發表您的表的完整DDL,或至少描述一下'PER_INDEX'嗎? – Aleksej

+0

您可以擁有唯一的由非唯一索引支持的約束。 'user_indexes'和'user_constraints'爲你的表顯示什麼? –

回答

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      

注意約束不必具有相同的名稱作爲索引,如果你在兩個步驟創建它們 - 當您添加約束時,它將使用與約束所針對的列匹配的任何索引。當自動創建索引時,約束和索引具有相同的名稱。


不能裝載有違反約束,除非你將其刪除的數據,但它可能有一個原因,它是不是輕率地做。你需要理解爲什麼約束存在,以及爲什麼你的數據違反了它 - 其中一個可能是錯誤的,但我們不能真正幫你決定。這是一個商業決策,也是一個技術問題。

+0

所以你的意思是一個非唯一索引可以作爲表的唯一約束?索引'PER_INDEX'具有非唯一性,屬於正常類型。 – priya77

+0

@ priya77 - 約束使用非唯一索引,是的;我不確定它在底層做了什麼,但我想它可以快速使用索引來查看是否已經存在違反約束的值。爲此目的,索引本身是否是唯一的並不重要。 –

+0

我的索引是爲性能目的而創建的。我在源表中檢查如下: 通過ID,NAME,GENERATION,STRUCTURE_AREA,O_ID從target_table組中選擇count(*),ID,NAME,GENERATION,STRUCTURE_AREA,O_ID (*)> 1; 此查詢返回 – priya77