MySQL表约束详解:非空、唯一、主键与外键实操指南

Nora
Nora
发布时间:2026-10-15| 6人浏览过
原创

在数据库设计中,约束是保障数据完整性与有效性的关键机制。本文深入解析MySQL中的非空、唯一、主键和外键四种常用约束,提供具体的Create Table与Insert测试用例,帮助开发者建立规范的数据结构。

认识MySQL数据约束

约束的英文单词为 constraint。在创建数据库表时,通过对特定字段附加约束条件,可以强制限制输入数据的有效范围,从而确保存储在表中的数据符合业务逻辑与实际需求。常见的数据类型约束包括:NOT NULL(非空)、UNIQUE(唯一性)、PRIMARY KEY(主键)、FOREIGN KEY(外键)以及 CHECK(检查约束)。这些约束共同构成了关系型数据库数据质量的防线。

1. 非空约束 (NOT NULL)

非空约束用于确保指定字段的值不能为空。若尝试插入空值且未设置默认值,系统将拒绝该操作并抛出错误。

第1步:定义含非空约束的表结构

目的:创建一个包含非空字段的表。

mysql> create table t_vip(
  id int,
  name varchar(255) not null
);

第2步:验证非空约束的效果

入口:向表中插入数据。

首先插入一个符合规范的数据行,系统正常接受:

mysql> insert into t_vip(id, name) values(1, 'zhangsan');
mysql> insert into t_vip(id, name) values(2, 'lisi');

接着,尝试仅插入 id 字段而忽略 name 字段,观察报错信息:

mysql> insert into t_vip(id) values(3);
ERROR 1364 (HY000): Field 'name' doesn't have a default value

上述报错表明,由于 name 字段被定义为 NOT NULL 且未设定默认值,MySQL 拒绝了隐式或显式的空值插入。

2. 唯一性约束 (UNIQUE)

唯一性约束要求字段内的所有值必须互不相同,但允许存在 NULL 值。这一约束常用于防止重复记录,例如限制用户名或邮箱的唯一性。

1. 单字段唯一性约束

目的:确保某一列的所有数据均不重复。

mysql> create table t_vip(
  id int,
  name varchar(255) unique,
  email varchar(255)
);

操作与结果:当尝试插入已存在的值时,系统会触发唯一性冲突错误:

mysql> insert into t_vip(id, name, email) values(3, 'lisi', 'lisi@123.com');
ERROR 1062 (23000): Duplicate entry 'lisi' for key 't_vip.name'

插入成功后,可通过查询确认表内数据状态:

mysql> select * from t_vip;

2. 多字段联合唯一性约束

需求场景:需要实现“姓名+邮箱”组合的唯一性,而非单个字段的全局唯一。

如果简单地分别给两列添加 unique(即每个字段独立唯一),无法满足业务要求。正确的做法是在 CREATE TABLE 语句末尾定义联合索引:

mysql> create table t_vip(
  id int,
  name varchar(255),
  email varchar(255),
  unique(name, email)
);

在此基础上,以下两条数据均合法,因为它们组成的组合值不同:

mysql> insert into t_vip(id, name, email) values(1, 'zhangsan', 'zhangsan@123.com');
mysql> insert into t_vip(id, name, email) values(1, 'zhangsan', 'zhangsan@sina.com');

但若再次插入完全相同的 (name, email) 组合,则会被拦截。

3. 主键约束 (PRIMARY KEY)

主键是表中每一行记录的物理或逻辑标识符,相当于记录的“身份证号”。主键具有两个核心特征:非空(NOT NULL)与唯一(UNIQUE)。

主键的相关术语

  1. 主键约束:一种强制数据唯一性和非空的约束类型。
  2. 主键字段:应用了主键约束的列。
  3. 主键值:主键字段当前存储的具体数值。

单一主键 vs 复合主键

单一主键:仅由一列构成。例如:

mysql> create table t_vip(
  id int primary key,
  name varchar(255)
);

测试发现,无论是试图插入重复 ID 还是缺失 ID(null),均会引发相应错误:

-- 插入重复主键报错
ERROR 1062 (23000): Duplicate entry '2' for key 't_vip.PRIMARY'
-- 插入空主键报错
ERROR 1364 (HY000): Field 'id' doesn't have a default value

复合主键:由多列联合组成主键。此时,只有组合起来才具备唯一性。例如:

mysql> create table t_vip(
  id int,
  name varchar(255),
  email varchar(255),
  primary key(id, name)
);

在此结构中,相同 ID 搭配不同 Name 是允许的:

mysql> insert into t_vip(id, name, email) values(1, 'zhangsan', 'zhansgan@123.com');
mysql> insert into t_vip(id, name, email) values(1, 'lisi', 'lisi@123.com');

自然主键与业务主键的选择

  • 自然主键:主键值为无意义的自然数(如自增整数),不与业务逻辑挂钩。实际开发中最为推荐,易于维护。
  • 业务主键:使用具有业务含义的字段(如银行卡号、手机号)作为主键。一旦业务属性发生变化(如用户换绑手机号),会导致主键变更及关联数据修改的巨大成本,故较少直接使用。

4. 外键约束 (FOREIGN KEY)

外键用于在不同表之间建立引用关系,确保参照完整性。涉及的概念包括:FOREIGN KEY 本身、引用该约束的列(外键字段)及其中的具体值。

为何需要外键?——从范式论说起

假设我们要设计“班级”和“学生”的信息模型。若将所有数据存储于单张表中,会出现大量班级信息的冗余(重复保存班级名称等),浪费存储空间且不利于更新。第二种方案将班级与学生分拆为两张表:

拆分后,学生表中的班级编号(cno)如果不加限制,可能会出现指向不存在的班级(如班级表中没有 102 班,但学生表里有 102)。为此,需引入外键约束,强制 cno 的值必须在父表(班级表)中存在。

外键操作的顺序规则

在使用外键时,必须严格遵守操作顺序,以避免破坏数据一致性:

  • 建表顺序:先创建父表(被引用表),再创建子表(引用表)。
  • 删除顺序:必须先删除子表数据,再删除子表;随后处理父表。
  • 插入顺序:必须先有父表数据,才能向子表插入对应外键值的记录。

创建并测试外键表

第1步:构建父子表结构

目的:建立一个具备参照引用的数据库环境。

-- 创建父表:班级表
mysql> create table t_class(
  classno int primary key,
  classname varchar(255)
);

-- 创建子表:学生表
mysql> create table t_student(
  no int primary key auto_increment,
  name varchar(255),
  cno int,
  foreign key(cno) references t_class(classno)
);

第2步:录入初始数据

入口:首先在父表中写入有效的班级列表。

mysql> insert into t_class(classno, classname) values(100, '高三1班');
mysql> insert into t_class(classno, classname) values(101, '高三2班');

随后在子表录入多名学生归属 100 班的记录:

mysql> insert into t_student(name, cno) values('jack', 100);
mysql> insert into t_student(name, cno) values('lucy', 100);
mysql> insert into t_student(name, cno) values('lilei', 100);
mysql> insert into t_student(name, cno) values('hanmeimei', 100);
mysql> insert into t_student(name, cno) values('zhangsan', 100);
mysql> insert into t_student(name, cno) values('lisi', 100);
mysql> insert into t_student(name, cno) values('wangwu', 100);
mysql> insert into t_student(name, cno) values('zhaoliu', 100);

关于父表字段是否必须是主键的说明:被外键引用的字段并不绝对必须是主键(Primary Key),但它至少必须具备 UNIQUE(唯一)约束,以保证关系的准确映射。

以上就是MySQL中常见数据约束(非空、唯一、主键、外键)的详细内容与操作实践,更多关于数据库设计与优化的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。