SQL JSON 数据类型操作与查询技巧

2次阅读

mysql 5.7+ 查 json 字段应使用 ->> 操作符(自动去引号并转类型),如 where info->>’$.role’ = ‘admin’;路径需合法 jsonpath,含特殊字符时用双引号括起键名。

SQL JSON 数据类型操作与查询技巧

mysql 5.7+ 怎么查 json 字段里的某个 key

直接用 ->->> 操作符,别先转成字符串再正则匹配——慢且不可靠。

-> 返回带引号的 JSON 字符串(比如 "admin"),->> 自动去引号并转类型(比如变成纯文本 admin),做 WHERE 条件时几乎总该用 ->>

  • 查用户角色: select * FROM users WHERE info->>'$.role' = 'admin';
  • 查嵌套字段: SELECT info->>'$.address.city' FROM users;
  • 注意路径必须是合法 JSONPath,$ 开头,单引号包裹整个路径字符串
  • 如果 key 名含点号或空格,得用双引号括起来: info->>'$.["first.name"]'

postgresqljsonb 字段为什么用 @> 比 = 更靠谱

因为 = 要求两个 jsonb 完全一致(顺序、空格、键顺序都得一样),而实际写入时客户端序列化行为不统一,容易误判相等。

@> 是“包含”操作符,只关心结构和值是否覆盖,更符合业务语义。比如你想找所有启用了通知的用户,只要他们 JSON 里有 {"notify": true} 就行,不管其他字段有没有、顺序如何。

  • 安全写法: SELECT * FROM profiles WHERE settings @> '{"notify": true}';
  • 避免写: settings = '{"notify": true}' —— 看似一样,但可能因格式差异返回空结果
  • 复合条件用 &&(重叠)或 ?(存在 key): settings ? 'theme' AND settings @> '{"active": true}'

JSON 字段建索引到底有没有用?怎么建才生效

有用,但必须用「函数索引」,而且查询写法要跟索引定义严格对齐,否则优化器直接忽略。

MySQL 用 GENERATED column + INDEX,PostgreSQL 直接在表达式上建索引。关键是:索引里的表达式,必须和 WHERE 中出现的表达式完全一致(包括是否用 -> 还是 ->>)。

  • MySQL 示例:先加虚拟列 ALTER table users ADD role VARCHAR(20) AS (info->>'$.role');,再建索引 CREATE INDEX idx_role ON users(role);
  • PostgreSQL 示例: CREATE INDEX idx_settings_notify ON profiles ((settings->>'notify'));,之后查询必须写 WHERE settings->>'notify' = 'true'
  • 别对整个 JSON 字段建普通 B-tree 索引——没意义,它不理解内部结构
  • jsonb 的 gin 索引适合模糊查 key 或多层嵌套,但写法更复杂,日常单 key 查询用表达式索引更稳

从 JSON 字段取值时 NULL 和缺失 key 的区别处理

很多 bug 出在这儿:以为 info->>'$.phone' 返回 NULL 就代表字段不存在,其实它也可能是因为 phone 显式存了 null,或者路径压根写错了。

MySQL 用 JSON_CONTAINS_PATH 判断 key 是否存在;PostgreSQL 用 ? 操作符或 jsonb_path_exists

  • MySQL 判定 key 是否真存在: JSON_CONTAINS_PATH(info, 'one', '$.phone') 返回 1 才算有这个 key
  • PostgreSQL 判定: info ? 'phone'(仅顶层)或 jsonb_path_exists(info, '$.phone')(支持路径)
  • 写 WHERE 时别直接 WHERE info->>'$.phone' IS NOT NULL——它会把显式 null 和路径错误混为一谈
  • 如果业务上“没填”和“填了 null”语义不同,必须拆开判断,不能偷懒

JSON 查询看着简单,但路径写错、索引不生效、NULL 处理模糊这三处,占了线上问题的八成。尤其是跨团队协作时,不同服务往同一个 JSON 字段写数据,格式稍有出入,查询就静默失效。

text=ZqhQzanResources