news 2026/5/8 2:18:29

MySQL基础 约束详解 表与表之间的关系

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
MySQL基础 约束详解 表与表之间的关系

🎯目标:掌握数据库五大约束的使用,理解表与表之间的三种关系及建立方式


📌 一、什么是约束?

在数据库设计中,约束(Constraint)是对表中数据施加的限制规则,用于确保数据的完整性(准确性、正确性)

使用约束的好处:

  • ✅ 防止错误数据写入数据库
  • ✅ 减少冗余数据(脏数据)
  • ✅ 保证数据的一致性和可靠性

MySQL 中常用的约束共有五大类:

约束类型关键字作用
主键约束PRIMARY KEY唯一标识一条记录,不允许为空且不能重复
唯一约束UNIQUE保证列中数据不重复,但允许为空
非空约束NOT NULL该列不允许为空值
默认约束DEFAULT插入时若不提供值,则使用默认值填充
外键约束FOREIGN KEY维护两张表之间数据的一致性与完整性

🔑 二、主键约束(PRIMARY KEY)

2.1 基本概念

  • 理论上,每张表都必须有一个主键作为数据的唯一标识
  • 主键列的值不允许为 NULL,且不允许重复
  • 主键通常用id命名,是额外增加的列,而非业务数据列

2.2 建表时指定主键

CREATETABLEstudent(idINTPRIMARYKEY,nameVARCHAR(50),ageINT,emailVARCHAR(100));

2.3 主键重复时会报错

-- 第一条:成功INSERTINTOstudent(id,name,age,email)VALUES(1,'张三',18,'1443005893@qq.com');-- 第二条:失败!id=1 已存在,主键重复报错INSERTINTOstudent(id,name,age,email)VALUES(1,'李四',20,'1443005893@qq.com');

Duplicate entry '1' for key 'PRIMARY'

2.4 自动递增 AUTO_INCREMENT

手动维护主键十分麻烦,MySQL 提供了自动递增策略——每次取当前表中最大 ID 值 + 1,由数据库自动维护。

CREATETABLEstudent(idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(50),ageINT,emailVARCHAR(100));-- 插入时无需手动指定 idINSERTINTOstudent(name,age,email)VALUES('张三',18,'1443005893@qq.com');INSERTINTOstudent(name,age,email)VALUES('李四',20,'1443005893@qq.com');

AUTO_INCREMENT 的重要特点:

  1. 只有整型列才能设置为自动递增
  2. 只有主键才能设置为自增列
  3. 新增数据时可以不赋值,系统自动填充
  4. 初始值默认为1,步长默认为1
  5. 自增值一旦被使用(即便该行被删除),也不会回退复用

🔒 三、唯一约束(UNIQUE)

3.1 基本概念

  • 保证某列数据不允许重复
  • 与主键类似,但级别低于主键
  • 一张表可以创建多个唯一约束
  • 唯一约束的列允许为 NULL(NULL 不参与唯一性比较)
  • ⚠️ 注意:VARCHAR(255)长度时无法设置唯一约束

3.2 常见应用场景

唯一约束常用于约束手机号、账号、邮箱等不允许重复的字段。

CREATETABLEstudent(idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(50),ageINT,emailVARCHAR(100)UNIQUE-- 邮箱不允许重复);

3.3 违反唯一约束时报错

INSERTINTOstudent(name,age,email)VALUES('张三',18,'1443005893@qq.com');-- 同一邮箱再次插入,触发唯一约束INSERTINTOstudent(name,age,email)VALUES('lisi',20,'1443005893@qq.com');

Duplicate entry '1443005893@qq.com' for key 'email'


🚫 四、非空约束(NOT NULL)

4.1 基本概念

通过NOT NULL将某列设置为必填字段,插入数据时该列不允许为空值。

4.2 使用示例

CREATETABLEstudent(idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(50)NOTNULL,-- 姓名不能为空ageINT,emailVARCHAR(100)UNIQUE);-- 尝试插入空姓名,会报错INSERTINTOstudent(name,age,email)VALUES(NULL,18,'test@qq.com');

Column 'name' cannot be null


🎛️ 五、默认约束(DEFAULT)

5.1 基本概念

通过DEFAULT为某列设置默认值,插入时若不提供该列的值,则自动使用默认值填充。

5.2 使用示例

CREATETABLEstudent(idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(50)NOTNULL,ageINTDEFAULT18,-- 年龄默认为18genderVARCHAR(10)DEFAULT'男'-- 性别默认为男);-- 不提供 age 和 gender,将使用默认值INSERTINTOstudent(name)VALUES('张三');-- 查询结果:age=18, gender='男'SELECT*FROMstudent;

🔗 六、外键约束(FOREIGN KEY)

6.1 基本概念

外键用来让两个表的数据之间建立连接,保证数据的一致性和完整性

  • 拥有外键的表称为从表(子表)
  • 被引用的表称为主表(父表)
  • 从表外键列的值必须在主表对应列中存在

6.2 添加外键示例

假设有部门表dept和员工表emp

-- 主表:部门表CREATETABLEdept(idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(50)NOTNULL);-- 从表:员工表,dept_id 引用 dept 的主键CREATETABLEemp(idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(50)NOTNULL,dept_idINT,CONSTRAINTfk_emp_deptFOREIGNKEY(dept_id)REFERENCESdept(id));

6.3 删除 / 更新时的行为策略

当主表数据发生变化时,从表如何联动,可通过以下策略控制:

策略说明
CASCADE父表 update/delete 时,子表匹配记录同步update/delete
SET NULL父表 update/delete 时,子表外键列设为 NULL(该列不能是 NOT NULL)
NO ACTION子表有匹配记录时,不允许父表进行 update/delete
RESTRICT同 NO ACTION,立即检查外键约束
-- 使用 CASCADE:父表删除时子表联动删除CONSTRAINTfk_emp_deptFOREIGNKEY(dept_id)REFERENCESdept(id)ONDELETECASCADEONUPDATECASCADE

6.4 使用外键的注意事项

  1. 数据库引擎必须为InnoDB(MyISAM 不支持外键)
  2. 从表中的外键值,必须在主表中存在,或者为 NULL

6.5 ⚠️ 为什么实际开发中常常不使用外键?

尽管外键能提高数据质量,但在实际工程中,许多团队选择不在数据库层面使用外键,而是在应用层做数据一致性校验。原因如下:

在表上存在活动外键时,每次插入、更新、删除操作前,数据库都需要检查是否违反约束,对性能影响较大。数据仓库、OLAP 场景中批量处理数据时性能开销尤为明显。

常见做法:数据库不加外键 + 业务代码保证数据一致性 + 定期数据巡检。


🗂️ 七、表与表之间的关系

数据库中,表和表之间存在三种基本关系:一对一一对多多对多。正确理解并设计表关系,是数据库建模的核心能力。


7.1 一对多(最常见)

概念

一张表中的一条记录对应另一张表中的多条记录

典型例子
  • 一个部门拥有多个员工
  • 一个用户有多条订单
  • 一个班级有多个学生
如何建立联系

在**"多"的一方**(子表)添加外键,引用**"一"的一方**(父表)的主键。

-- 父表:部门(一)CREATETABLEdept(idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(50)NOTNULL);-- 子表:员工(多)CREATETABLEemp(idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(50)NOTNULL,dept_idINT,-- 外键,指向 dept 表FOREIGNKEY(dept_id)REFERENCESdept(id));

关系示意图:


7.2 一对一

概念

一张表中的一条记录对应另一张表中的恰好一条记录,反之亦然。

典型例子
  • 用户表用户详情表(基础信息 + 扩展信息拆分存储)
  • 公民身份证
  • 员工工牌
为什么需要一对一?

通常是为了:

  1. 垂直分表:将频繁访问的核心字段和不常访问的扩展字段分开,提升查询性能
  2. 字段过多时,拆分成两张表管理更清晰
如何建立联系

在任意一方添加外键,并在外键列上加UNIQUE约束(保证一对一,而非一对多)。

-- 用户基础表CREATETABLEuser(idINTPRIMARYKEYAUTO_INCREMENT,usernameVARCHAR(50)NOTNULL,passwordVARCHAR(100)NOTNULL);-- 用户详情表CREATETABLEuser_detail(idINTPRIMARYKEYAUTO_INCREMENT,user_idINTUNIQUE,-- UNIQUE 保证一对一phoneVARCHAR(20),addressVARCHAR(200),FOREIGNKEY(user_id)REFERENCESuser(id));

关系示意图:


7.3 多对多

概念

一张表中的一条记录对应另一张表中的多条记录,反过来也一样。

典型例子
  • 学生课程:一个学生选多门课,一门课有多个学生
  • 用户角色:一个用户有多个角色,一个角色对应多个用户
  • 订单商品:一个订单包含多个商品,一个商品出现在多个订单中
如何建立联系:中间关系表

多对多不能直接在两张表上加外键来解决,必须引入第三张关联表(中间表)。中间表至少包含两个外键,分别指向两张主表的主键。

-- 学生表CREATETABLEstudent(idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(50)NOTNULL);-- 课程表CREATETABLEcourse(idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(100)NOTNULL);-- 中间关联表:学生选课CREATETABLEstudent_course(idINTPRIMARYKEYAUTO_INCREMENT,student_idINTNOTNULL,course_idINTNOTNULL,scoreDECIMAL(5,2),-- 还可以存储关系相关的额外属性FOREIGNKEY(student_id)REFERENCESstudent(id),FOREIGNKEY(course_id)REFERENCEScourse(id),UNIQUEKEYuk_stu_course(student_id,course_id)-- 防止重复选课);

数据示例:

可以看出:张三选了 MySQL 和 Java,李四选了 MySQL,王五选了 Python。


7.4 三种关系总结对比

关系类型典型场景实现方式
一对多部门-员工、用户-订单在"多"的一方加外键
一对一用户-详情、公民-身份证在任意一方加外键 +UNIQUE约束
多对多学生-课程、用户-角色创建中间关联表,各加一个外键

📝 八、综合建表案例

以一个简单的选课系统为例,综合运用约束与表关系:

-- 1. 班级表CREATETABLEclass(idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(50)NOTNULLUNIQUE-- 班级名唯一);-- 2. 学生表(多对一 班级)CREATETABLEstudent(idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(50)NOTNULL,ageINTDEFAULT18,emailVARCHAR(100)UNIQUE,class_idINT,FOREIGNKEY(class_id)REFERENCESclass(id)ONDELETESETNULL);-- 3. 课程表CREATETABLEcourse(idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(100)NOTNULL,descriptionVARCHAR(500));-- 4. 选课中间表(多对多)CREATETABLEstudent_course(idINTPRIMARYKEYAUTO_INCREMENT,student_idINTNOTNULL,course_idINTNOTNULL,scoreDECIMAL(5,2),FOREIGNKEY(student_id)REFERENCESstudent(id)ONDELETECASCADE,FOREIGNKEY(course_id)REFERENCEScourse(id)ONDELETECASCADE,UNIQUEKEYuk_stu_course(student_id,course_id));

💡 总结

知识点核心要点
主键约束唯一 + 非空,配合AUTO_INCREMENT自动维护
唯一约束不重复但可为空,一表可有多个
非空约束该列必须有值
默认约束不传值时自动填默认值
外键约束维护表间引用完整性,实际开发中常用应用层替代
一对多在"多"方加外键
一对一外键 + UNIQUE
多对多建立中间关联表

💬学习建议:约束是数据库设计的基础,表关系是业务建模的核心。建议多练习 ER 图设计,先画图再建表,养成良好的数据库设计习惯。


如有问题欢迎在评论区留言交流!👇

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/8 2:07:46

如何设计 Agent 的资源调度与优先级系统?

网罗开发(小红书、快手、视频号同名)大家好,我是 展菲,目前在上市企业从事人工智能项目研发管理工作,平时热衷于分享各种编程领域的软硬技能知识以及前沿技术,包括iOS、前端、Harmony OS、Java、Python等方…

作者头像 李华
网站建设 2026/5/8 2:01:37

解密世界杯转播费天价之谜:这 7 大因素是关键

解密世界杯转播费天价之谜:这 7 大因素是关键为你揭开世界杯转播费高昂背后的神秘面纱,让你明白其中缘由。全球超高关注度:受众群体庞大。世界杯是全球最具影响力的体育赛事,每届世界杯吸引全球数十亿观众观看。据统计&#xff0c…

作者头像 李华