MySQL 约束(Constraint)是对表中数据的规则限制,核心目的是保证数据的完整性、一致性和准确性(比如防止重复数据、非法数据、关联数据不一致等)。约束可分为「列级约束」(作用于单个列)和「表级约束」(作用于多个列),以下是 MySQL 中最常用的约束类型:

一、核心约束类型

约束类型 关键字 核心作用 级别 适用场景
主键约束 PRIMARY KEY 非空 + 唯一,表的唯一标识(一张表仅能有 1 个主键) 列级 / 表级 员工 ID、订单 ID 等唯一标识
非空约束 NOT NULL 列值不能为 NULL 列级 姓名、手机号等必填字段
唯一约束 UNIQUE 列值唯一(可多个 NULL,MySQL 特性) 列级 / 表级 邮箱、身份证号等唯一字段
外键约束 FOREIGN KEY 关联两张表,保证引用完整性(子表值必须在父表存在) 表级 部门 ID、领导 ID 等关联字段
默认约束 DEFAULT 列未赋值时自动填充默认值 列级 状态、性别等有默认值的字段
检查约束 CHECK 校验列值符合指定条件(MySQL 8.0.16+ 正式支持) 列级 / 表级 年龄、薪资等数值范围限制
自增约束 AUTO_INCREMENT 主键自动生成唯一递增数值(仅 MySQL 支持) 列级 主键 ID(无需手动赋值)

二、各约束详解

1. 主键约束(PRIMARY KEY)

核心:非空 + 唯一,一张表只能有 1 个主键(可组合多个列作为「复合主键」,但不推荐)。

-- 列级约束(推荐,单个列主键)
CREATE TABLE emp (
    id INT PRIMARY KEY COMMENT '员工ID(主键)', -- 列级主键
    ...
);

-- 表级约束(复合主键,多列组合唯一)
CREATE TABLE emp (
    id INT,
    dept_id INT,
    PRIMARY KEY (id, dept_id) -- 表级复合主键(id+dept_id 组合唯一)
);

注意事项:

  • 主键列默认自带 NOT NULL,无需额外加;

  • 主键推荐用 INT/BIGINT 类型,配合自增(AUTO_INCREMENT)更易用;

  • 复合主键仅在无单一唯一字段时使用(如订单详情表:order_id + product_id)。

2. 非空约束(NOT NULL)

核心:列值必须填写,不能为 NULL。

CREATE TABLE emp (
    name VARCHAR(50) NOT NULL COMMENT '姓名(非空)', -- 非空约束
    job VARCHAR(50) NOT NULL DEFAULT '未知' COMMENT '职位(非空+默认值)',
    ...
);

注意事项:

  • 非空列插入时必须赋值(除非有 DEFAULT 约束);

  • 若插入 NULL 会报错:[1048][1292] Column 'name' cannot be null

3. 唯一约束(UNIQUE)

核心:列值唯一,允许多个 NULL(MySQL 中 NULL 不参与唯一判断)。

CREATE TABLE emp (
    email VARCHAR(50) UNIQUE COMMENT '邮箱(唯一)', -- 列级唯一
    id_card VARCHAR(18),
    UNIQUE (id_card) -- 表级唯一(效果同上)
);
-- 插入重复邮箱会报错:Duplicate entry 'test@163.com' for key 'email'
INSERT INTO emp (id, name, email) VALUES (7, '赵敏', 'test@163.com'), (8, '周芷若', 'test@163.com');

注意事项:

  • 唯一约束可创建多个(区别于主键);

  • 若要实现「唯一且不允许 NULL」,需组合 UNIQUE + NOT NULL

4. 外键约束(FOREIGN KEY)

核心:关联两张表(父表 = 主表,子表 = 从表),保证子表的关联值必须在父表存在(防止脏数据)。

前提:

  • 父表的关联列必须是主键 / 唯一约束;

  • 子表和父表的关联列类型必须一致(如都是 INT);

  • 存储引擎必须是 InnoDB(MyISAM 不支持外键)。

-- 添加外键关联
-- creare table 表名(字段名 数据类型,     [constrint] [外键名称] foreign key (外建字段名) references 主表(主表列名));
-- alter table 表名 add constraint 外键名称 foreign key (外键字段名) references (主表列名);


-- 第一步:创建父表(部门表 dept)
CREATE TABLE IF NOT EXISTS dept (
    dept_id INT PRIMARY KEY COMMENT '部门ID(主键)',
    dept_name VARCHAR(50) NOT NULL COMMENT '部门名称'
);

-- 第二步:创建子表(员工表 emp),添加外键关联 dept 表
CREATE TABLE IF NOT EXISTS emp (
    id INT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    dept_id INT,
    -- 外键约束:emp.dept_id 关联 dept.dept_id
    FOREIGN KEY (dept_id) REFERENCES dept(dept_id)
    -- 可选:级联操作(删除/更新父表时,子表的处理逻辑)
    ON DELETE SET NULL -- 父表删除部门时,子表 dept_id 设为 NULL
    ON UPDATE CASCADE -- 父表更新部门ID时,子表同步更新
);

注意事项:

  • 若无级联操作,删除父表已关联的记录会报错:Cannot delete or update a parent row: a foreign key constraint fails

  • 外键会降低插入 / 删除效率,高并发场景可通过应用层保证引用完整性,不建外键。

5. 默认约束(DEFAULT)

核心:插入数据时若未给该列赋值,自动填充默认值。

CREATE TABLE emp (
    job VARCHAR(50) DEFAULT '实习生' COMMENT '职位(默认实习生)',
    entrydate DATE DEFAULT CURRENT_DATE() COMMENT '入职日期(默认当前日期)',
    ...
);
-- 实例
-- 插入时不指定 job,自动填充为「实习生」
INSERT INTO emp (id, name) VALUES (7, '小昭');
-- 查询结果:job 列值为「实习生」
SELECT id, name, job FROM emp WHERE id=7;

注意事项:

  • 默认值不能是 NULL(若要默认 NULL,无需加 DEFAULT);

  • 函数作为默认值仅 MySQL 8.0+ 支持(如 CURRENT_DATE())。

6. 检查约束(CHECK)

核心:校验列值符合指定条件(如年龄≥18、薪资 > 0),MySQL 8.0.16 之前仅语法支持但不生效,8.0.16+ 正式支持。

CREATE TABLE emp (
    id INT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    age INT CHECK (age >= 18 AND age <= 60) COMMENT '年龄(18-60岁)',
    salary DECIMAL(10,2) CHECK (salary > 0) COMMENT '薪资(必须大于0)'
);
-- 实例
-- 插入年龄17会报错:Check constraint 'emp_chk_1' is violated
INSERT INTO emp (id, name, age) VALUES (8, '小张', 17);
7. 自增约束(AUTO_INCREMENT)

核心:主键自动生成唯一递增数值(仅 MySQL 支持),无需手动赋值。

CREATE TABLE emp (
    id INT PRIMARY KEY AUTO_INCREMENT COMMENT '员工ID(自增)',
    ...
);
-- 实例
-- 插入时不指定 id,自动生成 1、2、3...
INSERT INTO emp (name) VALUES ('金庸'), ('张无忌'), ('杨逍');
-- 查询结果:id 分别为 1、2、3
SELECT id, name FROM emp;

注意事项:

  • 自增列必须是主键 / 唯一约束;

  • 仅支持 INT/BIGINT 等数值类型;

  • 自增值不会回滚(删除 id=3 的记录后,新增记录 id 为 4,而非 3)

三、约束的添加 / 删除(ALTER TABLE)

若表已创建,需新增 / 删除约束,用 ALTER TABLE

-- 1. 添加主键
ALTER TABLE emp ADD PRIMARY KEY (id);

-- 2. 添加非空约束
ALTER TABLE emp MODIFY COLUMN name VARCHAR(50) NOT NULL;

-- 3. 添加唯一约束
ALTER TABLE emp ADD UNIQUE (email);

-- 4. 添加外键约束
ALTER TABLE emp ADD FOREIGN KEY (dept_id) REFERENCES dept(dept_id);

-- 5. 删除主键
ALTER TABLE emp DROP PRIMARY KEY;

-- 6. 删除唯一约束(需先查约束名:SHOW INDEX FROM emp;)
ALTER TABLE emp DROP INDEX email;

-- 7. 删除外键约束(需先查约束名:SHOW CREATE TABLE emp;)
ALTER TABLE emp DROP FOREIGN KEY emp_ibfk_1;

四、完整实战示例

-- 约束
create table user(
    id int primary key auto_increment  comment '主键',
    name varchar(10) not null  unique  comment '姓名',
    age int check ( age>0 and age <=120 ) comment '年龄',
    status char(1) default '1'  comment '状态',
    gender char(1) comment'性别'
) comment '用户表';
-- 插入数据
insert into user ( name, age, status, gender) values ('tom','19','1','男'),('toy','26','0','男');
insert into user(name,age,status,gender) values ('tomm','18','1','女');

insert into user(name,age,status,gender) values ('tomy','80','1','女');
insert into user(name,age,gender) values ('tor','25','女');
delete from user where name = 'too';
-- 外检约束
-- 外键用来让两张表的数据之间建立连接,从而保证数据的一致性和完整性。
-- 具有外键的表成为子表,外键所关联的表称为父表。
-- 练习
create table dept(
    id int auto_increment primary key comment 'ID',
    name varchar(50) not null comment'部门名称'
) comment '部门表';
insert into dept(id, name) VALUE (1,'研发部'),(2,'市场部'),(3,'财务部'),(4,'销售部'),(5,'总经办');
insert into emp (id,name, age, job, salary, entrydate, managerid, dept_id) values (1,'金庸',66,'总裁',20000,'2000-01-01',null,5),(2, '张无忌', 28, '项目经理', 12500.00, '2005-12-05', 1, 1),
(3, '杨逍', 33, '开发', 8400.00, '2006-03-04', 2, 1),
(4, '韦一笑', 48, '开发', 11000.00, '2007-05-01', 2, 1),
(5, '常遇春', 43, '开发', 10500.00, '2008-01-01', 2, 1),
(6, '小昭', 19, '实习生', 4000.00, '2024-01-01', 3, 1);
-- 添加外键关联
-- creare table 表名(字段名 数据类型,     [constrint] [外键名称] foreign key (外建字段名) references 主表(主表列名));
-- alter table 表名 add constraint 外键名称 foreign key (外键字段名) references (主表列名);
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id);
-- 删除外建
-- alter table 表名 drop foreign key 外键名称;
alter table emp drop foreign key fk_emp_dept_id;
-- 外键约束
--  1. 删除和更新行为:no action,restrict,cascade,set null,set default;
-- 语法 alter table 表名 add constraint 外键名称 foreign key (外键字段) references 主表名(主表字段名) on update cascade on delete cascade;
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id) on update cascade on delete cascade;-- cascade 更新外键在子表中的记录
alter table emp add constraint fk_emp_dept_id foreign key (dept_id) references dept(id) on update set null on delete set null;
-- 总结:6种约束 非空约束not null、唯一约束unique、主键约束primary key(即非空又唯一)自增:auto_increment、默认约束default、检查约束check、外键约束foreign key

五、核心注意事项

  1. 约束优先级:主键 > 外键 > 唯一 > 非空 > 默认 > 检查;
  2. 性能权衡:约束越多,插入 / 更新 / 删除的性能越低(尤其是外键、检查约束),生产环境需在「数据完整性」和「性能」间平衡;
  3. NULL 处理:唯一约束允许多个 NULL,主键 / 非空约束不允许 NULL;
  4. 自增重置:若需重置自增值,执行 ALTER TABLE emp AUTO_INCREMENT = 1;(需先清空表数据)。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐