MySQL 5.7 完全不解析 CHECK 约束,仅作注释跳过;8.0.16+ 才真正支持实时校验、命名约束及严格语法检查,迁移时需清理脏数据并确保服务端正确加载。

MySQL 5.7 完全不解析 CHECK 约束语法,写进去也当注释处理,不是“不生效”,而是“根本没看”。
MySQL 5.7 对 CHECK 关键字的处理方式
5.7 的 SQL 解析器在遇到 CHECK 子句时,会跳过它并继续建表——既不报错,也不校验,更不会存入数据字典。这意味着:
-
CREATE TABLE t (x INT, CHECK (x > 0));在 5.7 中能成功执行,但约束形同虚设 -
INSERT INTO t VALUES (-5);会正常插入,毫无阻碍 -
SHOW CREATE TABLE t;输出里虽保留CHECK字样,但服务器根本不认这个逻辑
MySQL 8.0.16+ 才真正启用 CHECK 约束
8.0.16 是分水岭版本:之前版本(如 8.0.12)虽支持语法,但默认禁用;从 8.0.16 起,CHECK 成为强制校验的 DDL 组成部分。关键点包括:
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 约束在
INSERT/UPDATE时实时触发,违反即报错ERROR 3819 (HY000) - 支持命名约束:
CONSTRAINT chk_status_valid CHECK (status IN ('active','inactive')),便于后期ALTER TABLE DROP CHECK - 不支持非确定性函数,如
CURRENT_DATE()、UUID(),否则建表直接失败:ERROR 3816 (HY000)
跨版本迁移时 CHECK 约束的常见陷阱
从 5.7 导出再导入到 8.0 时,容易误以为约束“自动激活”,实际要警惕以下问题:
- 5.7 导出的建表语句含
CHECK,但 8.0 导入时若已有历史数据不满足该条件,ALTER TABLE ADD CHECK会失败,报错ERROR 3819 - 5.7 中用
ENUM或TINYINT UNSIGNED隐式限制取值范围,迁移到 8.0 后加CHECK属于冗余但可读性提升,不影响运行 - 应用层若依赖 5.7 的“宽松”行为(比如允许插入空字符串到
NOT NULL字段),8.0 开启STRICT_TRANS_TABLES后会暴露问题,和CHECK无关但常被混淆
真正要注意的是:CHECK 不是向后兼容特性,它是 8.0.16+ 的全新执行层能力。别指望 5.7 的 dump 文件里带了 CHECK 就能在 8.0 自动起效——得先清理脏数据,再确保建表时 server 正确识别并加载约束。

















