mysql json路径必须以$开头,否则函数静默返回null;->返回json字符串,->>返回去引号字符串;数组下标从0开始且不支持负数;where中直接用->>查嵌套字段会导致全表扫描,需建stored生成列加索引。

路径必须以 $ 开头,否则一律返回 NULL
MySQL 对 JSON 路径语法极其严格:任何不以 $ 开头的路径(比如 .user.name 或 user.name)都会让 JSON_EXTRACT、->、->> 全部静默返回 NULL,且不会报错。这是最常被忽略的硬性规则。
常见错误写法:
-
data->'.user.profile.name'→ 错误,缺$ -
data->'user.profile.name'→ 错误,既缺$也缺. -
data->'$.user["profile"].name'→ 正确,但引号非必需,仅当 key 含特殊字符(如短横线、空格)时才需双引号
-> 和 ->> 的类型差异直接影响 WHERE 和 ORDER BY 行为
data->'$.name' 返回带双引号的 JSON 字符串(类型为 json),而 data->>'$.name' 返回去引号的 UTF8MB4 字符串(类型为 varchar)。这个区别在实际查询中会直接导致逻辑失效:
- 用
->写WHERE data->'$.status' = 'active':MySQL 会尝试把 JSON 字符串"active"和字符串active比较,隐式转换失败,结果恒为 false - 用
->>写ORDER BY data->>'$.name':能正常排序;若用->,则按 JSON 字符串字节序排(即"alice"vs"bob"),但语义混乱且不可靠 - 布尔值如
true经->>返回的是字符串"true",不是原生布尔类型,不能直接用于IF()或布尔运算
嵌套数组取值必须用 [0] 这类数字下标,且从 0 开始
数组访问不支持负数索引或范围语法(如 [-1] 或 [0 to 2]),越界或字段不存在时都静默返回 NULL,无提示。
典型路径写法:
-
data->>'$.items[0].price'→ 取第一个商品的价格(注意->>去引号) -
data->>'$.users[1].profile.name'→ 取第二位用户的姓名 -
data->>'$.data."user-id"'→ 键名含短横线,必须加双引号 -
data->>'$[0].name'→ 若整个 JSON 是数组(如[{"name":"a"},{"name":"b"}]),直接用$[0]访问首元素
WHERE 中直接用 ->> 查嵌套字段必然全表扫描
MySQL 无法对 JSON 路径表达式建立有效索引。哪怕你只查 data->>'$.status',执行计划里也会显示 type: ALL —— 即每次都要解析整列 JSON 文本。
临时缓解办法:
- 加
AND JSON_VALID(data)过滤非法 JSON,避免解析失败干扰结果 - 避免在大表上对 JSON 字段做高频等值查询
长期方案(必须):
- 建
STORED生成列:ALTER TABLE t ADD COLUMN status VARCHAR(20) AS (data->>'$.status') STORED; - 再给该列加普通索引:
CREATE INDEX idx_status ON t(status); -
VIRTUAL列不能建索引,这点容易踩坑
真正需要查嵌套结构里的动态条件(比如数组中某个 code = "A" 对应的 val),JSON_EXTRACT 本身做不到,得靠 JSON_TABLE(MySQL 8.0+)或应用层处理——5.7 没有优雅解法。











