在mysql数据库的实际使用中,当单个字段无法唯一标识一条数据记录时,就需要使用多个字段组合形成复合主键,来保证表中记录的唯一性。复合主键的核心作用是让多个字段的组合值在全表中不重复,同时这些字段的组合也不能为null。

创建表时设置复合主键
在创建新表的时候,可以直接在表定义的末尾通过PRIMARY_KEY关键字指定多个字段作为复合主键,多个字段之间用英文逗号分隔即可。
以下是一个用户角色关联表的示例,用户ID和角色ID的组合需要唯一,因此将这两个字段设置为复合主键:
-- 创建用户角色关联表,设置user_id和role_id为复合主键
CREATE TABLE user_role (
user_id INT NOT NULL,
role_id INT NOT NULL,
create_time DATETIME DEFAULT CURRENT_TIMESTAMP,
-- 复合主键定义,多个字段用逗号分隔
PRIMARY KEY (user_id, role_id)
);
也可以在定义字段的时候直接给某个字段加主键标识,但这种方式只能设置单个字段主键,无法设置复合主键,因此复合主键必须通过表级约束的方式定义。
给已有表添加复合主键
如果表已经创建完成,需要后续添加复合主键,可以使用ALTER TABLE语句来修改表结构,添加复合主键约束。
操作前需要确保要作为复合主键的字段都不存在null值,并且这些字段的组合在当前表中没有重复值,否则添加主键的操作会执行失败。
以下是给已有表添加复合主键的示例:
-- 给已有的order_item表添加复合主键,order_id和goods_id组合唯一 ALTER TABLE order_item ADD PRIMARY KEY (order_id, goods_id);
复合主键的使用注意事项
- 复合主键中的所有字段都不能允许为null,只要有一个字段为null,整个组合就不满足主键的非空约束。
- 复合主键的字段数量没有固定限制,但实际使用中建议控制在3个以内,过多的字段作为复合主键会降低查询效率,也会增加索引占用的存储空间。
- 如果表已经有自增的单字段主键,需要先删除原有主键才能添加复合主键,删除主键的语句为
ALTER TABLE 表名 DROP PRIMARY KEY;。 - 复合主键的索引是按照字段定义的顺序来构建的,查询时如果条件包含复合主键的前缀字段,才能有效使用这个主键索引。
复合主键和唯一索引的区别
很多开发者会混淆复合主键和复合唯一索引,两者的核心区别如下:
| 对比项 | 复合主键 | 复合唯一索引 |
|---|---|---|
| 是否允许为null | 所有字段都不允许为null | 字段可以允许为null,null值不参与唯一性判断 |
| 一个表的数量 | 只能有一个 | 可以有多个 |
| 默认索引类型 | 聚簇索引(InnoDB引擎) | 非聚簇索引 |
如果业务场景只需要保证多字段组合唯一,不需要用这个组合作为表的唯一标识,优先选择复合唯一索引会更灵活。
复合主键的查询示例
使用复合主键查询时,条件中最好包含复合主键的所有字段或者前缀字段,才能充分利用主键索引提升查询速度。
-- 使用复合主键的全部字段查询,能用到主键索引 SELECT * FROM user_role WHERE user_id = 1 AND role_id = 2; -- 只使用复合主键的第一个字段查询,也能用到部分主键索引 SELECT * FROM user_role WHERE user_id = 1; -- 只使用复合主键的第二个字段查询,无法用到主键索引,会全表扫描 SELECT * FROM user_role WHERE role_id = 2;
mysql复合主键primary_key数据库设计修改时间:2026-07-15 04:15:19