json_table 是 mysql 8.0.4 引入的行生成器函数,将 json 文本按路径展开为虚拟表,支持 join/where/group by;解决日志分析、配置解析、api 响应提取等场景。

JSON_TABLE 是什么,它能解决哪些实际问题
JSON_TABLE 是 MySQL 8.0.4 引入的内建表函数,作用是把一段 JSON 文本(字符串或列值)按指定路径“展开”成虚拟关系表。它不是解析器,也不是转换工具,而是一个可参与 JOIN、WHERE、GROUP BY 的**行生成器**——这意味着你能把它当普通表用,但数据来自 JSON 内容。
典型场景包括:日志字段存了 {"status":"success","code":200,"duration_ms":142},想按 code 统计错误率;用户配置字段是 JSON 数组,要查出每个 feature 开关状态;API 响应体直接落库为 TEXT,需临时提取关键字段做分析。
基本语法结构和必填参数怎么写
核心结构是:JSON_TABLE(json_doc, path COLUMNS (col_def, ...)) AS alias。其中三部分缺一不可:
-
json_doc:必须是合法 JSON 字符串(如'{"a":1,"b":[2,3]}'),不能是 NULL 或无效格式,否则整条 SELECT 报错 -
path:JSONPath 表达式,定位到要“循环展开”的节点。如果是对象,用$;如果是数组,用$[*];嵌套数组需写全,比如$.items[*].tags[*] -
COLUMNS子句里每个col_def必须声明名称、类型、路径,例如id INT PATH '$.id';若路径不存在,该列返回 NULL(除非加NOT NULL约束,此时整行被过滤)
示例:从 JSON 数组中提取用户 ID 和邮箱
SELECT u.id, u.email
FROM JSON_TABLE(
'[{"id":101,"email":"a@x.com"},{"id":102,"email":"b@y.com"}]',
'$[*]' COLUMNS (
id INT PATH '$.id',
email VARCHAR(100) PATH '$.email'
)
) AS u;
常见报错和容易忽略的坑
实际用时最常卡在以下三点:
-
Invalid JSON text in argument 1 to function json_table:输入不是合法 JSON 字符串,比如单引号没转义、含控制字符、用了 JavaScript 风格(如undefined)。先用JSON_VALID()检查,再用JSON_PRETTY()看结构 - 路径写错导致无结果:比如原 JSON 是
{"data":{"users":[{"name":"A"}]}},却写'$.users[*]'(漏了data),结果为空集而不是报错。建议先用JSON_EXTRACT(col, '$.data.users')确认路径 - 数组嵌套过深时性能陡降:对 10KB+ 的 JSON 字段执行
$.logs[*].events[*].meta[*]展开,可能触发大量内存拷贝。优先考虑提前在应用层拆分,或加 WHERE 过滤后再进JSON_TABLE
和 JSON_EXTRACT / JSON_UNQUOTE 的配合方式
JSON_TABLE 不替代 JSON_EXTRACT,而是互补。当你只需要单个字段,JSON_EXTRACT(json_col, '$.status') 更轻量;但需要多字段、带类型转换、或要 JOIN 其他表时,JSON_TABLE 才体现价值。
注意:JSON_EXTRACT 返回带引号的 JSON 字符串(如 "active"),而 JSON_TABLE 中的 VARCHAR PATH 自动去引号;如果字段本身是数字但存为字符串(如 "123"),必须显式写 INT PATH 才能转成整数,否则仍是字符串类型参与比较
一个实用组合:先用 JSON_EXTRACT 初筛大 JSON,再喂给 JSON_TABLE
SELECT jt.name, jt.level
FROM logs,
JSON_TABLE(
JSON_EXTRACT(payload, '$.errors'),
'$[*]' COLUMNS (
name VARCHAR(50) PATH '$.name',
level INT PATH '$.severity'
)
) AS jt
WHERE JSON_VALID(payload) AND payload LIKE '%error%';
真正难的是路径表达式的准确性,以及嵌套层级与业务逻辑的耦合度——JSON 结构一变,JSON_TABLE 就得重写,这点比预定义 schema 更脆弱。











