登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  数据库 >  MySQL

MySQL CHECK_CONSTRAINTS 怎样查看表上的校验约束

来源:17golang原创

时间:2026-11-11 18:38:28 133浏览 收藏

如果你想查看 MySQL 表上已经定义了哪些 CHECK 校验,先查 INFORMATION_SCHEMA.CHECK_CONSTRAINTS。它能给出约束所属数据库、约束名称和 CHECK_CLAUSE;如果还要知道约束属于哪张表,以及当前是否启用,再按数据库名和约束名关联 INFORMATION_SCHEMA.TABLE_CONSTRAINTS。

官方地址:https://dev.mysql.com/doc/refman/8.4/en/information-schema-check-constraints-table.html

CHECK_CONSTRAINTS 能查到什么

CHECK_CONSTRAINTS 是 MySQL 的元数据表,作用是描述表级或列级 CHECK 约束。最常用的字段有三类:

  • CONSTRAINT_SCHEMA:约束所属的数据库。
  • CONSTRAINT_NAME:约束名称。
  • CHECK_CLAUSE:约束条件表达式,例如 amount > 0。

它本身主要回答“约束叫什么、属于哪个库、表达式是什么”,并不直接把目标表名称作为核心返回字段。因此,排查某张表上的约束时,不能只看这一张元数据表。

MySQL 业务表中的 CHECK 约束进入 INFORMATION_SCHEMA CHECK_CONSTRAINTS 的静态关系说明图
图1:元数据关系说明图,展示 CHECK_CONSTRAINTS 如何承载约束名称、所属库和 CHECK_CLAUSE。

先按数据库查询 CHECK 约束定义

最小查询是按 CONSTRAINT_SCHEMA 过滤。这样可以把结果限定在当前业务库中,也便于后续和表级元数据关联:

-- 只读取目标数据库中的 CHECK 约束定义
SELECT
    CONSTRAINT_SCHEMA,
    CONSTRAINT_NAME,
    CHECK_CLAUSE
FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = 'appdb'
ORDER BY CONSTRAINT_NAME;

结果中的 CHECK_CLAUSE 是约束表达式文本,不是已经执行后的真假值。例如表中有 CHECK (amount > 0),这里关注的是 amount > 0 这一条定义。

按约束名称定位单条定义

当错误信息、迁移脚本或建表语句已经给出约束名时,可以把筛选条件收窄到一个名称。约束名称在 schema 的约束命名空间内使用,因此通常同时带上数据库条件:

-- 用数据库和约束名锁定一条 CHECK 定义
SELECT
    CONSTRAINT_SCHEMA,
    CONSTRAINT_NAME,
    CHECK_CLAUSE
FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = 'appdb'
  AND CONSTRAINT_NAME = 'chk_order_amount';

如果查不到结果,先区分三种情况:约束名记错、当前连接看不到目标 schema,或者目标对象并不是 CHECK 约束。不要把“没有返回行”直接理解为“表没有任何约束”。

为什么还要关联 TABLE_CONSTRAINTS

要定位目标表,需要使用 TABLE_CONSTRAINTS。这张表提供 TABLE_SCHEMA、TABLE_NAME、CONSTRAINT_TYPE 和 ENFORCED 等信息。两张元数据表可以通过同一 schema 中的约束名关联:

-- 关联约束元数据,补出目标表和是否启用
SELECT
    cc.CONSTRAINT_SCHEMA,
    tc.TABLE_NAME,
    cc.CONSTRAINT_NAME,
    cc.CHECK_CLAUSE,
    tc.ENFORCED
FROM INFORMATION_SCHEMA.CHECK_CONSTRAINTS AS cc
JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tc
  ON tc.CONSTRAINT_SCHEMA = cc.CONSTRAINT_SCHEMA
 AND tc.CONSTRAINT_NAME = cc.CONSTRAINT_NAME
 AND tc.CONSTRAINT_TYPE = 'CHECK'
WHERE cc.CONSTRAINT_SCHEMA = 'appdb'
ORDER BY tc.TABLE_NAME, cc.CONSTRAINT_NAME;

这里的 CONSTRAINT_TYPE = 'CHECK' 是一个明确边界:它避免把同名的其他约束类型混入结果。ENFORCED 表示该 CHECK 是否被执行;定义文本和启用状态是两个不同维度,排查时要分开看。

MySQL CHECK_CONSTRAINTS 关联 TABLE_CONSTRAINTS 后定位目标表和 ENFORCED 状态的静态说明图
图2:定位边界说明图,展示 CHECK_CONSTRAINTS 与 TABLE_CONSTRAINTS 的关联关系。

按指定表筛选所有 CHECK 约束

如果问题来自某一张表,可以在关联查询中同时限定 TABLE_SCHEMA 和 TABLE_NAME。这比只依赖约束名更适合迁移前的结构盘点:

-- 列出 appdb.orders 上的全部 CHECK 约束
SELECT
    tc.TABLE_SCHEMA,
    tc.TABLE_NAME,
    tc.CONSTRAINT_NAME,
    cc.CHECK_CLAUSE,
    tc.ENFORCED
FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS AS tc
JOIN INFORMATION_SCHEMA.CHECK_CONSTRAINTS AS cc
  ON cc.CONSTRAINT_SCHEMA = tc.CONSTRAINT_SCHEMA
 AND cc.CONSTRAINT_NAME = tc.CONSTRAINT_NAME
WHERE tc.CONSTRAINT_TYPE = 'CHECK'
  AND tc.TABLE_SCHEMA = 'appdb'
  AND tc.TABLE_NAME = 'orders'
ORDER BY tc.CONSTRAINT_NAME;

这条语句的阅读顺序是“先锁定表,再确认约束类型,最后拿回定义文本”。如果同一张表有多个校验条件,结果会按约束名称分成多行,不要把多行误认为重复数据。

排查 CHECK 约束时要分清的三个字段

字段回答的问题常见用途
CONSTRAINT_NAME这条约束叫什么?按名称定位迁移或报错对象
CHECK_CLAUSE它要求什么条件?阅读实际校验表达式
TABLE_NAME它属于哪张表?确认影响范围
ENFORCED当前是否执行?区分已生效和未启用的定义

最容易混淆的是 CHECK_CLAUSE 和 ENFORCED:前者是规则文本,后者是规则状态。一个约束可以拥有正确的表达式,但如果状态不是启用,排查写入行为时就不能只看表达式。

常见查询误区

  • 只查 CHECK_CONSTRAINTS 就想得到表名:先查定义,再通过 TABLE_CONSTRAINTS 关联目标表。
  • 只按约束名过滤:把 CONSTRAINT_SCHEMA 一起写上,避免跨库同名对象造成误判。
  • 把 CHECK_CLAUSE 当成执行结果:它是条件表达式,不代表某一行当前是否满足条件。
  • 忽略 ENFORCED:排查“为什么异常数据仍能写入”时,要同时确认约束定义和启用状态。
  • 忘记元数据权限:如果结果异常为空,先检查当前账号能否读取目标 schema 的元数据,再判断约束是否不存在。

一句话总结

查看 MySQL 的 CHECK 约束可以固定成一条清晰路径:用 CHECK_CONSTRAINTS 读取所属库、约束名和 CHECK_CLAUSE,再用 schema 与约束名关联 TABLE_CONSTRAINTS,补出目标表和 ENFORCED。这样查到的就不只是规则文本,还能确认规则究竟作用在哪张表、当前是否启用。

常见问题

CHECK_CONSTRAINTS 为什么查不到表名?

它主要描述 CHECK 约束本身,目标表信息应从 TABLE_CONSTRAINTS 读取,再按 schema 和约束名关联。

CHECK_CLAUSE 是不是一条数据的校验结果?

不是。它是约束条件的定义文本,例如 amount > 0;要分析某条数据是否违反规则,应结合具体写入行为和数据库返回的错误。

ENFORCED 和 CHECK_CLAUSE 有什么区别?

CHECK_CLAUSE 说明规则内容,ENFORCED 说明规则是否执行。排查约束未生效时需要同时读取这两个维度。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>