1. 基本概念
(1)主键 (primary key)
唯一标识表中每条记录,不允许重复且不能为 null。
主键也可以由多个列组成,这被称为复合主键(composite primary key)或联合主键。
当单个列无法唯一标识表中的每一行时,就可以将多个列组合起来作为主键。
组合后的列值整体必须是唯一的,且每个参与的列都不能为null。
复合主键的核心特性
- 唯一性:所有参与列的值组合起来必须在整个表中唯一。
- 非空性:组成复合主键的每一个列都必须定义为
not null。 - 标识性:整个列集合共同作用,用于唯一标识表中的一条记录。
(2)唯一键 (unique key)
确保某列或列组合的值唯一,但允许 null 值。
2. 如何表示
(1)创建表时定义:
-- 创建包含主键和唯一键的表
create table users (
id int auto_increment primary key, -- 主键
email varchar(100) unique, -- 唯一键(简写)
username varchar(50) unique, -- 另一个唯一键
phone varchar(20),
constraint uk_phone unique (phone) -- 唯一键(完整写法)
);
-- 或者复合键定义方式
create table orders (
order_id int,
product_id int,
quantity int,
primary key (order_id, product_id), -- 复合主键
unique key uk_order_product (order_id, product_id) -- 复合唯一键
);
(2)修改表时添加:
-- 添加主键 alter table users add primary key (id); -- 添加唯一键 alter table users add unique key uk_email (email); alter table users add constraint uk_username unique (username);
3. 主要区别对比
| 特性 | 主键 (primary key) | 唯一键 (unique key) |
|---|---|---|
| 数量限制 | 每表只能有一个 | 每表可以有多个 |
| null 值 | 不允许 null | 允许 null(但只能有一个 null,某些数据库允许多个) |
| 索引类型 | 默认创建聚簇索引(innodb) | 创建非聚簇索引 |
| 用途 | 标识记录的唯一性 | 确保数据的唯一性约束 |
| 外键引用 | 可以被其他表的外键引用 | 很少被外键引用 |
| 自动增长 | 常与 auto_increment 一起使用 | 不能使用 auto_increment |
4. 详细示例
-- 创建示例表
create table employees (
emp_id int auto_increment primary key, -- 主键,自增长
emp_code varchar(10) unique, -- 员工编号,唯一但不作为主键
email varchar(100) unique, -- 邮箱,唯一
department varchar(50),
hire_date date
);
-- 插入数据
insert into employees (emp_code, email, department) values
('e001', 'john@company.com', 'it'),
('e002', 'jane@company.com', 'hr');
-- 以下操作会失败(违反唯一约束)
insert into employees (emp_code, email) values
('e001', 'tom@company.com'); -- emp_code 重复
-- 以下操作会失败(违反主键约束)
insert into employees (emp_id, emp_code, email) values
(1, 'e003', 'sam@company.com'); -- emp_id 重复
-- 允许 null 值的唯一键示例
create table contacts (
id int primary key,
phone varchar(20) unique,
email varchar(100) unique
);
-- 可以插入多个 null 到 phone 列(mysql 特性)
insert into contacts values (1, null, 'a@test.com');
insert into contacts values (2, null, 'b@test.com'); -- 允许,因为 null != null
5. 复合键示例
-- 课程注册表:一个学生不能重复注册同一门课
create table course_registrations (
student_id int,
course_id int,
registration_date date,
primary key (student_id, course_id), -- 复合主键
unique key uk_student_course (student_id, course_id) -- 复合唯一键
);
-- 有效数据
insert into course_registrations values
(1, 101, '2024-01-10'),
(1, 102, '2024-01-10'), -- 同一个学生不同课程
(2, 101, '2024-01-11'); -- 不同学生同一课程
-- 以下会失败(违反主键/唯一键约束)
insert into course_registrations values
(1, 101, '2024-01-12'); -- student_id=1 和 course_id=101 已存在
6. 实际应用场景
主键使用场景:
- 用户表的用户id
- 订单表的订单id
- 产品表的产品id
唯一键使用场景:
- 用户表的邮箱、手机号、用户名
- 身份证号码
- 员工工号
- 防止重复的业务组合(如用户+产品收藏记录)
7. 性能考虑
-- 查看表的索引信息(包括主键和唯一键) show index from users; -- 执行计划分析 explain select * from users where email = 'test@example.com';
8. 总结
- 主键是表的"身份证",唯一键是"防重复检查器"
- 主键更严格(不能 null),唯一键更灵活(允许 null)
- 设计时通常用自增主键作为技术主键,用唯一键保护业务数据唯一性
- 两者都自动创建索引,提高查询性能,但也会影响插入/更新速度
根据你的业务需求选择合适的方式:需要严格标识每条记录用主键,只需要防止数据重复用唯一键。
到此这篇关于mysql主键和唯一键的使用与区别的文章就介绍到这了,更多相关mysql主键和唯一键内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论