首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

Oracle 唯一約束 vs 唯一索引:本質差異、TOAD 介面操作與刪除行為深度解析

     編輯:Oracle 資料庫基礎

核心結論先行:一個建約束、一個只建索引

操作建立的物件資料字典記錄刪除時行為
CREATE UNIQUE CONSTRAINT1 個 Constraint + 1 個唯一索引USER_CONSTRAINTS + USER_INDEXES可 DROP CONSTRAINT KEEP INDEX 保留索引
CREATE UNIQUE INDEX僅 1 個唯一索引USER_INDEXES(無 Constraint 記錄)DROP INDEX 直接移除,資料可重複

本質關係:唯一約束內部透過建立唯一索引來強制執行。約束是邏輯層規則,索引是物理層實現。

TOAD 介面雙入口的迷思

TOAD 的「建立約束」與「建立索引」視窗分別提供「唯一」選項,易造成誤以為兩者等價:

  • Constraints 視窗 → Unique → 建立 CONSTRAINT + 隱含索引
  • Indexes 視窗 → Unique → 僅建立 INDEX

TOAD建立約束介面 TOAD建立索引介面

主鍵約束 vs 主鍵索引:結果完全一致

-- 方式 1:建立主鍵約束(推薦)
ALTER TABLE emp ADD CONSTRAINT pk_emp PRIMARY KEY(empno);
-- 產生:PK Constraint + 唯一索引(名稱通常同 PK 名或 SYS_Cxxxx)

-- 方式 2:建立唯一索引再指定為 PK(罕見)
CREATE UNIQUE INDEX pk_emp_idx ON emp(empno);
ALTER TABLE emp ADD CONSTRAINT pk_emp PRIMARY KEY(empno) USING INDEX pk_emp_idx;
-- 結果相同:PK Constraint + 指定索引

兩種路徑最終產生相同的物件組合,無功能差異。主鍵約束必須有唯一索引支撐。

唯一約束與唯一索引的實務差異場景

場景 1:刪除約束但保留索引效能

-- 業務暫時允許重複 Email,但查詢仍需索引加速
ALTER TABLE users DROP CONSTRAINT uk_users_email KEEP INDEX;
-- 索引保留,查詢不受影響;資料可插入重複 Email

-- 之後恢復業務規則
ALTER TABLE users ADD CONSTRAINT uk_users_email UNIQUE(email) USING INDEX uk_users_email;

場景 2:只需效能不需業務強制

-- 記錄表:查詢常用 correlation_id,但業務允許重複(不同來源系統)
CREATE UNIQUE INDEX idx_logs_corr_id ON logs(correlation_id);
-- 錯誤!唯一索引會阻擋重複值

-- 正確:建立非唯一索引
CREATE INDEX idx_logs_corr_id ON logs(correlation_id);

場景 3:匯入資料前暫時移除約束

-- 唯一約束:可停用驗證,保留索引結構
ALTER TABLE emp DISABLE CONSTRAINT uk_emp_email KEEP INDEX;
-- 大量匯入...
ALTER TABLE emp ENABLE NOVALIDATE CONSTRAINT uk_emp_email;  -- 不驗證既有資料

-- 唯一索引:只能刪除重建
DROP INDEX uk_emp_email;
-- 匯入...
CREATE UNIQUE INDEX uk_emp_email ON emp(email);  -- 若資料有重複會失敗

前端開發視角:行為一致,維護不同

對應用程式而言,兩者皆阻擋重複值插入,拋出 ORA-00001。差異在於:

  • 錯誤訊息:約束違規顯示約束名;索引違規顯示索引名
  • 中繼資料查詢:USER_CONSTRAINTS 可查約束,工具常依此產生 ER 圖
  • ORM 框架映射:Hibernate/JPA @UniqueConstraint 對應約束,@Index(unique=true) 對應索引

最佳實踐建議

  1. 業務規則 → 唯一約束:Email、身分證號、業務單號等「語義上不可重複」的欄位,必須建立 UNIQUE CONSTRAINT,語意清晰、工具支援完整。
  2. 純效能需求 → 非唯一索引:高頻查詢欄位但允許重複,建立普通 CREATE INDEX。
  3. 避免單獨建立唯一索引:除非極特殊場景(如場景 1 臨時保留索引),否則易造成「有索引無約束」的文檔缺失。
  4. 命名規範:UK_<表>_<欄位> 同時用於約束與其支撐索引,IDX_<表>_<欄位> 用於非唯一索引。

驗證腳本:查看某欄位的約束與索引關係

SELECT 
    c.constraint_name,
    c.constraint_type,  -- 'U' = Unique, 'P' = Primary Key
    c.status,
    i.index_name,
    i.uniqueness,
    i.status AS index_status
FROM user_constraints c
LEFT JOIN user_indexes i 
    ON c.index_name = i.index_name
    AND c.table_name = i.table_name
WHERE c.table_name = 'EMP'
  AND c.constraint_type IN ('U','P');

總結

Oracle 中唯一約束 = 唯一索引 + 語義標籤。主鍵約束同理。理解「約束是什麼、索引是怎麼做到的」關係,能正確選擇建立方式、設計刪除/停用策略、與 ORM 框架無縫對接。原則:有業務語義用約束,純效能用索引。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved