跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

SQL如何处理JSON字段中的嵌套数据_使用JSON_EXTRACT解析

MySQL 5.7+ 支持 JSON_EXTRACT() 但仅返回单个 JSON 值,无法展开数组;真正摊开嵌套数组需用 MySQL 8.0.4+ 的 JSON_TABLE 配合 LATERAL JOIN,并注意 JSON_VALID 校验、字符集和生成列索引优化。 JSON_EXTRACT在MySQL中根本不存在 MySQL 5.7+ 原生支持的是
JSON_EXTRACT()
函数,但注意:它不是你想象中那个能直接展开数组、返回多行的“万能解析器”。它的行为非常明确——只返回一个 JSON 类型的值(比如字符串、数字、对象或数组),且结果仍包裹在双引号或方括号里。常见错误是写成
JSON_EXTRACT(json_col, '$.items[*].name')
后直接拿去
WHERE
或
GROUP BY
,结果报错或逻辑错乱,因为返回的是
["a","b"]
这样的 JSON 字符串,不是可枚举的行集。 真正能“摊开”嵌套数组的是JSON_TABLE MySQL 8.0.4+ 引入了
JSON_TABLE
,这才是处理多层嵌套、尤其是带数组结构的正解。它把一段 JSON 当作虚拟表来 JOIN,天然支持路径映射、类型转换和层级展开。 必须用
LATERAL
关键字配合
JOIN
,否则无法引用上游表的 JSON 字段 路径表达式里不能用
[*]
通配符直接写在最外层;要写成
COLUMNS (name TEXT PATH '$.name')
这种显式列定义 嵌套数组需用嵌套的
JSON_TABLE
,例如先展开
$.shops
,再对每个
shop
的
products
字段再套一层
JSON_TABLE
示例:从
page_data
中提取所有商品标题
SELECT jt1.shop_id, jt2.title FROM t, JSON_TABLE(page_data, '$.shops[*]' COLUMNS ( shop_id STRING PATH '$.shop_id', products JSON PATH '$.products' )) AS jt1, JSON_TABLE(jt1.products, '$[*]' COLUMNS ( title STRING PATH '$.title' )) AS jt2;
别忽略JSON_VALID和字符集问题 生产环境中,JSON 字段常混入非法字符(如未转义的换行、控制符)或编码不一致(UTF-8 vs GBK),导致
JSON_TABLE
直接报错退出,整条 SQL 失败。必须前置校验: Find JSON Path Online Easily find JSON paths within JSON objects using our intuitive Json Path Finder 下载 用
JSON_VALID(json_col)
过滤掉脏数据,避免中断执行 确保字段声明为
JSON
类型,而非
TEXT
或
VARCHAR
;后者即使内容合法,
JSON_TABLE
也可能因隐式转换失败 导入时若用
LOAD DATA INFILE
,记得加
CHARACTER SET utf8mb4
性能陷阱:别在WHERE里反复调用JSON函数 像
WHERE JSON_EXTRACT(data, '$.user.id') = '123'
这种写法,每行都会触发一次 JSON 解析,且无法走索引。更糟的是,如果同时写多个
JSON_EXTRACT
,解析次数翻倍。 正确做法:提前用生成列(generated column)+ 索引固化常用路径,例如
ALTER TABLE t ADD user_id BIGINT AS (JSON_EXTRACT(data, '$.user.id')) STORED
,再给
user_id
加索引 临时分析场景可用
CTE
预解析一次,避免重复调用
JSON_CONTAINS
和
JSON_OVERLAPS
在匹配数组时比多次
JSON_EXTRACT
更高效 复杂嵌套真正难的不是语法,而是路径是否完整覆盖所有分支、空数组/空对象是否被显式处理、以及生成列索引是否真正生效——这些地方一漏,查出来就是静默丢数。

相关文章