json_extract提取嵌套数组需用$.[0]取单元素、$.[*]匹配全部(8.0.4+),但返回json类型值;真正展开为多行必须用json_table,路径须写'$.items'而非带[*],且需显式声明columns类型。

JSON_EXTRACT 提取嵌套数组的基本语法
MySQL 的 JSON_EXTRACT 本身不“提取数组”,它返回的是 JSON 类型值(比如一个 JSON 数组),你需要配合 JSON_UNQUOTE、JSON_LENGTH 或后续的 JSON_TABLE 才能真正“展开”或“遍历”。直接写 JSON_EXTRACT(json_col, '$.items[0].name') 是合法的,但若 $.items 是个数组,而你想取所有 name,就不能只靠一次 JSON_EXTRACT。
- 路径中用
[0]取单个元素,[*]可匹配整个数组(MySQL 8.0.4+ 支持) -
JSON_EXTRACT(json_col, '$.items[*].name')返回的是一个 JSON 数组,比如["a","b","c"],不是三行字符串 - 如果路径不存在,
JSON_EXTRACT返回NULL,不是空数组
想把嵌套数组转成多行?必须用 JSON_TABLE
JSON_EXTRACT 拿不到“行集”,这是常见误区。真正把 $.items 这样的嵌套数组展开为结果集,得用 JSON_TABLE(MySQL 8.0.4+):
SELECT jt.name, jt.price
FROM orders,
JSON_TABLE(
data,
'$.items' COLUMNS (
name VARCHAR(100) PATH '$.name',
price DECIMAL(10,2) PATH '$.price'
)
) AS jt;
-
JSON_TABLE第二个参数是数组路径(不能带[*],直接写'$.items') -
COLUMNS里每个字段对应数组中每个对象的键;类型要显式声明,否则默认为JSON - 如果原 JSON 中
items是空数组或NULL,该行不会生成任何输出(可用LEFT JOIN配合处理)
绕不开的坑:路径错误、类型不匹配、NULL 处理
实际用的时候,这几个点最容易卡住:
- 路径写成
'$.items[0].name'却忘了items是NULL—— 结果就是整行NULL,不是报错 - 把
JSON_EXTRACT当字符串用,没套JSON_UNQUOTE,导致结果带双引号(比如"apple"而不是apple) - 在
WHERE子句里直接用JSON_EXTRACT(...)做比较,没加类型转换,可能触发隐式转换失败(如和整数比时) - 用
JSON_CONTAINS查数组元素前,没确认目标字段确实是 JSON 类型(CAST(data AS JSON)有时是必须的)
替代方案:用 JSON_EXTRACT + JSON_LENGTH 配合循环逻辑(仅限简单遍历)
如果没法用 JSON_TABLE(比如老版本 MySQL),又只需要取前 N 项,可以手动拼路径:
SELECT JSON_UNQUOTE(JSON_EXTRACT(data, '$.items[0].name')) AS name0, JSON_UNQUOTE(JSON_EXTRACT(data, '$.items[1].name')) AS name1, JSON_LENGTH(JSON_EXTRACT(data, '$.items')) AS item_count FROM orders;
-
JSON_LENGTH(JSON_EXTRACT(data, '$.items'))是判断数组长度的可靠方式(别用CHAR_LENGTH) - 手动展开最多 5–10 项还行,超过就该考虑应用层解析了
- 注意:MySQL 不支持动态路径拼接(比如 CONCAT('$.items[', i, '].name')),所以没法真“循环”
嵌套数组不是拿来“提取”的,是拿来“展开”的——这个思维切换点,很多人卡在第一步。











