JSON_EXTRACT需单引号包裹路径(如'$.user.name'),数组索引从0开始,字段含特殊字符用$["key"],结果为NULL而非空字符串;推荐优先使用->>操作符自动去引号。
MySQL 8.0+ 怎么用 JSON_EXTRACT 取出嵌套字段
直接说结论:json_extract 是 mysql 原生支持 json 字段取值的核心函数,但写法稍硬、容易漏引号或层级错位。它不自动展开数组、不处理 null 安全、也不兼容老版本(5.7 有但功能弱,8.0+ 才推荐用)。
常见错误是把路径写成 $.user.name 却忘了外层加单引号——必须是 JSON_EXTRACT(json_col, '$.user.name'),否则报错 Invalid JSON path expression。
- 路径字符串必须用单引号包裹,且以
$开头 - 数组索引从 0 开始,
$[0].id才能取第一个对象的id,写$[1]会越界返回NULL - 字段名含点号、空格或特殊字符时,得用双引号括起来:例如
$.["user.name"]或$.["first name"] - 如果目标字段不存在,结果是
NULL,不是空字符串——别拿= ''去判断
JSON_EXTRACT 和 -> / ->> 操作符的区别在哪
MySQL 5.7 引入了更简洁的箭头操作符:-> 等价于 JSON_EXTRACT,返回带引号的 JSON 字符串;->> 是“去引号版”,自动调用 JSON_UNQUOTE,适合直接当文本用。
比如 data -> '$.name' 返回 "Alice"(带双引号),而 data ->> '$.name' 返回 Alice(纯文本)。做 WHERE 匹配或 ORDER BY 时,几乎都该用 ->>,否则可能因引号导致比较失败。
-
->适合后续还要继续解析子结构的场景,比如col -> '$.items' -> '$[0].price' -
->>更安全:避免JSON_EXTRACT+JSON_UNQUOTE两层嵌套,也防NULL传给JSON_UNQUOTE报错 - 所有箭头操作符底层仍走
JSON_EXTRACT,性能无差别,但可读性高很多
从 JSON 数组里取多个元素,为什么 JSON_EXTRACT 只返回一个
因为 JSON_EXTRACT 默认只按路径匹配第一个结果。比如 $.tags[*] 看似想取全部,实际返回的是整个数组 JSON,不是逐行展开——它不等价于 SQL 的 UNNEST。
真要一行一值,得配合 JSON_TABLE(MySQL 8.0.4+)用。例如:
SELECT jt.tag FROM t, JSON_TABLE(data, '$.tags[*]' COLUMNS(tag TEXT PATH '$')) AS jt;
没升级到 8.0.4?只能靠应用层解析,或用 JSON_LENGTH + 循环变量模拟,但极不推荐——性能差、逻辑重。
-
JSON_EXTRACT(col, '$.tags')返回完整数组:["a","b","c"] -
JSON_EXTRACT(col, '$.tags[0]')只取第一个:"a" - 想 WHERE 匹配数组中是否存在某值?用
JSON_CONTAINS(col, '"x"', '$.tags'),别硬拆
PostgreSQL 或 SQLite 里有没有类似 JSON_EXTRACT 的东西
没有同名函数,但能力更自然:PostgreSQL 用 -> 和 ->>(和 MySQL 箭头语义一致),还支持 #> 路径操作符;SQLite 3.38+ 有 json_extract() 函数,参数顺序和 MySQL 相反:json_extract(json_str, '$.name')。
跨数据库写 SQL 时,别假设 JSON_EXTRACT 可移植——MySQL 的路径语法(如 $[0])在 PostgreSQL 里得写成 $[0] 加额外括号,SQLite 则不支持部分路径写法(如 $.*)。
- PostgreSQL 中
data->'user'->>'name'和 MySQL 的data ->> '$.user.name'效果相同 - SQLite 的
json_extract()不支持数组通配符[*],也没JSON_TABLE替代方案 - 如果项目要换数据库,JSON 查询逻辑最好抽到应用层,别死绑 SQL
JSON_EXTRACT 能自动展平数组——它只是“取”,不是“解构”。

















