MySQL 5.7 的 CHECK 约束完全未实现,仅语法接受后静默丢弃;MySQL 8.0 中需启用严格模式、全表校验无误、表达式确定性才生效,且仅作用于 INSERT/UPDATE。

CHECK 约束在 MySQL 5.7 中根本不会生效——不是“失效”,而是压根没实现。
MySQL 5.7 解析 CHECK 子句时只做语法接受,随后静默丢弃。你写 CHECK (age > 0),插入 age = -5 依然成功,这不是 bug,是官方设计行为。
MySQL 5.7 的 CHECK 是语法摆设,不是功能缺陷
-
SHOW CREATE TABLE输出里看不到CHECK定义 - 查询
information_schema.TABLE_CONSTRAINTS,constraint_type = 'CHECK'的记录一条都没有 - 官方文档明确标注:5.7 中
CHECK被 “silently ignored”(静默忽略) - 升级前依赖它做数据校验的逻辑,实际从未起效
MySQL 8.0 的 CHECK 也不是开箱即用
即使升级到 8.0,CHECK 仍需满足三个条件才能真正拦截非法数据:
- 必须启用严格 SQL 模式:比如
STRICT_TRANS_TABLES或STRICT_ALL_TABLES - 违反约束时,若模式不严格,MySQL 可能只发 warning,甚至配合
INSERT IGNORE静默跳过 - 检查当前模式:
SELECT @@sql<em>mode;</em>,确认含STRICT*字样
给已有表加 CHECK 会全表扫描,一错就失败
-
ALTER TABLE users ADD CHECK (age BETWEEN 0 AND 150);执行时,MySQL 会立即遍历整张表 - 只要有一行
age = -1或age = 200,就报错:ERROR 3819 (HY000): Check constraint is violated - 不会跳过、不会警告、不会部分生效
- 先查问题数据:
SELECT * FROM users WHERE age < 0 OR age > 150;,修正后再执行ALTER
CHECK 表达式本身受严格限制,稍不注意就语法报错
- 禁止非确定性函数:
NOW()、CURRENT_DATE()、UUID()、子查询都直接拒绝 - 报错示例:
ERROR 3816 (HY000): Invalid check constraint - 允许的只有:列引用、常量、
AND/OR/BETWEEN、确定性函数如ABS()、UPPER()、REGEXP - 想校验邮箱格式?
CHECK (email LIKE '%@%')合法;CHECK (email REGEXP '^.+@.+..+$')也合法
真正容易被忽略的是:CHECK 只作用于 INSERT 和 UPDATE,对 SELECT、DELETE、LOAD DATA INFILE 完全无感——它不是数据清洗工具,也不是读取过滤器。


















