Oracle主鍵、唯一鍵與唯一索引的區別
Oracle主鍵、唯一鍵與唯一索引的區別
一般,我們看到術語“索引”和“鍵”交換使用,但實際上這兩個是不同的。索引是儲存在中的一個物理結構,鍵純粹是一個邏輯概念。鍵代表建立來實施業務規則的完整性約束。索引和鍵的混淆通常是由於資料庫使用索引來實施完整性約束。
接下來我們看看資料庫中的主鍵約束、唯一鍵約束和唯一索引的區別。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
SQL>select*fromv$version; BANNER -------------------------------------------------------------------------------- OracleDatabase11g Enterprise Edition Release 11.2.0.1.0 - Production PL/SQL Release 11.2.0.1.0 - Production CORE 11.2.0.1.0 Production TNSforLinux: Version 11.2.0.1.0 - Production NLSRTL Version 11.2.0.1.0 - Production
SQL>createtabletest ( 2 idint, 3 namevarchar2(20), 4 constraintpk_testprimarykey(id)) 5 tablespace users; Tablecreated.
SQL>selectconstraint_name, constraint_typefromuser_constraints; CONSTRAINT_NAME C ------------------------------ - PK_TEST P |
在test表中,我們指定了ID列作為主鍵,Oracle資料庫會自動建立一個同名的唯一索引:
1 2 3 4 5 6 7 |
SQL>selectindex_name, index_type, uniqueness, tablespace_name 2 fromuser_indexes 3 wheretable_owner='SCOTT' 4 andtable_name ='TEST'; INDEX_NAME INDEX_TYPE UNIQUENES TABLESPACE_NAME -------------------- -------------------- --------- ------------------------------ PK_TEST NORMAL UNIQUE USERS |
此時,如果我們再試圖在ID列上建立一個唯一索引,Oracle會報錯,因為該列上已經存在一個唯一索引:
1 2 3 4 5 |
SQL>createuniqueindexidx_test_ukontest(id); createuniqueindexidx_test_ukontest(id) * ERRORatline 1: ORA-01408: suchcolumnlist already indexed |
即使建立非唯一索引也不行:
1 2 3 4 5 |
SQL>createindexidx_test_idontest(id); createindexidx_test_idontest(id) * ERRORatline 1: ORA-01408: suchcolumnlist already indexed |
那麼唯一鍵約束的情況是怎樣的呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 |
SQL>droptabletest purge; Tabledropped.
SQL>createtabletest( 2 idint, 3 namevarchar2(20), 4 constraintuk_testunique(id)); Tablecreated.
SQL>selectconstraint_name, constraint_typefromuser_constraints; CONSTRAINT_NAME C ------------------------------ - UK_TEST U |
檢視此時的索引情況:
1 2 3 4 5 6 7 |
SQL>selectindex_name, index_type, uniqueness, tablespace_name 2 fromuser_indexes 3 wheretable_owner='SCOTT' 4 andtable_name ='TEST'; INDEX_NAME INDEX_TYPE UNIQUENES TABLESPACE_NAME -------------------- -------------------- --------- ------------------------------ UK_TEST NORMAL UNIQUE USERS |
Oracle同樣自動建立了一個同名的唯一索引,而且也不允許再在此列上建立唯一索引或非唯一索引。
我們知道,主鍵約束要求列值非空(NOT NULL),那麼唯一鍵約束是否也要求非空呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
SQL>insertintotestvalues(1,'Sally'); 1 row created.
SQL>insertintotestvalues(null,'Tony'); 1 row created.
SQL>insertintotestvalues(null,'Jack'); 1 row created.
SQL>select*fromtest; IDNAME ---------- -------------------- 1 Sally Tony Jack |
從實驗結果來看,唯一鍵約束並沒有非空要求。
接下來我們看看唯一索引對列值的非空要求有什麼不同。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
SQL>droptabletest purge; Tabledropped.
SQL>createtabletest( 2 idint, 3 namevarchar2(20)); Tablecreated.
SQL>createuniqueindexidx_test_idontest (id); Indexcreated.
SQL>insertintotestvalues(1,'Sally'); 1 row created.
SQL>insertintotestvalues(null,'Tony'); 1 row created.
SQL>insertintotestvalues(null,'Jack'); 1 row created.
SQL>select*fromtest; IDNAME ---------- -------------------- 1 Sally Tony Jack |
透過實驗,我們看出唯一索引與唯一鍵約束一樣對列值非空不做要求。
如果我們讓主鍵約束或者唯一鍵約束失效,Oracle自動建立的唯一索引是否會受到影響?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
SQL>droptabletest purge; Tabledropped. SQL>createtabletest( 2 idint, 3 namevarchar2(20), 4 constraintuk_testunique(id)); Tablecreated.
SQL>selectindex_name, index_type, uniquenessfromuser_indexes; INDEX_NAME INDEX_TYPE UNIQUENES ------------------------------ --------------------------- --------- UK_TEST NORMAL UNIQUE
SQL>altertabletest disableconstraintuk_test; Tablealtered.
SQL>selectindex_name, index_type, uniquenessfromuser_indexes; norowsselected
SQL>altertabletest disableconstraintuk_test; Tablealtered.
SQL>selectindex_name, index_type, uniquenessfromuser_indexes; INDEX_NAME INDEX_TYPE UNIQUENES ------------------------------ --------------------------- --------- UK_TEST NORMAL UNIQUE |
當主鍵約束或者唯一鍵約束失效時,Oracle會標記隱式建立的唯一索引為刪除狀態。
=====================================================
Using Nonunique Indexes to Enforce Uniqueness
You can use an existing nonunique index on a table to enforce uniqueness, either for UNIQUE constraints or the unique ect of a PRIMARY KEY constraint. The advantage of this approach is that the index remains available and valid when the constraint is disabled. Therefore, enabling a disabled UNIQUE or PRIMARY KEY constraint does not require rebuilding the unique index associated with the constraint. This can yield significant time savings on enable operations for large tables.
Using a nonunique index to enforce uniqueness also lets you eliminate redundant indexes. You do not need a unique index on a primary key column if that column is included as the prefix of a composite index. You can use the existing index to enable and enforce the constraint. You also save significant space by not duplicating the index. However, if the existing index is partitioned, then the partitioning key of the index must also be a subset of the UNIQUE key; otherwise, Database creates an additional unique index to enforce the constraint.
=====================================================
如果我們先建立唯一索引,再建立主鍵或者唯一鍵約束,情況又會怎樣呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
SQL>droptabletest purge; Tabledropped.
SQL>createtabletest( 2 idint, 3 namevarchar2(20)); Tablecreated.
SQL>createuniqueindexidx_test_idontest (id); Indexcreated.
SQL>selectindex_name, index_type, uniqueness 2 fromuser_indexes 3 wheretable_owner ='SCOTT' 4 andtable_name ='TEST'; INDEX_NAME INDEX_TYPE UNIQUENES ------------------------------ --------------------------- --------- IDX_TEST_ID NORMAL UNIQUE
SQL>altertabletestaddconstraintuk_testunique(id); Tablealtered.
SQL>selectindex_name, index_type, uniqueness 2 fromuser_indexes 3 wheretable_owner ='SCOTT' 4 andtable_name ='TEST'; INDEX_NAME INDEX_TYPE UNIQUENES ------------------------------ --------------------------- --------- IDX_TEST_ID NORMAL UNIQUE
SQL>selectconstraint_name, constraint_type 2 fromuser_constraints 3 wheretable_name ='TEST'; CONSTRAINT_NAME C ------------------------------ - UK_TEST U
SQL>altertabletest disableconstraintuk_test; Tablealtered.
SQL>selectconstraint_name, constraint_type, status 2 fromuser_constraints 3 wheretable_name ='TEST'; CONSTRAINT_NAME C STATUS ------------------------------ - -------- UK_TEST U DISABLED
SQL>selectindex_name, index_type, uniqueness, status 2 fromuser_indexes 3 wheretable_owner ='SCOTT' 4 andtable_name ='TEST'; INDEX_NAME INDEX_TYPE UNIQUENES STATUS ------------------------------ --------------------------- --------- -------- IDX_TEST_ID NORMAL UNIQUE VALID
實驗結果表明,先建立的唯一索引不受約束失效的影響。
SCOTT@ orcl>createindexidx_test_idontest(id); Indexcreated.
SCOTT@ orcl>altertabletestaddconstraintuk_testunique(id); Tablealtered.
SCOTT@ orcl>insertintotestvalues(1,'liu'); insertintotestvalues(1,'liu') * ERRORatline 1: ORA-00001:uniqueconstraint(SCOTT.UK_TEST) violated
SCOTT@ orcl>altertabletestdropconstraintuk_test; Tablealtered.
SCOTT@ orcl>insertintotestvalues(1,'liu'); 1 row created.
SCOTT@ orcl>deletefromtestwhereid=1andrownum=1; 1 row deleted.
SCOTT@ orcl>select*fromtest; IDNAME ---------- -------------------- yang 1 liu
SCOTT@ orcl>createuniqueindexidx_test_idontest(id); Indexcreated.
SCOTT@ orcl>altertabletestaddconstraintuk_testunique(id); Tablealtered.
SCOTT@ orcl>altertabletestdropconstraintuk_test; Tablealtered.
SCOTT@ orcl>insertintotestvalues(1,'liu'); insertintotestvalues(1,'liu') * ERRORatline 1: ORA-00001:uniqueconstraint(SCOTT.IDX_TEST_ID) violated |
總結如下:
(1)主鍵約束和唯一鍵約束均會隱式建立同名的唯一索引,當主鍵約束或者唯一鍵約束失效時,隱式建立的唯一索引會被刪除;
(2)主鍵約束要求列值非空,而唯一鍵約束和唯一索引不要求列值非空;
(3)相同欄位序列不允許重複建立索引;
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29119536/viewspace-1100502/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 主鍵、自增主鍵、主鍵索引、唯一索引概念區別與效能區別索引
- Oracle主鍵約束、唯一鍵約束、唯一索引的區別(轉)Oracle索引
- 【INDEX】Oracle中主鍵、唯一約束與唯一索引之區別IndexOracle索引
- 主鍵和唯一索引的區別索引
- 主鍵(PK)與非空唯一索引(Unique Index)的區別索引Index
- ORACLE: 查詢(看)表的主鍵、外來鍵、唯一性約束和索引Oracle索引
- 唯一索引和非唯一索引ROWID儲存的區別索引
- MYSQL中的普通索引,主健,唯一,全文索引區別MySql索引
- indexedDB 索引與primarykey主鍵區別Index索引
- 查詢(看)表的主鍵、外來鍵、唯一性約束和索引索引
- 唯一性約束和唯一性索引的區別索引
- 主鍵與主鍵索引的關係索引
- 【唯一】DISTINCT與UNIQUE的“區別”
- 主鍵索引 (聚集索引) 和普通索引 (輔助索引) 的區別索引
- 關於唯一性索引造成堵塞和非唯一性索引造成堵塞的區別索引
- Oracle GoldenGate 針對表沒有主鍵或唯一索引的解決方案OracleGo索引
- Oracle GoldenGate 針對表沒有主鍵或唯一索引的解決方案OracleGo索引
- 生成按時間增長的全域性唯一主鍵
- 資料庫約束 主鍵-唯一性-Check-外來鍵資料庫
- 唯一索引索引
- MySQL 處理插入過程中的主鍵唯一鍵重複值辦法MySql
- Oracle與GreatSQL差異:更改唯一索引列OracleSQL索引
- [專案踩坑] MySQL 分割槽:分割槽鍵和唯一索引主鍵的關係,解決報錯 A PRIMARY KEYMySql索引
- 【PK】Oracle 10g刪除主鍵約束後無法刪除唯一約束索引問題的模擬與分析Oracle 10g索引
- MySQL <唯一索引>MySql索引
- oracle資料庫(ORA-02270:此列表的唯一或主鍵不匹配)Oracle資料庫
- Oracle主鍵與複合主鍵的效能分析Oracle
- 解決方案系列-叢集選主(基於 DB 唯一鍵)
- MongoDB之索引(唯一索引)MongoDB索引
- 分散式系統唯一主鍵識別符號ID生成機制比較 - Encore分散式符號
- Oracle刪除主鍵保留索引的方法Oracle索引
- 資料庫聚簇索引——not null條件對唯一鍵索引成為聚簇索引的影響資料庫索引Null
- MySQL 唯一索引和普通索引MySql索引
- 約束:確保資料的完整性(主鍵,唯一,檢查,預設,非空,外來鍵)
- MySQL·捉蟲動態·唯一鍵約束失效MySql
- 唯一index和非唯一index中leaf node裡rowid的一點區別。Index
- MySql插入唯一鍵衝突的三種可選方式MySql
- 表上建立唯一性索引,SQL*Loader用或不用dirdect的區別索引SQL