MySQL表约束详解:8大核心约束实战指南

上一篇文章学到了数据类型,而数据类型只能限制数据的类型和长度 ,约束能从业务规则 层面保证数据合法、正确(比如邮箱唯一、姓名不能为空),是数据库表设计的核心规范。接下来我们来学习一下MySQL表的约束。我们重点学习 8 个高频约束:NULL / NOT NULLDEFAULTCOMMENTZEROFILLPRIMARY KEYAUTO_INCREMENTUNIQUE KEYFOREIGN KEY。

再上一个文章我们还能知道如果我们向MySQL特定类型中插入不合法的数据,MySQL一般都是直接拦截我们的,不让我们做对应的操作!反过来,如果我们已经有数据成功被插入到MySQL中,那一定是插入时候合法的!所以,MySQL中,一般而言,数据类型本身也是一种约束------而这个约束是倒逼程序员,让程序员尽可能进行正确的插入。约束即约束使用者的!另外,如果你不是一个很好的使用者,MySQL也能保证数据插入合法。故保证数据库中的数据是可预期的,完整的。

目录

[1. 空属性约束:NULL / NOT NULL](#1. 空属性约束:NULL / NOT NULL)

[2. 默认值约束:DEFAULT](#2. 默认值约束:DEFAULT)

[3. 列描述:COMMENT](#3. 列描述:COMMENT)

[4. 零填充:ZEROFILL](#4. 零填充:ZEROFILL)

[5. 主键(PRIMARY KEY)](#5. 主键(PRIMARY KEY))

[6. 自增长(AUTO_INCREMENT)](#6. 自增长(AUTO_INCREMENT))

[7. 唯一键(UNIQUE KEY)](#7. 唯一键(UNIQUE KEY))

[8. 外键(FOREIGN KEY)](#8. 外键(FOREIGN KEY))

[MySQL 表约束全章总结](#MySQL 表约束全章总结)


1. 空属性约束:NULL / NOT NULL

字段默认允许为 NULL,但 NULL 不参与任何运算(任何值 + NULL 都为 NULL),实际开发中核心业务字段应尽量设置为 NOT NULL

  • NULL:允许为空(默认)
  • NOT NULL:不允许为空,插入时必须提供值

示例演示

复制代码
-- NULL 无法参与运算
SELECT NULL;
SELECT 1 + NULL;

运行结果:

建表示例

创建班级表,要求班级名、教室都不能为空:

复制代码
mysql> create table if not exists myclass(
    -> name varchar(20) not null,
    -> room varchar(10) not null);

查看:

复制代码
desc myclass;

结果:

插入时若缺少必填字段,直接报错:

复制代码
mysql> insert into myclass(name) values('class1');
ERROR 1364 (HY000): Field 'room' doesn't have a default value

所以我们在设计数据库表的时候,一定要在表中进行限制,满足上面条件的数据就不能插入到表中。这 就是"约束"。


2. 默认值约束:DEFAULT

当插入数据不指定某字段值时,自动使用预设的默认值,简化插入语句并保证数据完整性。只有设置了 DEFAULT 的列,插入时才能省略该列。但是用户如果插入了具体的数据,就用用户的,没有才默认的。

建表示

复制代码
mysql> create table if not exists t10 (
    -> name VARCHAR(20) NOT NULL,
    -> age TINYINT UNSIGNED DEFAULT 0,
    -> sex CHAR(2) DEFAULT '男'
    -> );

查看:

复制代码
desc t10;

结果:

插入时只给姓名,其他字段自动使用默认值:

复制代码
mysql> insert into t10(name) values('张三');
Query OK, 1 row affected (0.00 sec)

查看:

注意:DEFAULT 与 NOT NULL 并不冲突,二者反而是互相补充、配合使用的关系

设置 NOT NULL 用于强制字段必须有值、不能为空;搭配 DEFAULT 则可以在插入时不手动传值,自动使用默认值填充,既满足非空约束,又简化数据插入。


3. 列描述:COMMENT

列描述:comment,没有实际含义,专门用来描述字段,会根据表创建语句保存,用来给程序员或DBA 来进行了解。

  • 作用 :给字段加注释说明,方便程序员 / 运维理解字段含义
  • 规则DESC 表名看不到注释,必须用SHOW CREATE TABLE查看

完整案例:创建用户表(年龄默认 0、性别默认男)

复制代码
create table if not exists user_info(
    name VARCHAR(20) NOT NULL COMMENT '用户名',
    age TINYINT UNSIGNED DEFAULT 0 COMMENT '年龄,默认0岁',
    sex CHAR(2) DEFAULT '男' COMMENT '性别,默认男'
);

查看创建结构:

复制代码
show create table user_info\G

运行结果:

插入:

复制代码
-- 插入数据:只填用户名,年龄、性别用默认值
insert into user_info(name) VALUES('张三');

查询:


4. 零填充:ZEROFILL

作用 :数字类型格式化显示 ,不足指定宽度时前面补0

关键 :只改变显示效果,不改变数据库实际存储的值

完整案例:数字补 0 展示

创建表,id字段设置:宽度5 + 零填充

复制代码
mysql> create table if not exists num_test(
    -> id int(5) unsigned zerofill comment '零填充测试');

插入:

复制代码
-- 插入值1
insert into num_test values(1);

查询数据:显示00001

复制代码
mysql> insert into num_test values(1);

验证真实存储值:还是1

复制代码
mysql> select id, hex(id) from num_test;

结果:


5. 主键(PRIMARY KEY)

主键用于唯一标识表中的每一行记录 ,从根本上保证数据不重复、可精准定位。主键的核心约束:字段值不能重复,且不能为空

特别注意:一张表最多只能有一个主键 ,但这不意味着主键只能设置在一列上 。主键可以只作用于单个字段 ,也可以同时作用于多个字段 ,由多个字段共同组成的主键称为复合主键

主键基本特性

  1. 唯一性:主键字段(或字段组合)的值不能重复
  2. 非空性:主键字段自动隐含 NOT NULL 约束,不允许为 NULL
  3. 唯一性限制:一张表只能定义一个主键
  4. 类型建议:主键字段通常使用整数类型(INT、BIGINT),查询与存储效率更高

案例 1:创建表时直接指定单列主键

在字段定义后直接加上 primary key,该字段单独作为主键。

复制代码
mysql> create table if not exists t13(
    -> id int unsigned primary key comment '学号,主键非空且唯一',
    -> name varchar(20) not null
    -> );

查看:

复制代码
desc t13;

Key 列显示 PRI,表示该字段是主键。

主键唯一性约束测试

复制代码
mysql> insert into t13 values(1, 'aaa');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t13 values(1, 'abc');
ERROR 1062 (23000): Duplicate entry '1' for key 't13.PRIMARY'

主键值重复,插入失败。

追加 / 删除主键

表创建

复制代码
mysql> create table if not exists t9(
    -> id int unsigned,
    -> name varchar(20) not null
    -> );

查看:

没有主键。

追加主键 语法:

复制代码
alter table 表名 add primary key(字段列表);

运行结果:

删除主键语法:

复制代码
alter table 表名 drop primary key;

运行结果:

案例 2:复合主键(多列共同组成一个主键)

一张表只有一个主键,但这个主键可以由多个字段联合构成,只有这几个字段的组合完全重复时,才算主键冲突。

创建表( id 和 course 共同组成一个主键)

复制代码
mysql> create table if not exists t14(
    -> id int unsigned,
    -> course char(10) comment '课程代码',
    -> score tinyint unsigned default 60 comment '成绩',
    -> primary key(id, course)  
    -> );
Query OK, 0 rows affected (0.01 sec)

查看:

复合主键约束测试

复制代码
mysql> insert into t14 (id,course) values(1, '123');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t14 (id,course) values(1, '124');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t14 (id,course) values(2, '124');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t14 (id,course) values(1, '123');
ERROR 1062 (23000): Duplicate entry '1-123' for key 't14.PRIMARY'

有现象可知------只有id 和 course 同时重复,才会触发主键冲突。


6. 自增长(AUTO_INCREMENT)

auto_increment 表示:插入数据时不给该字段赋值,系统会自动取当前字段最大值 +1,生成一个新的唯一值。通常与主键搭配使用,作为自动生成的逻辑主键。

自增长特点

  1. 自增长字段必须是索引列(Key 列有值,如主键、唯一键)
  2. 自增长字段必须是整数类型
  3. 一张表最多只能有一个自增长字段

案例

创建表:

复制代码
mysql> create table if not exists t15(
    -> id int unsigned primary key auto_increment,
    -> name varchar(10) not null default ''
    -> );

插入:

复制代码
mysql> insert into t15(name) values('张三');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t15(name) values('李四');
Query OK, 1 row affected (0.00 sec)

查看:

发现他自己增加了。

获取上一次插入的自增 ID

复制代码
mysql> select last_insert_id();

运行结果:

批量插入时,返回的是批量中第一条记录的自增 ID。

索引简介

在关系数据库中,索引是一种独立的、物理性的排序存储结构,用于加快数据查找。可以把索引理解为图书的目录:通过目录可以快速定位页码,而不用一页页翻阅全书。

索引会对指定一列或多列的值进行排序,并存储指向真实数据行的指针。数据库在查询时,可以通过索引直接定位数据,避免全表扫描,从而大幅提升查询效率。主键、唯一键、自增长字段默认都会自动创建索引


7. 唯一键(UNIQUE KEY)

在数据表设计中,除了主键需要具备唯一性外,业务上往往还存在其他字段也必须保证不重复,例如学号、工号、手机号、邮箱等。但一张表只能有一个主键,无法满足多字段同时唯一的约束需求,唯一键(UNIQUE KEY) 就是用来解决这个问题的。

唯一键用于保证字段取值在业务层面不重复,其规则与主键相似,但有一个关键不同:唯一键允许字段值为 NULL,并且可以存在多个 NULL,因为 NULL 不参与唯一性比较。

主键与唯一键的核心区别

  • 主键:用于唯一标识一行记录,自带非空约束,一张表只能有一个,通常与业务无关,用于定位数据。
  • 唯一键:用于保证业务字段不重复,允许为空,一张表可以有多个,专门约束业务逻辑上不能重复的数据。
    设计原则建议

实际开发中,建议主键使用与业务无关的自增 ID,而把身份证号、工号、学号这类业务唯一字段设为唯一键。这样即使未来业务规则变更,也不会影响主键结构,表结构更稳定。

案例演示

创建表(学号设为唯一键)

复制代码
mysql> create table if not exists student(
    -> id char(10) unique comment '学号,业务唯一,允许为空',
    -> name varchar(10) not null
    -> );

插入:

复制代码
-- 正常插入
mysql> insert into student(id, name) values('1', '张三');
Query OK, 1 row affected (0.00 sec)

-- 插入重复学号,违反唯一约束,失败
mysql> insert into student(id, name) values('1', '李四');
ERROR 1062 (23000): Duplicate entry '1' for key 'student.id'

-- 插入 NULL,唯一键允许为空,成功
mysql> insert into student(id, name) values('null', '李四');
Query OK, 1 row affected (0.00 sec)

查看:


8. 外键(FOREIGN KEY)

外键是用于建立两张表之间关联关系、保证数据参照完整性的约束。它可以避免出现 "学生属于一个不存在的班级""商品对应一个不存在的分类" 这类逻辑非法的数据。

外键核心规则

  • 外键约束建立在 ** 从表(子表)** 上
  • 被引用的主表(父表)字段必须是主键或唯一键
  • 从表外键列的值,必须在主表中存在,或者为 NULL
  • 主表记录被从表引用时,不能随意删除或修改,避免数据断裂

外键语法

复制代码
foreign key (从表字段) references 主表(主表关联字段)

案例实现

先创建主表:班级表

复制代码
create table if not exists myclass (
    id int primary key comment '班级编号,主键',
    name varchar(30) not null comment '班级名称'
);

这个是主表。

再创建从表:学生表,并设置外键关联班级

复制代码
create table if not exists stu (
    id int primary key comment '学生编号',
    name varchar(30) not null comment '学生姓名',
    class_id int comment '所属班级编号',
    foreign key (class_id) references myclass(id)
);

这个是从表。

查看

由表结构可知:外键用于建立从表(stu)与主表(myclass)的关联关系 ,并通过强制约束保证数据参照完整性。从表class_id作为外键,其取值必须在主表主键id中存在(或为 NULL),以此从数据库层面杜绝非法关联数据,确保两张表的业务逻辑一致性。

数据插入测试

复制代码
-- 向班级表插入合法数据
mysql> insert into myclass values(10, 'C++大牛班'),(20, 'java大神班');

-- 向学生表插入合法数据(班级存在)
mysql> insert into stu values(100, '张三', 10),(101, '李四',20);

-- 插入不存在的班级 30,违反外键约束,插入失败
mysql> insert into stu values(102, 'wangwu',30);
ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`test`.`stu`, CONSTRAINT `stu_ibfk_1` FOREIGN KEY (`class_id`) REFERENCES `myclass` (`id`))


-- 插入 NULL 表示暂未分配班级,允许插入
mysql> insert into stu values(102, 'wangwu', null);

可知:

  1. 外键约束会严格校验从表数据,插入主表中不存在的关联值时,操作直接失败,保证了业务数据的合法性。
  2. 外键字段允许为 NULL,表示该记录暂未关联主表数据,不违反参照完整性。
  3. 外键从数据库层面强制维护表与表之间的关联关系,有效避免无效、错误的脏数据产生。

外键的意义 :如果不使用外键,两张表只在逻辑上相关,数据库不会做任何校验,就可能出现脏数据。外键的本质,是把业务层的关联规则交给数据库强制校验,从底层保证数据一致性,避免业务逻辑漏洞产生无效数据。

外键的本质,是把业务层的关联规则交给数据库强制校验,从底层保证数据一致性,避免业务逻辑漏洞产生无效数据。

MySQL 表约束全章总结

本章系统讲解了 MySQL 中核心的表约束类型,从基础字段约束到表间关联约束,完整覆盖了数据合法性校验的核心手段:

  • 基础字段约束NOT NULL 强制字段非空、DEFAULT 预设默认值、COMMENT 标注字段含义、ZEROFILL 实现数字格式化显示,从字段层面规范数据存储;
  • 唯一标识约束PRIMARY KEY 作为表的唯一标识(非空 + 唯一,一张表仅一个,支持单列 / 复合主键),搭配 AUTO_INCREMENT 自动生成自增 ID,是表设计的标准规范;UNIQUE KEY 解决多字段唯一性需求,允许空值,适配业务字段的唯一性校验;
  • 表间关联约束FOREIGN KEY 建立主从表的关联关系,强制校验从表外键数据的合法性,从数据库层面杜绝脏数据,保证数据的参照完整性与业务逻辑一致性。

约束是数据库数据合法性的最后防线,合理使用约束能从根源上避免脏数据、提升数据质量,是 MySQL 表设计的核心必备技能。


以上就是本次 MySQL 表约束的全部内容,若大家后续有补充内容,或发现文中疏漏、错误,欢迎在评论区一起交流探讨~感谢各位的阅读!

相关推荐
zh15702310 分钟前
JavaScript中WorkerThreads解决服务端计算瓶颈
jvm·数据库·python
代码AI弗森14 分钟前
一文理清楚“算力申请 / 成本测算 / 并发评估”
java·服务器·数据库
摇滚侠1 小时前
expdp 查看帮助
java·数据库·oracle
流年似水~1 小时前
MCP协议实战:从零搭建一个让Claude能“看见“数据库的工具服务
数据库·人工智能·程序人生·ai·ai编程
2401_871492852 小时前
Vue.js监听器watch利用回调函数处理级联下拉框数据联动
jvm·数据库·python
志栋智能2 小时前
超自动化安全:构建智能安全运营的核心引擎
大数据·运维·服务器·数据库·安全·自动化·产品运营
zhoutongsheng3 小时前
C#怎么实现Swagger文档 C#如何在ASP.NET Core中集成Swagger自动生成API文档【框架】
jvm·数据库·python
WinterKay3 小时前
【开源】我写了一个轻量级本地数据库浏览工具,支持 MySQL/Redis 只读查询
数据库·mysql·开源
zxrhhm4 小时前
Oracle 索引完整指南
数据库·oracle
程序猿乐锅5 小时前
【Tilas|第三篇】多表SQL语句
数据库·经验分享·笔记·学习·mysql