json路径必须用单引号包裹且以$开头,数组用[0]、含特殊字符键名需双引号;字符串提取须json_unquote或->>操作符;where中禁用json_extract,应建生成列加索引;注意json_valid校验与反斜杠转义。

能直接用,但必须写对路径、处理好引号、避开索引陷阱——否则查出来是"Alice"而不是Alice,WHERE里一用就全表扫。
路径必须用单引号包裹,且不能漏掉$根符号
MySQL 把路径当字符串字面量处理,不是语法结构。写成 $.user.name 直接报错 ERROR 3141 (22032): Invalid JSON text;正确写法是 '$.user.name'。
- 对象嵌套:用点号连接,
'$.data.profile.avatar_url' - 数组访问:必须带方括号,
'$.items[0].title'(不是$.items.0.title) - 键名含点或空格:得加双引号,
'$.info."full.name"'或'$.config."api version"' - 多层提取不建议套函数:别写
JSON_EXTRACT(JSON_EXTRACT(data, '$.meta'), '$.id'),直接JSON_EXTRACT(data, '$.meta.id')
字符串值要加 JSON_UNQUOTE,否则带双引号
JSON_EXTRACT() 返回的是 JSON 类型值,哪怕原字段是字符串,结果也是 "Alice" 这种带引号的 JSON 字符串。直接用于 WHERE name = 'Alice' 或拼接 CONCAT() 会失败。
- 安全写法:
JSON_UNQUOTE(JSON_EXTRACT(data, '$.name'))→ 得到纯文本Alice -
JSON_UNQUOTE(NULL)仍为NULL,不用额外判空 - 数字/布尔类型可不加
JSON_UNQUOTE,MySQL 会隐式转成对应类型(如1 + JSON_EXTRACT(data, '$.count')可算) - 想一步到位?用简写操作符:
data->>'$.name'等价于JSON_UNQUOTE(JSON_EXTRACT(data, '$.name'))
WHERE 中直接用 JSON_EXTRACT 会导致全表扫描
哪怕你加了索引,只要 WHERE 条件里出现 JSON_EXTRACT(data, '$.status') = 'active',MySQL 就没法走索引——执行计划里会出现 "rows": 1000000 这类提示,说明已放弃索引。
- 真正可行的方案是建生成列:
ALTER TABLE t ADD COLUMN status VARCHAR(20) AS (JSON_UNQUOTE(JSON_EXTRACT(data, '$.status'))) STORED; - 再对生成列建索引:
CREATE INDEX idx_status ON t(status); - 之后查询就写
WHERE status = 'active',毫秒响应 - 注意:数组通配路径(如
'$.tags[*].id')不支持生成列,这种得靠JSON_TABLE()展开后查
数组越界不报错,但返回 NULL,容易埋逻辑坑
JSON_EXTRACT('{"list": [1,2]}', '$.list[5]') 不会中断查询,而是静默返回 NULL。如果你在 JOIN 或 WHERE 里依赖这个值做判断,可能漏数据或误匹配。
- 取值前先用
JSON_LENGTH()检查长度:JSON_LENGTH(JSON_EXTRACT(data, '$.items')) > 3 - 关键业务字段建议兜底:
COALESCE(JSON_UNQUOTE(JSON_EXTRACT(data, '$.code')), 'N/A') - 用
IS NOT NULL显式判断是否存在,别只靠= 'xxx' - 脏数据更危险:字段是
VARCHAR而非JSON类型时,非法 JSON(比如中文引号、尾逗号)会让整个提取返回NULL,务必加WHERE JSON_VALID(data)过滤
最常被忽略的一点:路径里的反斜杠要双写,比如 '$.path."new\old"',单写会解析失败;还有,JSON_TABLE() 对字段类型敏感——如果源字段是 VARCHAR 不是 JSON,它可能直接失效,连错误都不报。











