主键(primary key),一列 (或一组列),其值能够唯一区分表中的每个行。唯一标识表中每行的这个列(或这组列)称为主键。主键用来表示一个特定的行。没有主键,更新或删除表中特定行很困难,因为没有安全方法保证只涉及相关的行而不误伤其他行!
主键索引自动创建,如果不自增就会造成频繁页分裂,导致性能降低。
一个顾客表可以使用顾客编号列,而订单表可以使用订单ID,雇员表可以使用雇员ID或雇员社会保险号。
应该总是定义主键 虽然并非总需主键,但大多数数据库设计人员都应保证他们创建的每个表具有一个主键,以便以后的数据操纵和管理。
表中的任何列都可以作为主键,只要它满足以下主键值规则条件:
- 任两行不具相同的主键值
- 每行都必须具有一个主键值(主键列不允许NULL)
这里的规则是MySQL本身强制实施的。
除MySQL强制实施的规则外,还应该坚持的最佳实践:
- 不更新主键列中的值
- 不重用主键列的值
- 不在主键列中使用可能会更改的值 例如,如果使用一个名字作为主键以标识某个供应商,当该供应商合并和更改其 名字时,必须更改这个主键)
联合主键
- 好处 可以直观的看到某个重复字段的记录条数
主键A跟主键B组成联合主键 主键A跟主键B的数据可以完全相同,联合就在于主键A跟主键B形成的联合主键是唯一的。 联合主键体现在多个表上,复合主键体现在一个表中的多个字段。
复合主键
主键通常定义在表的一列上,但这并不是必需的,也可使用多个列作为主键。此时上述的条件必须应用到构成主键的所有列,所有列值的组合必须是唯一的(多列中的单个列的值可以不唯一)。
表的主键含有一个以上的字段组成,不使用无业务含义的自增id作为主键 将多个字段设置为主键,形成复合主键,这多个字段联合标识唯一性,其中,某几个主键字段值出现重复是没有问题的,只要不是有多条记录的所有主键值完全一样,就不算重复
超键
在关系中能唯一标识元组的属性集称为关系模式的超键。一个属性可以为作为一个超键,多个属性组合在一起也可以作为一个超键。超键包含候选键和主键。
候选键
是最小超键,即没有冗余元素的超键。
外键
在一个表中存在的另一个表的主键称此表的外键
主键的选择
数据库中的每一条记录都需要有一个唯一的标识,依据数据库第二范式,数据库中每一个表中都需要有一个唯一的主键,其他数据元素和主键一一对应。
- 使用业务字段作为主键,比如用户表,可使用手机号,email或身份证号
- 使用生成的唯一ID作为主键。
大部分场景第一种选择并不适用,比如评论表,难找到个业务字段作为主键,因为评论表难找到一个字段能唯一标识一条评论。而对于用户表来说,我们需要考虑的是作为主键的业务字段是否能够唯一标识一个人,一个人可以有多个email和手机号,一旦出现变更email或者手机号的情况,就需要变更所有引用的外键信息,所以使用email或者手机作为主键是不合适的。
身份证号码确实是用户的唯一标识,但是由于它的隐私属性,并不是一个用户系统的必须属性,你想想,你的系统如果没有要求做实名认证,那么肯定不会要求用户填写身份证号码的。并且已有的身份证号码是会变更的,比如在1999年时身份证号码就从15位变更为18位,但是主键一旦变更,以这个主键为外键的表也都要随之变更,这个工作量是巨大的。
因此,我更倾向于使用生成的ID作为数据库的主键。不单单是因为它的唯一性,更是因为一旦生成就不会变更,可以随意引用。
在单库单表的场景下,我们可以使用数据库的自增字段作为ID,因为这样最简单,对于开发人员来说也是透明的。
- 代理主键(推荐使用)
与业务无关的,无意义的数字序列。
- 不与业务耦合,因此更容易维护
- 通用的键策略能够减少要编写的源码数量,减少系统的总体拥有成本
- 自然主键 事物属性中的自然唯一标识