mysql菜鸟教程
8.1 主键(PRIMARY KEY)唯一标识
在现实生活中,每个人都有一个唯一的身份证号,每个学生都有一个唯一的学号,每个订单都有一个唯一的订单号。在数据库的世界里,主键(PRIMARY KEY) 就是扮演这个角色的核心概念——它是表中用于唯一标识每一行数据的列或列的组合。
一、主键的核心作用
为什么需要主键?
-
唯一标识:确保表中每行记录都能被唯一地找到。就像身份证号能唯一确定一个人。
-
数据完整性:防止表中出现重复的记录,保证数据的准确性。
-
快速查找:主键会自动创建索引,基于主键的查询速度极快。
-
建立关系:主键是与其他表建立关联(外键)的基础。
主键必须具备的特性
特性
说明
唯一性
整个表中,主键列的值必须唯一,不能重复。
非空性
主键列的值不能为 NULL。
稳定性
主键的值一旦确定,最好不要更新(理想情况下永久不变)。
最小性
如果是复合主键,应尽量选择最少的列组合,避免过大索引。
二、主键的创建方式
在 MySQL 中,可以在创建表时定义主键,也可以在表创建后添加。我们来看看几种常见的方式。
1. 单列主键(列级约束)
直接在列定义后面添加 PRIMARY KEY 关键字:
CREATE TABLE students (
id INT PRIMARY KEY, -- 将 id 设为主键
name VARCHAR(50) NOT NULL,
age TINYINT
);
这种方式简洁明了,适合单列主键。
2. 单列主键(表级约束)
在列定义结束后,单独声明主键:
CREATE TABLE students (
id INT,
name VARCHAR(50) NOT NULL,
age TINYINT,
PRIMARY KEY (id) -- 表级约束定义主键
);
表级约束可以为主键指定名称(可选):
CREATE TABLE students (
id INT,
name VARCHAR(50) NOT NULL,
PRIMARY KEY pk_student_id (id) -- 为主键起名 pk_student_id
);
3. 复合主键(多列组合主键)
当单列不足以唯一标识一行时,可以用多列组合作为主键。例如,订单明细表中,同一订单号下可能有多个商品,但订单号+商品号的组合可以唯一确定一行:
CREATE TABLE order_details (
order_id INT,
product_id INT,
quantity INT,
price DECIMAL(10,2),
PRIMARY KEY (order_id, product_id) -- 复合主键
);
注意:复合主键的每一列都不能为 NULL,且组合值必须唯一。
4. 建表后添加主键
如果表已经创建,可以使用 ALTER TABLE 添加主键:
ALTER TABLE students ADD PRIMARY KEY (id);
但要注意,添加主键前必须保证该列没有重复值和 NULL 值,否则操作会失败。
5. 删除主键
ALTER TABLE students DROP PRIMARY KEY;
删除主键时要小心,如果该主键被其他表的外键引用,需要先处理外键。
三、自增主键(AUTO_INCREMENT)
实际开发中,最常用的主键类型是自增整数主键。使用 AUTO_INCREMENT 属性,数据库会自动为每行生成一个唯一的递增值,省去了手动赋值的麻烦。
语法示例
CREATE TABLE students (
id INT AUTO_INCREMENT PRIMARY KEY, -- 自增主键
name VARCHAR(50) NOT NULL
);
插入数据时,可以不为 id 指定值,或指定为 NULL 或 0,数据库会自动填充:
INSERT INTO students (name) VALUES ('张三'); -- id 自动生成 1
INSERT INTO students VALUES (NULL, '李四'); -- id 自动生成 2
INSERT INTO students VALUES (0, '王五'); -- id 自动生成 3(0 也会触发自增)
自增的细节
-
默认起始值为 1,步长为 1。
-
删除最大记录后,新记录不会复用被删除的值(除非手动重置)。
-
可以使用 LAST_INSERT_ID() 函数获取最后生成的 ID。
-
可以手动设置自增起始值:ALTER TABLE students AUTO_INCREMENT = 1000;
四、主键选择策略:用自然键还是代理键?
在设计主键时,有两种常见的选择:
类型
定义
优点
缺点
例子
自然键
利用业务中已有的唯一属性做主键
业务意义明确,无需额外列
可能不稳定(如手机号会变)、可能过长(如身份证号18位)、可能重复(如重名)
身份证号、邮箱、学号
代理键
创建一个与业务无关的列做主键(通常是自增整数或 UUID)
简单、稳定、高效、易于管理
无业务含义,可能需要在查询时关联其他列
自增 id、UUID
推荐做法
-
首选代理键:绝大多数情况下,使用自增整数作为主键是最稳妥的选择,尤其适合 OLTP 系统。
-
慎用自然键:除非你能保证该业务属性绝对唯一、永不改变、且长度适中(如国家代码、某些唯一编码)。
-
复合主键:尽量少用,除非逻辑上确实需要(如多对多关系的中间表)。复合主键可能导致索引变大,查询复杂度增加。
五、主键使用注意事项
-
主键列不能为 NULL:这是基本要求,插入时必须提供值(自增列会自动生成)。
-
不要频繁更新主键:主键是其他表引用它的基础,更新主键会引发连锁反应(外键更新),应尽量避免。
-
主键不宜过长:主键会在索引中存储,过长的主键(如 UUID 字符串)会占用大量空间,影响性能。推荐使用整数类型。
-
每个表只能有一个主键,但可以有多个唯一索引(UNIQUE)。
-
主键会自动创建索引,所以基于主键的查询很快。
六、实战练习
-
创建一个 users 表,使用自增主键 id,包含 username(唯一)、email、created_at 字段。
-
创建一个 courses 表,使用课程编号 course_code(如 'CS101')作为自然主键。
-
创建一个 student_course 表(学生选课表),使用复合主键 (student_id, course_id),并插入一些示例数据。
-
尝试向 students 表插入两条相同 id 的数据,观察错误。
-
删除某个表的主键,然后再重新添加。
主键要点总结
方面
要点
定义
唯一标识表中每一行的列或列组合
特性
唯一、非空、稳定、最小
创建方式
列级约束、表级约束、ALTER TABLE 添加
自增主键
AUTO_INCREMENT
配合主键使用,最常用
复合主键
多列组合,用于多对多关系表
选择策略
优先使用代理键(自增整数),慎用自然键和复合主键
重要性
数据完整性的基石,也是表间关联的桥梁
主键是数据库设计的核心,一个设计良好的主键能让后续的数据操作和关系建立事半功倍。记住:每个表都应该有一个主键,这是数据完整性的第一条法则。

发表评论
所有评论