數(shù)據(jù)庫(kù)表中已有重復(fù)數(shù)據(jù)添加唯一鍵(唯一約束)
問(wèn)題描述
以 demo 舉例,模擬真實(shí)場(chǎng)景。
表 TEST_TABLE 有如下字段和數(shù)據(jù):id 是主鍵,code 沒(méi)有設(shè)置鍵和索引
| ID | CODE |
|---|---|
| 1 | code1 |
| 2 | code2 |
| 3 | code2 |
| 4 | code2 |
| 5 | code3 |
通過(guò)以上表中數(shù)據(jù)可以看出 code 是有重復(fù)數(shù)據(jù)的,此時(shí)如果我們直接添加唯一鍵,會(huì)報(bào)錯(cuò)。
通過(guò) PL/SQL 可視化操作,或者通過(guò) SQL 語(yǔ)句添加(ENABLE NOVALIDATE 的作用是約束新增數(shù)據(jù)但不會(huì)驗(yàn)證已有數(shù)據(jù)):ALTER TABLE TEST_TABLE ADD CONSTRAINT UK_TEST_TABLE_CODE UNIQUE(CODE) ENABLE NOVALIDATE;
即使用到了 ENABLE NOVALIDATE 也報(bào)錯(cuò),如下:
ORA-02299: cannot validate(TESTUSER.TEST_TABLE.UK_TEST_TABLE_CODE)-duplicate keys found
--Create/Recreate primary, unique and foreign key constraints alter table TEST_TABLE and constraint UK_TEST_TABLE_CODE unique(CODE) novalidate
解決方案
- 先添加普通索引
CREATE INDEX IDX_TEST_TABLE_CODE ON TEST_TABLE(CODE);
- 再添加唯一鍵
ALTER TABLE TEST_TABLE ADD CONSTRAINT UK_TEST_TABLE_CODE UNIQUE(CODE) ENABLE NOVALIDATE;
如果你對(duì)上面提到的基本概念不太清楚,建議繼續(xù)往下看,或者查找資料去學(xué)習(xí),然后多在測(cè)試數(shù)據(jù)庫(kù)中模擬“犯罪現(xiàn)場(chǎng)”,然后進(jìn)行還原問(wèn)題、找問(wèn)題、分析問(wèn)題和解決問(wèn)題。
基本概念
鍵、索引、約束的區(qū)別
一般,我們看到術(shù)語(yǔ)“索引”和“鍵”交換使用,但實(shí)際上這兩個(gè)是不同的。索引是存儲(chǔ)在數(shù)據(jù)庫(kù)中的一個(gè)物理結(jié)構(gòu),鍵純粹是一個(gè)邏輯概念。鍵代表創(chuàng)建來(lái)實(shí)施業(yè)務(wù)規(guī)則的完整性約束。索引和鍵的混淆通常是由于數(shù)據(jù)庫(kù)使用索引來(lái)實(shí)施完整性約束。
- 主鍵索引和主鍵有什么關(guān)系?
主鍵索引是創(chuàng)建主鍵的時(shí)候系統(tǒng)自動(dòng)創(chuàng)建的索引,主鍵要求不重復(fù),不為空,但是他如何判斷有效率呢?當(dāng)然是建索引了,老是全表遍歷還不瘋掉。
所以建立主鍵會(huì)自動(dòng)的建立主鍵索引。
主鍵和唯一鍵的區(qū)別在于唯一鍵可以為空,主鍵不可以
建立唯一約束和唯一索引又什么區(qū)別?
同理,建立唯一約束的時(shí)候,也會(huì)自動(dòng)的創(chuàng)建唯一索引。建立唯一索引可以說(shuō)是唯一約束的一種手段。
基本上,實(shí)現(xiàn)起來(lái)是沒(méi)有什么區(qū)別的。如果實(shí)在理解不了,就當(dāng)一樣好了。
- 聚簇索引和非聚簇索引有何區(qū)別?
這個(gè)上邊已經(jīng)講和很詳細(xì)了,還附有兩篇文章,這里就不說(shuō)了。
- 約束和主鍵有什么區(qū)別?
約束一般有主鍵約束,外鍵約束,唯一約束等。
分別為primary key,foreign key,unique 其中主鍵約束只是約束的一種。
其實(shí)他們是不同概念的東西。