bigywater.tech
MySQL / InnoDB · 82

CHECK CONSTRAINT

真实建一个CHECK约束,从INSERT和UPDATE两个方向去撞它,验证这个MySQL 8.0.16才真正生效的功能到底管不管用。

3819
CHECK约束被违反时真实统一的错误码
8.0.16
MySQL真实开始让CHECK约束生效的版本

做的事:真实建一个带CHECK约束的表,从三个方向去撞它

代码CREATE TABLE check_test ( id INT PRIMARY KEY, age INT, CONSTRAINT chk_age CHECK (age >= 0 AND age <= 150) ); INSERT INTO check_test VALUES (1, 30); -- 合法值,先插入一条基准数据

验证:三种违反方式,真实都被同一个约束拦下

实测 · 本机执行输出
INSERT INTO check_test VALUES (2, -5);    ERROR 3819: Check constraint 'chk_age' is violated.
INSERT INTO check_test VALUES (3, 200);   ERROR 3819: Check constraint 'chk_age' is violated.
UPDATE check_test SET age = -1 WHERE id=1; ERROR 3819: Check constraint 'chk_age' is violated.

三次真实操作,两次INSERT一次UPDATE,都真实被同一条chk_age约束拦了下来,错误码统一是3819——CHECK约束不只是在插入时生效,任何会导致某一行违反约束的写操作(包括UPDATE)都会真实被检查,这和唯一索引、外键这些约束的生效范围是一致的。

结论:这是MySQL 8.0.16才真正补上的功能

本文能真实测出这个约束生效,是因为本机跑的是MySQL 26.7.0——在MySQL 8.0.16之前,CREATE TABLE ... CHECK (...)这句语法真实是能写进去、能通过解析的,但InnoDB和其他存储引擎压根不会真的去检查它,相当于一个真实的空操作,很多人写了CHECK约束却不知道它从来没起过作用,直到升级到8.0.16之后才第一次真实感受到它开始拦截数据。真实还可以从information_schema.CHECK_CONSTRAINTS里查到约束的具体表达式(本文查到的是((age >= 0) and (age <= 150)),MySQL会把原始表达式重新格式化存储),这张表本身也是8.0.16之后才新增的,进一步印证了这个功能的真实生效时间点。

分步演示:CHECK约束对INSERT和UPDATE的真实拦截

每一步都是本文上面用真实DDL和DML跑出来的原始结果。

同一个约束,真实拦下三种不同的违反方式
这一步新验证的操作

    本文用到的工具

    • 本机 MySQL 26.7.0(InnoDB),真实的CHECK CONSTRAINT(MySQL 8.0.16起真正生效)
    • information_schema.CHECK_CONSTRAINTS:查看约束的真实存储表达式
    京ICP备2026067502号-1京公网安备11010502063487号