check约束在mysql 8.0.16及以上版本才真正生效;此前版本仅语法支持但不执行校验,insert非法值不会报错,show create table中也看不到约束定义。

CHECK 约束在 MySQL 8.0.16 及以上版本才真正生效;低于该版本(包括 5.7、8.0.15 及更早)写的 CHECK 语句会被解析但直接忽略,插入非法值不会报错。
确认你的 MySQL 版本是否支持 enforced CHECK
执行 SELECT VERSION();,确保返回结果是 8.0.16 或更高。低于这个版本,即使建表语句里写了 CHECK(age >= 0),MySQL 也不会校验——INSERT INTO t VALUES (-5); 依然成功。
- MySQL 8.0.15 及之前:语法被接受,但约束不生效,
SHOW CREATE TABLE输出中也看不到约束定义 - MySQL 8.0.16+:默认
ENFORCED,非法写入会触发错误,如ERROR 3819 (HY000): Check constraint 'chk_age' is violated. - 显式加
NOT ENFORCED的话,哪怕在 8.0.16+ 也会被跳过,慎用
创建表时添加 CHECK 约束的写法差异
列级和表级写法效果一致,但可读性和维护性不同。列级约束只能引用当前列,表级可跨列做逻辑判断(比如 c1 > c2)。
- 列级写法(简洁,适合单字段):
age INT CHECK (age >= 0 AND age - 表级写法(推荐命名,便于后续管理):
CONSTRAINT chk_age_range CHECK (age BETWEEN 0 AND 120) - 多个约束可并存:
CHECK (price > 0), CHECK (stock >= 0),各自独立触发 - 约束名(
symbol)必须在库内唯一;不指定则由 MySQL 自动生成,但后期删改困难
ALTER TABLE 添加或删除 CHECK 约束
已有表想补约束,用 ALTER TABLE ... ADD CONSTRAINT;发现约束名写错或条件过严,得先删再加。
- 添加:
ALTER TABLE users ADD CONSTRAINT chk_phone_format CHECK (phone REGEXP '^1[3-9]\d{9}$'); - 删除:
ALTER TABLE users DROP CHECK chk_phone_format;(注意不是DROP CONSTRAINT) - 删除前可用
SELECT * FROM information_schema.CHECK_CONSTRAINTS WHERE CONSTRAINT_SCHEMA = 'your_db';查约束名 - 修改约束?MySQL 不支持直接
ALTER CHECK,只能删了重加
CHECK 约束不能用的表达式类型
看似合法的表达式,可能在 CHECK 中被拒绝,不是语法错,而是设计限制。
- 禁止子查询:
CHECK (status IN (SELECT code FROM valid_status))→ 报错 - 禁止不确定函数:
CHECK (created_at 、<code>CHECK (RAND() > 0.5)→ 不允许 - 禁止用户变量、系统变量、存储函数、触发器内部变量
- 允许的典型表达式:
>=、BETWEEN、IN、正则REGEXP、数学运算、列间比较(如start_time )
最容易被忽略的是:CHECK 约束对 INSERT IGNORE、UPDATE IGNORE 无效——这些语句会静默跳过违反约束的行,而不是报错。线上用 IGNORE 前务必确认是否真要容忍数据越界。











