json_table用于将json数组展开为关系表,适用于对象数组场景,不适用于嵌套过深、单字段提取或json校验;需注意path路径正确性、驱动表顺序、mysql版本及utf8mb4字符集兼容性。

JSON_TABLE 用在哪?不是所有 JSON 都适合它
JSON_TABLE 是 MySQL 8.0.4+ 提供的函数,核心作用是把一行 JSON 字符串「展开」成多行关系表。它不处理嵌套太深的结构,也不适合做 JSON 校验或提取单个字段——那是 JSON_EXTRACT 或 -> 操作符的事。
常见错误现象:把 {"name": "Alice", "tags": ["a","b"]} 直接喂给 JSON_TABLE 却没指定 tags 是数组路径,结果返回空行。
使用场景很明确:
- JSON 列里存的是「对象数组」,比如
[{"id":1,"val":"x"},{"id":2,"val":"y"}] - 你想把它当普通表 JOIN、WHERE、GROUP BY
- 数据来自外部系统(如日志、API 响应),且格式相对稳定
性能影响明显:每次调用 JSON_TABLE 都要解析整段 JSON,如果源字段没建函数索引,又在 WHERE 条件里反复用,查询会变慢。
SELECT jt.id, jt.val FROM orders o, JSON_TABLE(o.items, '$[*]' COLUMNS ( id INT PATH '$.id', val VARCHAR(20) PATH '$.val' )) AS jt WHERE o.status = 'shipped';
PATH 表达式写错,结果就全空
JSON_TABLE 的 COLUMNS 子句里,每个 PATH 必须严格匹配 JSON 结构层级。路径错一级、少个 [*]、多一层 $,整列就 NULL。
容易踩的坑:
- 把
'$.items[<em>]'</em>写成'$items[]'(漏了点) - 数组路径用了
'$.list'但实际是{"list": [{"a":1}]},得写成'$.list[*]' - 路径里混用双引号和单引号导致语法报错,MySQL 要求统一用单引号包住整个 PATH 字符串
参数差异要注意:PATH 后面可以跟 EXISTS、FOR ORDINALITY,但别误以为 FOR ORDINALITY 能排序——它只加一列序号,不改变输出顺序。
Hishop.5.2.BETA2版主要更新: [修改] 进一步优化了首页打开速度 [修改] 美化了默认模板 [修改] 优化系统架构,程序标签及SQL查询效率,访问系统页面的速度大大提高 [修改] 采用了HTML模板机制,实现了前台模板可视化编辑,降低模板制作与修改的难度. [修改] 全新更换前后台AJAX技术框架,提升了用户操作体验. 店铺管理 [新增] 整合TQ在线客服 [修改] 后台广告位增加
JSON_TABLE(data, '$' COLUMNS ( name VARCHAR(50) PATH '$.user.name', tags JSON PATH '$.user.tags', -- 保留原 JSON 片段 has_tags FOR ORDINALITY -- 这列值恒为 1,不是索引 ))
JOIN 时别忘了显式指定驱动表
JSON_TABLE 本身不支持直接 LEFT JOIN,只能靠逗号语法或 LATERAL(MySQL 8.0.14+ 支持)。但即使写了 LATERAL,优化器仍可能选错驱动表,尤其当 JSON 字段所在表数据量大、又没合适索引时。
常见错误现象:本想以主表 orders 为驱动,逐行展开其 items,结果 MySQL 先扫了 JSON_TABLE 输出的临时结果集,再反向匹配,内存暴涨甚至 OOM。
实操建议:
- 确保主表有高效过滤条件(如
WHERE created_at > '2024-01-01')并已建索引 - 在
FROM子句中把主表放前面,JSON_TABLE放后面,避免优化器乱换顺序 - 如果必须 LEFT JOIN(即某行 JSON 为空也要保留),改用
UNION ALL+IS NULL模拟,虽然啰嗦但可控
SELECT o.id, jt.item_id, jt.qty FROM orders o LATERAL JSON_TABLE(o.items, '$[*]' COLUMNS ( item_id INT PATH '$.id', qty INT PATH '$.quantity' )) AS jt WHERE o.status = 'confirmed';
MySQL 版本和字符集不兼容,解析直接失败
JSON_TABLE 在 MySQL 8.0.4 引入,但早期小版本(如 8.0.4–8.0.12)对中文、emoji、深层嵌套的支持不稳定。最常遇到的是:JSON 字符串含 UTF8MB4 字符,而连接字符集设为 utf8(非 utf8mb4),解析后字段全变成 ??? 或报错 Invalid utf8mb4 character string。
兼容性要点:
- 客户端连接必须声明
charset=utf8mb4 - JSON 列定义推荐用
JSON类型,而非TEXT;后者虽能存,但JSON_TABLE解析时可能因隐式转换出错 - 不要用
JSON_VALID()替代JSON_TABLE的容错——前者只判合法,后者在路径不匹配时静默返回 NULL,不会中断查询
容易被忽略的地方是:哪怕你确认 JSON 格式正确、路径也没错,只要客户端连接的 character_set_client 是 latin1,JSON_TABLE 就可能把中文键名识别失败,整个 COLUMNS 映射失效。









