【MySQL】第六节—一文详解 | 表的约束
2026/6/12 22:08:49 网站建设 项目流程

以下是MySQL 表的约束(Constraints)一文详解,适合作为“第六节”的核心内容,内容覆盖 MySQL 8.0+ 主流用法,包含原理、语法、常见场景、注意事项和面试/生产高频考点。

一、MySQL 表约束总览(2025–2026 主流)

约束类型英文名称作用是否允许 NULL是否允许重复是否可以有多列是否可以自定义名称是否可以延迟检查
主键约束PRIMARY KEY唯一标识每一行,唯一 + 非空可以(复合主键)可以
唯一约束UNIQUE列/列组合值唯一可以可以可以
非空约束NOT NULL该列不允许为空可以不可
默认值约束DEFAULT未指定值时自动填充默认值不可
检查约束CHECK自定义条件校验(MySQL 8.0.16+ 真正生效)可以可以
外键约束FOREIGN KEY维护参照完整性可以可以可以可以可以(延迟)

二、每种约束详细语法与实战说明

1. 主键约束(PRIMARY KEY)
-- 方式1:列级定义(最常见)CREATETABLEusers(idBIGINTNOTNULLAUTO_INCREMENTPRIMARYKEY,usernameVARCHAR(50)NOTNULL);-- 方式2:表级定义(适合复合主键)CREATETABLEorder_items(order_idBIGINTNOTNULL,item_idBIGINTNOTNULL,quantityINTNOTNULL,PRIMARYKEY(order_id,item_id));-- 方式3:已有表添加主键(必须先满足唯一+非空)ALTERTABLEusersADDPRIMARYKEY(id);

重要特性

  • 自动创建唯一索引(名为PRIMARY
  • InnoDB 表必须有主键(推荐自增 BIGINT)
  • 没有主键的表会隐式创建 6 字节 ROWID 作为聚簇索引(不推荐)
2. 唯一约束(UNIQUE)
-- 列级CREATETABLEemployees(emp_noINTPRIMARYKEY,emailVARCHAR(100)UNIQUENOTNULL);-- 表级(复合唯一)CREATETABLEuser_roles(user_idBIGINTNOTNULL,role_idBIGINTNOTNULL,UNIQUEKEYuk_user_role(user_id,role_id));-- 已有表添加ALTERTABLEemployeesADDUNIQUEKEYuk_email(email);ALTERTABLEuser_rolesADDUNIQUE(user_id,role_id);

关键区别vs 主键:

项目PRIMARY KEYUNIQUE
允许 NULL是(但 NULL 不算重复)
数量限制一个表只能一个可以多个
是否自动创建索引是(聚簇索引)是(普通唯一索引)
名字固定为 PRIMARY可自定义

面试常问:一张表可以有多个 UNIQUE 约束,但只能有一个 PRIMARY KEY。

3. 非空约束(NOT NULL)
CREATETABLEproducts(idINTPRIMARYKEYAUTO_INCREMENT,nameVARCHAR(100)NOTNULL,priceDECIMAL(10,2)NOTNULLDEFAULT0.00,created_atDATETIMENOTNULLDEFAULTCURRENT_TIMESTAMP);

注意

  • 已有表添加 NOT NULL 时,列中不能有 NULL 值,否则报错
  • ALTER TABLE ... MODIFY COLUMN可以添加/移除 NOT NULL
4. 默认值(DEFAULT)
-- 普通默认值statusTINYINTNOTNULLDEFAULT0,-- 表达式默认值(MySQL 8.0.13+)created_atDATETIMENOTNULLDEFAULTCURRENT_TIMESTAMP,updated_atDATETIMENOTNULLDEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP,-- 虚拟列默认值(函数表达式)full_nameVARCHAR(101)GENERATED ALWAYSAS(CONCAT(first_name,' ',last_name))STORED,

MySQL 8.0+ 支持的 DEFAULT 表达式

  • CURRENT_TIMESTAMP
  • NOW()
  • UUID()
  • (expression) AS …
5. 检查约束(CHECK)—— MySQL 8.0.16+ 真正生效
CREATETABLEemployees(idINTPRIMARYKEYAUTO_INCREMENT,ageTINYINTUNSIGNEDNOTNULL,salaryDECIMAL(10,2)NOTNULL,-- 方式1:列级CHECK(age>=18ANDage<=65),-- 方式2:表级(可跨列)CONSTRAINTchk_salaryCHECK(salary>=3000ANDsalary<=100000));-- 已有表添加ALTERTABLEemployeesADDCONSTRAINTchk_ageCHECK(ageBETWEEN18AND65);

重要提醒

  • MySQL 5.7 及之前版本:CHECK 语法可以写,但不生效(只是语法通过)
  • 8.0.16 之后才真正校验
  • 性能开销较小,但复杂 CHECK 会影响写入性能
6. 外键约束(FOREIGN KEY)——参照完整性
-- 先创建主表CREATETABLEdepartments(dept_idINTPRIMARYKEYAUTO_INCREMENT,dept_nameVARCHAR(50)NOTNULLUNIQUE);-- 再创建从表CREATETABLEemployees(emp_idINTPRIMARYKEYAUTO_INCREMENT,dept_idINTNOTNULL,nameVARCHAR(50)NOTNULL,FOREIGNKEY(dept_id)REFERENCESdepartments(dept_id)-- 更完整的写法(推荐生产环境)CONSTRAINTfk_emp_deptFOREIGNKEY(dept_id)REFERENCESdepartments(dept_id)ONDELETERESTRICT-- 默认行为ONUPDATECASCADE);

外键动作选项(ON DELETE / ON UPDATE)

选项含义典型使用场景
RESTRICT禁止删除/更新主表记录(默认)严格保护数据完整性
CASCADE级联删除/更新主从数据必须保持一致(如订单-明细)
SET NULL主表删除/更新后从表对应字段置 NULL可选关联关系
NO ACTION同 RESTRICT(MySQL 中等价)

外键使用建议(生产环境)

  • 小型项目、性能敏感表 → 可以不建外键,用业务代码保证
  • 中大型业务系统、数据质量要求高 → 强烈建议建外键 + 合适的 ON DELETE/UPDATE 策略
  • 外键会创建索引(如果从表字段没有索引,会自动创建)

三、约束的增删改查操作总结

-- 查看表所有约束SHOWCREATETABLEemployees\G-- 查看所有外键SELECT*FROMinformation_schema.REFERENTIAL_CONSTRAINTSWHERETABLE_SCHEMA='your_db';-- 删除约束(必须知道约束名)ALTERTABLEemployeesDROPFOREIGNKEYfk_emp_dept;ALTERTABLEemployeesDROPPRIMARYKEY;ALTERTABLEemployeesDROPINDEXuk_email;ALTERTABLEemployeesMODIFYCOLUMNemailVARCHAR(100)NULL;-- 移除 NOT NULL-- 添加约束(已有数据要满足条件)ALTERTABLEemployeesADDUNIQUE(email);ALTERTABLEemployeesADDCONSTRAINTpk_empPRIMARYKEY(emp_id);

四、面试/生产高频问题 20 条(建议背熟)

  1. 主键和唯一约束的本质区别是什么?
  2. 一张表可以有几个主键?几个唯一约束?
  3. MySQL 外键一定需要创建索引吗?
  4. ON DELETE CASCADE 和 ON DELETE SET NULL 的适用场景分别是什么?
  5. MySQL 什么时候真正开始校验 CHECK 约束?
  6. 没有主键的 InnoDB 表底层是怎么存储的?
  7. 复合主键的顺序对查询性能有影响吗?
  8. 外键约束会影响 insert/update/delete 的性能吗?
  9. 如何批量删除外键约束?
  10. DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP 的典型使用场景?

希望这份总结能帮你彻底搞懂 MySQL 表的约束体系。

需要我继续补充外键级联实际案例CHECK 约束性能测试无主键表 vs 有主键性能对比等更深入的内容吗?

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询