SQL JSON 数据类型查询与操作

1次阅读

mysql 5.7+ json类型需规范使用:json_contains要求参数均为json类型且路径精确;取值用->>避免隐式转换;建索引须通过stored生成列实现;路径严格区分大小写且不可含空格。

SQL JSON 数据类型查询与操作

mysql 5.7+ 的 jsON 类型不是“能存 json 就完事了”,查不准、改不掉、索引失效是常态,核心问题在函数用错、路径写崩、类型隐式转换。

JSON_CONTAINS 为什么总返回 FALSE?

常见错误是把字符串当 JSON 值传进去,或者路径没写对。这个函数只认真正的 JSON 值,'{"id": 1}' 是字符串,JSON_OBJECT('id', 1)CAST('{"id": 1}' AS JSON) 才是合法 JSON。

  • 必须确保左右操作数都是 JSON 类型,否则自动转成字符串后比对失败
  • 第二个参数是「要查找的 JSON 值」,不是路径——比如查 {"tags": ["a", "b"]} 是否含 "a",得写 JSON_CONTAINS(json_col, '"a"', '$.tags'),注意 "a" 要加双引号变成 JSON 字符串
  • 路径表达式不支持通配符(如 $..name),只支持 $ 开头的确定路径

怎么安全地从 JSON 字段取整数或布尔值?

直接用 json_col->'$.age' 拿到的是带引号的字符串(比如 "25"),参与数学运算会触发隐式转换,但一旦字段是 NULL 或格式不对就变 0,很隐蔽。

  • json_col->>'$.age'(注意 >>)强制转成 MySQL 原生类型,->> 等价于 JSON_UNQUOTE(JSON_EXTRACT(...))
  • 取布尔值时,TRUE/FALSE 在 JSON 里是小写,但 MySQL 解析后是 1/0,所以 json_col->>'$.active' 返回的是 10,可直接用于 WHERE
  • 如果不确定字段是否存在,JSON_EXTRACT 返回 NULL,而 ->->> 在路径不存在时也返回 NULL,这点一致

给 JSON 字段建索引为什么没生效?

MySQL 不支持直接对整个 JSON 列建索引,必须用生成列(generated column)+ 普通索引组合。漏掉任一环节,EXPLAIN 里都看不到 key

  • 先加生成列:ALTER table t ADD COLUMN status int AS (json_col->>'$.status') STORED;
  • 再建索引:CREATE INDEX idx_status ON t(status);
  • 查询时必须用生成列名,不能还写 json_col->>'$.status' = 1,否则索引不走——得写 status = 1
  • 生成列必须是 STORED(不能是 VIRTUAL),因为只有 STORED 才能建索引

最常被忽略的是路径大小写和空格:JSON 路径严格区分大小写,$.Name$.name 是两个东西;另外 -> 后面的路径字符串里不能有多余空格,json_col->' $.id ' 会解析失败,报 Invalid JSON path expression 错误。

text=ZqhQzanResources