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

SQL怎样提取JSON数组中的特定元素_利用JSON_TABLE函数

JSON_TABLE是MySQL 8.0+中唯一能将JSON数组展开为多行关系结果集的函数,必须用于需对JSON数组元素逐项JOIN、WHERE筛选或聚合的场景。 JSON_TABLE 是什么,什么时候必须用它
JSON_TABLE
不是“可选替代方案”,而是 MySQL 中 唯一能把 JSON 数组展开成标准行集(即多行结果)的函数 。如果你的 JSON 字段存的是数组(比如
[{"id":1,"name":"a"},{"id":2,"name":"b"}]
),而你想对每个元素做
JOIN
、加
WHERE
条件筛选、或与其他表关联,
JSON_EXTRACT
或
->
操作符只能返回单个值或 NULL,没法生成多行 —— 这时候就必须上
JSON_TABLE
。 常见错误现象: 用
JSON_EXTRACT(json_col, '$[0]')
只能取第一个对象,想遍历全部?手动写 N 个
$[0]
,
$[1]
… 不现实 用
SELECT ... FROM t, JSON_TABLE(...)
却没加
LATERAL
或写错别名,报错
Unknown column 't.json_col' in 'field list'
使用场景明确包括: 日志字段里存了多个标签
["bug", "ui", "backend"]
,要统计各标签出现次数 用户权限字段是对象数组
[{"role":"admin"},{"role":"editor"}]
,需查出所有含
"admin"
的用户 订单明细以 JSON 数组存在主表字段中,不想拆表也要支持按商品 ID 聚合 怎么写一个可用的 JSON_TABLE 查询 核心结构固定:
JSON_TABLE(json_expr, path COLUMNS (col_def, ...)) AS alias
,漏任何一部分都语法报错。 关键参数差异和实操建议: php版微信js-sdk支付接口类 php版微信js-sdk支付接口类 下载
json_expr
必须是合法 JSON 字符串或列名,如果是字段,建议先用
ISJSON()
或
JSON_VALID()
过滤,避免解析失败导致整行丢弃
path
写
$[*]
表示遍历整个数组;若只想处理前 3 个元素,得先用
JSON_EXTRACT(json_col, '$[0 to 2]')
截取再传入
COLUMNS
里每个
col_def
格式为
col_name type PATH '$.key' [ORDINALITY | EXISTS]
,注意:
type
必须显式声明(如
VARCHAR(50)
,
INT
),不能写
TEXT
(MySQL 不支持)
PATH
是相对于当前数组元素的路径,不是整个 JSON 的根路径 加
ORDINALITY
会多出一列序号(从 1 开始),方便排序或去重 示例(提取用户权限数组中的所有 role):
SELECT u.id, jt.role FROM users u, JSON_TABLE(u.permissions, '$[*]' COLUMNS (role VARCHAR(20) PATH '$.role') ) AS jt WHERE jt.role = 'admin';
容易踩的坑:NULL、空数组、嵌套结构怎么处理
JSON_TABLE
对非法输入非常严格,稍不注意就静默丢数据: 如果
json_expr
是
NULL
或非数组(比如传了个对象
{}
),整行不会出现在结果中,也不会报错 —— 建议在外层用
WHERE JSON_TYPE(permissions) = 'ARRAY'
预过滤 空数组
[]
会导致
JSON_TABLE
不生成任何行,这符合预期,但容易被误判为“没数据”而非“数组为空” 嵌套太深(如
$.items[].details[].price
)不能直接两层
$[*]
套用,必须分步:先用外层
JSON_TABLE
展开
items
,再对每行的
details
字段单独调一次
JSON_TABLE
性能提示:
JSON_TABLE
无法走索引,纯内存解析,字段越大越慢;如果高频查询某 key,优先建虚拟列 + 索引(如
ALTER TABLE users ADD COLUMN first_role VARCHAR(20) GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(permissions, '$[0].role'))) STORED
) 不要用
JSON_TABLE
处理超长数组(>100 元素),考虑应用层拆分或预计算 复杂点在于:它不提供“跳过解析失败项”的开关,一旦某个数组元素的
PATH
找不到字段(比如
$.role
不存在),该行直接被忽略,连
NULL
都不给 —— 这和
JSON_EXTRACT
的宽容行为完全不同。

相关文章