JSON_TABLE是MySQL 8.0.4+将JSON数组展开为多行关系表的原生行生成器函数,必须在FROM子句中使用;而JSON_EXTRACT仅能提取标量或JSON片段,无法自动展开数组为多行。

JSON_TABLE 是什么,它和 JSON_EXTRACT 有什么区别?
JSON_TABLE 不是提取单个值的函数,而是一个**行生成器(table function)**:它把 JSON 文档“展开”成多行多列的关系表结构,类似 UNNEST 在 PostgreSQL 中的作用。而 JSON_EXTRACT 或 ->> 只能返回标量或嵌套 JSON 片段,不能直接产出多行结果。
常见错误是试图用 JSON_EXTRACT 拆解数组并期望自动“展开”,结果只得到一个带方括号的字符串或 NULL——因为 MySQL 不会自动将 JSON 数组映射为结果集行。
- 必须用
JSON_TABLE才能将["a","b","c"]转成三行单列 - 必须用
JSON_TABLE才能把[{"id":1,"name":"x"},{"id":2,"name":"y"}]转成两行两列 -
JSON_TABLE必须配合LATERAL(隐式或显式)在FROM子句中使用,不能单独出现在SELECT列表里
基础语法怎么写,path 和 COLUMNS 怎么配?
核心结构是:JSON_TABLE(json_doc, path COLUMNS (col_def, ...)) AS alias。其中:
-
json_doc是任意返回 JSON 的表达式,比如字段名data、字符串'[{"a":1}]'或函数调用JSON_OBJECT('x', 1) -
path是 JSON Path 表达式,用于定位要展开的数组。常用$[*](根数组所有元素),$.items[*](取items字段下的数组) -
COLUMNS定义输出列:每列需指定类型(INT、VARCHAR(100)等)、PATH(子路径)、是否EXISTS或FOR ORDINALITY
示例:把用户订单 JSON 数组转成关系行
SELECT u.id, jt.order_id, jt.amount
FROM users u,
JSON_TABLE(
u.orders_json,
'$[*]' COLUMNS (
order_id INT PATH '$.id',
amount DECIMAL(10,2) PATH '$.total'
)
) AS jt;
注意:PATH '$.id' 是相对于当前数组元素的路径,不是整个文档;若字段可能缺失,加 NULL ON ERROR(MySQL 8.0.21+ 支持)避免整行被过滤掉。
处理嵌套对象和可选字段时容易踩哪些坑?
常见错误包括路径写错、类型不匹配导致列全为 NULL、遗漏 ON EMPTY/ON ERROR 控制空值行为。
- 如果 JSON 中
$.price是字符串"99.99",但定义为INT PATH '$.price',该列会是NULL,不会自动转换——得用DECIMAL(10,2)或先CAST - 想保留原始 JSON 片段(如整个
address对象),用JSON PATH '$.address',别用VARCHAR强转 - 字段可能不存在时,默认行为是
NULL ON EMPTY,但若想明确控制,写成name VARCHAR(50) PATH '$.name' NULL ON EMPTY DEFAULT 'N/A' ON ERROR - 嵌套数组(如每个订单有多个 item)需要**两层
JSON_TABLE+LATERAL**,不能在一个COLUMNS里展开两级
性能和兼容性要注意什么?
JSON_TABLE 是计算型操作,无法利用 JSON 列上的虚拟列索引加速展开过程。对大 JSON 文档或高并发场景,性能开销明显。
- 避免在 WHERE 条件里对
JSON_TABLE输出列做复杂过滤——先展开再过滤,不如提前用JSON_CONTAINS或虚拟列缩小数据集 - MySQL 8.0.4 引入,但完整功能(如
ON ERROR)需 8.0.21+;低版本遇到FUNCTION JSON_TABLE does not exist就是版本不够 - 不支持在存储过程或函数体中作为独立语句使用(如
SET @x = JSON_TABLE(...)),只能用于SELECT FROM或INSERT ... SELECT - 如果 JSON 数据量稳定且结构固定,长期看建议拆成正规表 + 外键,而不是每次查询都解析 JSON
最易被忽略的是:JSON path 中的 $ 始终指向当前作用域起点——在 '$[*]' 下,$ 是数组每个元素;在 '$.items[*]' 下,$ 是 items 数组本身,不是外层文档。路径写错,结果就全空。


















