前言 最近在一次面試中,討論了一個這樣的問題:主鍵和索引有什麼區別?當時我的回答是這樣的:“主鍵就是加了唯一性約束的聚集索引。” “你確定你所說的是對的?” 面試官反問到。 “應該是對的。” 我不加思索地回答道。 “你回去後研究一下這個問題吧。” 難道我真的錯了? 第一次嘗試 當問題出現時,請用事實 ...
前言
最近在一次面試中,討論了一個這樣的問題:主鍵和索引有什麼區別?當時我的回答是這樣的:“主鍵就是加了唯一性約束的聚集索引。” “你確定你所說的是對的?” 面試官反問到。 “應該是對的。” 我不加思索地回答道。 “你回去後研究一下這個問題吧。”
難道我真的錯了?
第一次嘗試
當問題出現時,請用事實支持你的觀點。
首先,必須瞭解一些基本知識:對於一張表來說,聚集索引只能有一個,因為數據真實的物理存儲順序就是按照聚集索引存儲的。基於這個原理,現在可以用這樣的方案來測試:對一張表設置一個主鍵, 之後再建立一個聚集索引,假如聚集索引能創建成功, 表明主鍵就不是聚集索引, 如果不可以建立聚集索引,就表明主鍵是聚集索引。
--建立一張TABLE 同時設置主鍵
CREATE TABLE student
(
stud_id INT IDENTITY(1,1) NOT NULL,
stud_name NVARCHAR(50) NOT NULL,
CONSTRAINT pk_student PRIMARY KEY(stud_id)
);
接下來就嘗試對這張表建立一個聚集索引吧。
CREATE CLUSTERED INDEX index_stud_name ON student(stud_name);
執行這條語句的時候,SQLServer的消息框彈出了這樣的處理信息:“無法對 表 'student' 創建多個聚集索引。請在創建新聚集索引前刪除現有的聚集索引 'pk_student'。"
是不是我已經勝出了?
進一步思考
很大程度上,我應該對上述結果感到很滿意的。但謹慎的思維提醒我:會不會自己遺漏了什麼東西?
來看一下關於主鍵的定義吧,主鍵是表中的一個欄位或多個欄位,用來唯一地標識表中的一條記錄。唯一性是主鍵最主要的特性。在查閱建立主鍵的方法的時候, 一個之前被我完全忽略的創建方式突然出現在我的眼前, 在建立主鍵的時候可以聲明為CLUETERED(聚集)或NONCLUETERED(非聚集)!也就是說主鍵也可以聲明為非聚集索引,如下:
CREATE TABLE student
(
stud_id INT IDENTITY(1,1) NOT NULL,
stud_name NVARCHAR(20) NOT NULL,
CONSTRAINT pk_student PRIMARY KEY NONCLUSTERED (stud_id)
);
在SQLServer中,主鍵的創建必須依賴於索引,預設創建的是聚集索引,這就解釋了在上面的嘗試中為什麼表中已建立了聚集索引。
可見,真的是我錯了。
後續
園子里的朋友提到一個觀點,就是跟著主鍵而創建的索引可以被單獨刪除,經我測試過,這是不可以的。
--執行刪除索引語句
DROP INDEX pk_student ON student
SQLServer的消息框會彈出這樣的提示信息:”不允許對索引 'student.pk_student' 顯式地使用 DROP INDEX。該索引正用於 PRIMARY KEY 約束的強制執行。“
如果對索引執行強制刪除的話,如下圖操作:
結果是可以刪除的,但主鍵也會被跟著一起刪除,所以主鍵必須依賴於索引的觀點暫時是正確的。