mysql菜鸟教程

专栏导航

8.1 主键(PRIMARY KEY)唯一标识

      在现实生活中,每个人都有一个唯一的身份证号,每个学生都有一个唯一的学号,每个订单都有一个唯一的订单号。在数据库的世界里,主键(PRIMARY KEY) 就是扮演这个角色的核心概念——它是表中用于唯一标识每一行数据的列或列的组合。

一、主键的核心作用

为什么需要主键?

  1. 唯一标识:确保表中每行记录都能被唯一地找到。就像身份证号能唯一确定一个人。

  2. 数据完整性:防止表中出现重复的记录,保证数据的准确性。

  3. 快速查找:主键会自动创建索引,基于主键的查询速度极快。

  4. 建立关系:主键是与其他表建立关联(外键)的基础。

主键必须具备的特性

特性

说明

唯一性

整个表中,主键列的值必须唯一,不能重复。

非空性

主键列的值不能为 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 系统。

  • 慎用自然键:除非你能保证该业务属性绝对唯一、永不改变、且长度适中(如国家代码、某些唯一编码)。

  • 复合主键:尽量少用,除非逻辑上确实需要(如多对多关系的中间表)。复合主键可能导致索引变大,查询复杂度增加。

五、主键使用注意事项

  1. 主键列不能为 NULL:这是基本要求,插入时必须提供值(自增列会自动生成)。

  2. 不要频繁更新主键:主键是其他表引用它的基础,更新主键会引发连锁反应(外键更新),应尽量避免。

  3. 主键不宜过长:主键会在索引中存储,过长的主键(如 UUID 字符串)会占用大量空间,影响性能。推荐使用整数类型。

  4. 每个表只能有一个主键,但可以有多个唯一索引(UNIQUE)。

  5. 主键会自动创建索引,所以基于主键的查询很快。

六、实战练习

  1. 创建一个 users 表,使用自增主键 id,包含 username(唯一)、emailcreated_at 字段。

  2. 创建一个 courses 表,使用课程编号 course_code(如 'CS101')作为自然主键。

  3. 创建一个 student_course 表(学生选课表),使用复合主键 (student_idcourse_id),并插入一些示例数据。

  4. 尝试向 students 表插入两条相同 id 的数据,观察错误。

  5. 删除某个表的主键,然后再重新添加。

主键要点总结

方面

要点

定义

唯一标识表中每一行的列或列组合

特性

唯一、非空、稳定、最小

创建方式

列级约束、表级约束、ALTER TABLE 添加

自增主键

AUTO_INCREMENT

 配合主键使用,最常用

复合主键

多列组合,用于多对多关系表

选择策略

优先使用代理键(自增整数),慎用自然键和复合主键

重要性

数据完整性的基石,也是表间关联的桥梁

主键是数据库设计的核心,一个设计良好的主键能让后续的数据操作和关系建立事半功倍。记住:每个表都应该有一个主键,这是数据完整性的第一条法则。


发表评论

昵称:
联系方式:
评论内容:

所有评论

关于我 备案号:蜀ICP备2023042032号-1