MySQL中给字段添加唯一约束的方式有哪些?

一、先明确:为什么必须掌握唯一约束?

  1. 你是否知道添加唯一约束的多种方式?(创建表时 / 修改表时)
  2. 能否区分 "单列唯一约束" 和 "多列唯一约束" 的适用场景?
  3. 是否了解唯一约束的核心特性?(比如与主键的区别、对 NULL 值的处理)

二、先铺垫:什么是 MySQL 唯一约束?

唯一约束(UNIQUE Constraint)是 MySQL 中用于限制字段(或多个字段组合)的值不能重复的一种约束,它能保证数据表中指定字段的唯一性,防止重复数据插入,从而保障数据的有效性。比如:用户表的phone(手机号)字段添加唯一约束后,就无法插入两个手机号相同的用户;订单表的order_no(订单编号)添加唯一约束后,不会出现重复的订单编号。

三、核心:添加唯一约束的 3 种方式

复制代码
-- 基础表结构(未加唯一约束)
CREATE TABLE `sys_user` (
  `id` INT PRIMARY KEY AUTO_INCREMENT, -- 主键(自增)
  `username` VARCHAR(50) NOT NULL,    -- 用户名
  `phone` VARCHAR(11),                -- 手机号
  `email` VARCHAR(50),                -- 邮箱
  `dept_id` INT                       -- 部门ID
);

方式 1:创建表时添加唯一约束

在CREATE TABLE语句中,通过UNIQUE关键字直接给字段添加唯一约束,支持「单列唯一」和「多列唯一」两种场景。

1.1 单列唯一约束(单个字段值唯一)

  • 语法:在字段定义后直接添加 UNIQUE 关键字(或 UNIQUE KEY,两者等价)。

  • SQL 示例 1:创建用户表时,给username(用户名)添加唯一约束(保证用户名不重复)

    CREATE TABLE sys_user (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL UNIQUE, -- 单列唯一约束:用户名唯一
    phone VARCHAR(11),
    email VARCHAR(50),
    dept_id INT
    );

  • SQL 示例 2:给phone(手机号)添加唯一约束,同时指定约束名称(便于后续删除 / 修改)

    CREATE TABLE sys_user (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    phone VARCHAR(11),
    email VARCHAR(50),
    dept_id INT,
    -- 单列唯一约束:指定约束名称(uq_sys_user_phone),更易维护
    UNIQUE KEY uq_sys_user_phone (phone)
    );

  • 适用场景:单个字段需要保证唯一性的场景(如用户名、手机号、订单编号)。

1.2 多列唯一约束(联合唯一,多个字段组合值唯一)

  • 通俗定义:不是单个字段的值唯一,而是多个字段的「组合值」唯一(单个字段值可重复,组合后不可重复)。

  • 语法:在表结构末尾通过 UNIQUE KEY 约束名 (字段1, 字段2, ...) 定义。

  • SQL 示例:给dept_id(部门 ID)和username(用户名)添加联合唯一约束(同一部门内用户名不能重复,不同部门可重复)

    CREATE TABLE sys_user (
    id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(50) NOT NULL,
    phone VARCHAR(11),
    email VARCHAR(50),
    dept_id INT,
    -- 多列联合唯一约束:同一部门内用户名唯一
    UNIQUE KEY uq_sys_user_dept_username (dept_id, username)
    );

  • 适用场景:需要按 "组合条件" 保证唯一性的场景(如同一部门用户名唯一、同一商品的规格组合唯一)。

方式 2:修改表时添加唯一约束(表已存在时使用)

如果表已经创建完成(比如前期设计遗漏了唯一约束),可以通过ALTER TABLE语句添加唯一约束,同样支持单列和多列场景。

2.1 给单列添加唯一约束

  • 语法:ALTER TABLE 表名 ADD UNIQUE KEY [约束名] (字段名);

  • SQL 示例:给已存在的sys_user表的email字段添加唯一约束

    -- 方式1:不指定约束名(MySQL会自动生成默认约束名,不推荐)
    ALTER TABLE sys_user ADD UNIQUE KEY (email);

    -- 方式2:指定约束名(推荐,便于后续维护)
    ALTER TABLE sys_user ADD UNIQUE KEY uq_sys_user_email (email);

2.2 给多列添加联合唯一约束

  • 语法:ALTER TABLE 表名 ADD UNIQUE KEY 约束名 (字段1, 字段2, ...);

  • SQL 示例:给已存在的sys_user表添加dept_id和username的联合唯一约束

    ALTER TABLE sys_user ADD UNIQUE KEY uq_sys_user_dept_username (dept_id, username);

  • 适用场景:表已创建完成,需要补充唯一约束的场景(如需求迭代后新增唯一性要求)。

方式 3:创建唯一索引(功能等价于唯一约束)

MySQL 中,唯一约束的本质是通过唯一索引实现的,创建唯一索引(CREATE UNIQUE INDEX)和添加唯一约束在功能上完全一致,都能保证字段值的唯一性。

  • 语法:CREATE UNIQUE INDEX 索引名 ON 表名 (字段1, 字段2, ...);

  • SQL 示例 1:给sys_user表的phone字段创建唯一索引

    CREATE UNIQUE INDEX idx_sys_user_phone_unique ON sys_user (phone);

  • SQL 示例 2:给sys_user表的dept_id和username创建联合唯一索引

    CREATE UNIQUE INDEX idx_sys_user_dept_username_unique ON sys_user (dept_id, username);

  • 适用场景:更偏向 "索引优化" 场景(比如需要通过唯一索引提升查询效率,同时保证数据唯一性),实习生了解即可,优先掌握前两种方式。

四、唯一约束的核心特性

  1. 对 NULL 值的处理 :唯一约束允许字段存储多个NULL值(因为 MySQL 中NULL不等于任何值,包括它自身)。

  2. 与主键(PRIMARY KEY)的区别

    特性 唯一约束(UNIQUE) 主键(PRIMARY KEY)
    唯一性 保证字段值唯一 保证字段值唯一
    非空性 允许 NULL 值(单列) 不允许 NULL 值
    一个表数量 可以有多个唯一约束(单列 / 多列) 一个表只能有一个主键(可联合主键)
    索引类型 唯一索引 聚簇索引
  3. 约束的删除 :如果需要删除唯一约束,可通过约束名 / 索引名删除:

    复制代码
    -- 语法:ALTER TABLE 表名 DROP INDEX 约束名/索引名;
    ALTER TABLE `sys_user` DROP INDEX `uq_sys_user_phone`;

加分项

  1. 结合项目举例:"我在实训项目的用户注册模块中,给手机号phone字段添加了唯一约束,避免同一手机号重复注册;同时给部门 IDdept_id和用户名username添加了联合唯一约束,保证同一部门内用户名不重复";
  2. 区分场景选择方式:"创建表时我会直接添加唯一约束,表已存在时用ALTER TABLE补充,需要提升查询效率时会创建唯一索引";
  3. 注意 NULL 值特性:"我知道唯一约束允许多个 NULL 值,所以如果手机号是必填项,我会同时给phone字段加NOT NULL和唯一约束,避免出现空值重复问题"。

踩坑点

  1. 混淆唯一约束和主键:比如认为 "一个表只能有一个唯一约束",或给需要非空的字段只加唯一约束不加NOT NULL;
  2. 忽略多列联合唯一的逻辑:比如误以为多列联合唯一是 "每个字段都唯一",而不是 "组合值唯一";
  3. 不指定约束 / 索引名:创建唯一约束时不指定名称,后续需要删除 / 修改时无法快速定位(依赖 MySQL 默认生成的复杂名称)。

举一反三

1、"唯一约束和主键有什么区别?如果我想让手机号既非空又唯一,该怎么设置?"(答案:给phone字段同时添加NOT NULL和UNIQUE约束);

2、"我插入一条username为'zhangsan'、dept_id为 1 的记录后,还能插入username为'zhangsan'、dept_id为 2 的记录吗?为什么?"(答案:可以,因为是联合唯一约束,组合值不同即可);

3、"如何删除sys_user表中uq_sys_user_phone这个唯一约束?"(答案:ALTER TABLE sys_user DROP INDEX uq_sys_user_phone;)。

相关推荐
倔强的石头_8 小时前
kingbase备份与恢复实战(二)—— sys_dump库级逻辑备份与恢复(Windows详细步骤)
数据库
阿巴斯甜14 小时前
Android 报错:Zip file '/Users/lyy/develop/repoAndroidLapp/l-app-android-ble/app/bu
android
Kapaseker14 小时前
实战 Compose 中的 IntrinsicSize
android·kotlin
xq952715 小时前
Andorid Google 登录接入文档
android
黄林晴16 小时前
告别 Modifier 地狱,Compose 样式系统要变天了
android·android jetpack
冬奇Lab1 天前
Android触摸事件分发、手势识别与输入优化实战
android·源码阅读
城东米粉儿1 天前
Android MediaPlayer 笔记
android
Jony_1 天前
Android 启动优化方案
android
阿巴斯甜1 天前
Android studio 报错:Cause: error=86, Bad CPU type in executable
android
张小潇1 天前
AOSP15 Input专题InputReader源码分析
android