最近在一次面试中,讨论了一个这样的问题:主键和索引有什么区别?当时个人回答是这样的:“主键就是加了惟一性约束的汇集索引。” “你肯定你所说的是对的?” 面试官反问到。 “应该是对的。” 我不加思索地回答道。 “你回去后研究一下这个问题吧。”面试
难道我真的错了?测试
当问题出现时,请用事实支持你的观点。spa
首先,必须了解一些基本知识:对于一张表来讲,汇集索引只能有一个,由于数据真实的物理存储顺序就是按照汇集索引存储的。基于这个原理,如今能够用这样的方案来测试:对一张表设置一个主键, 以后再创建一个汇集索引,假如汇集索引能建立成功, 代表主键就不是汇集索引, 若是不能够创建汇集索引,就代表主键是汇集索引。code
--创建一张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) );
接下来就尝试对这张表创建一个汇集索引吧。blog
CREATE CLUSTERED INDEX index_stud_name ON student(stud_name);
执行这条语句的时候,SQLServer的消息框弹出了这样的处理信息:“没法对 表 'student' 建立多个汇集索引。请在建立新汇集索引前删除现有的汇集索引 'pk_student'。"索引
是否是我已经胜出了?class
很大程度上,我应该对上述结果感到很满意的。但谨慎的思惟提醒我:会不会本身遗漏了什么东西?原理
来看一下关于主键的定义吧,主键是表中的一个字段或多个字段,用来惟一地标识表中的一条记录。惟一性是主键最主要的特性。在查阅创建主键的方法的时候, 一个以前被我彻底忽略的建立方式忽然出如今个人眼前, 在创建主键的时候能够声明为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中,主键的建立必须依赖于索引,默认建立的是汇集索引,这就解释了在上面的尝试中为何表中已创建了汇集索引。im
可见,真的是我错了。
园子里的朋友提到一个观点,就是跟着主键而建立的索引能够被单独删除,经我测试过,这是不能够的。
--执行删除索引语句 DROP INDEX pk_student ON student
SQLServer的消息框会弹出这样的提示信息:”不容许对索引 'student.pk_student' 显式地使用 DROP INDEX。该索引正用于 PRIMARY KEY 约束的强制执行。“
若是对索引执行强制删除的话,以下图操做:
结果是能够删除的,但主键也会被跟着一块儿删除,因此主键必须依赖于索引的观点暂时是正确的。