Oracle

具有重複值的列的唯一約束

  • March 25, 2022

如何在不干擾現有數據的情況下對具有重複值的列創建唯一約束。我已經嘗試過以下方法,

先創建普通索引,再創建唯一約束。但是在這種情況下,我將無法刪除首先創建的未使用索引。我不想要那個。

還有其他可以在生產環境中應用的清潔方法嗎?

我確定這已經被問過了,但是..來自Oracle 文件

在頁面的下方,當您查找每個約束狀態時:

驗證 | NOVALIDATE VALIDATE 和 NOVALIDATE 的行為始終取決於約束是啟用還是禁用,無論是顯式還是預設。因此,它們在“啟用條款”和“禁用條款”的上下文中進行描述。

ENABLE 子句 如果要將約束應用​​於表中的數據,請指定 ENABLE。

如果啟用唯一鍵或主鍵約束,並且鍵上不存在索引,則 Oracle 數據庫會創建唯一索引。除非您在隨後禁用約束時指定 KEEP INDEX,否則每次重新啟用約束時都會刪除此索引,並且數據庫會重建索引。

您還可以通過創建新的主鍵和最初禁用的唯一約束來避免重建索引並消除冗餘索引。然後創建(或使用現有的)非唯一索引來強制執行約束。Oracle 在禁用約束時不會刪除非唯一索引,因此便於後續的 ENABLE 操作。

ENABLE VALIDATE 指定所有新舊數據也符合約束。啟用的驗證約束保證所有數據都是有效的,並將繼續有效。

如果表中的任何行違反完整性約束,則約束保持禁用狀態,Oracle 返回錯誤。如果所有行都符合約束,則 Oracle 啟用約束。隨後,如果新數據違反了約束,則 Oracle 不執行該語句並返回一個錯誤,指示違反了完整性約束。

如果您將主鍵約束置於 ENABLE VALIDATE 模式,則驗證過程將驗證主鍵列是否不包含空值。為避免這種成本,請在將數據輸入列之前和啟用表的主鍵約束之前,將主鍵中的每一列標記為 NOT NULL。

ENABLE NOVALIDATE 確保對受約束數據的所有新 DML 操作都符合約束。此子句不確保表中的現有數據符合約束。

因此,您可能希望在約束結束時指定它是 ENABLE NOVALIDATE。這是一個例子

ALTER TABLE my_table ADD CONSTRAINT my_constraint UNIQUE (my_columns) ENABLE NOVALIDATE;

顯然,僅此一項仍會引發 ORA-2299,因為 Oracle 仍在嘗試在創建時使用索引來支持UNIQUE約束。UNIQUE解決這個問題的最簡單方法是首先創建(非唯一)索引。

CREATE INDEX my_index ON my_table (my_columns);
ALTER TABLE my_table ADD CONSTRAINT my_constraint UNIQUE (my_columns) ENABLE NOVALIDATE;

如果索引包含您想要的唯一鍵列,請首先刪除索引。然後執行以下命令

Alter table <table_name> add constraint constraint_name 
unique(column_name) novalidate deferrable;

引用自:https://dba.stackexchange.com/questions/144674