json_contains()是首选,因专为判断“某json值是否在另一json值中”设计,语义清晰、支持字符串(需双引号)、数字、布尔及null,返回1/0可直用于where;而json_search()仅支持字符串模糊匹配且返回路径,对数字无效。

直接用 JSON_CONTAINS(),别绕弯;字符串要加双引号、数字不用,否则永远查不到。
为什么 JSON_CONTAINS() 是首选
它专为“某 JSON 值是否在另一 JSON 值中”设计,语义清晰、行为确定。相比 JSON_SEARCH()(只支持字符串搜索、返回路径、对数字无效),JSON_CONTAINS() 同时支持字符串和数字,且返回布尔结果(1/0),可直接用于 WHERE 条件。
常见错误现象:写成 JSON_CONTAINS(tags, 'developer') —— 这会报错或始终返回 0,因为 'developer' 是 SQL 字符串,不是 JSON 字符串;必须是 '"developer"'(SQL 字符串里包着一个带双引号的 JSON 字符串)。
- 字符串值:必须用双引号包裹,再整体用单引号括起,如
'"admin"' - 数字值:直接写,如
42或3.14,不加引号 - 布尔值:
true/false,不加引号 - null 值:
NULL(SQL 关键字),不能写成'null'
怎么写路径参数才不踩坑
如果你的 JSON 数组嵌套在对象里(比如 {"roles": ["user", "editor"]}),必须指定路径,否则 JSON_CONTAINS() 会在整个 JSON 文档顶层匹配,大概率失败。
路径写法要用 -> 操作符或字符串形式:
- 推荐写法:
info->'$.roles'—— 更安全,自动做 JSON 解析 - 等效写法:
info和'$.roles'作为两个参数:JSON_CONTAINS(info, '"editor"', '$.roles') - 错误写法:
JSON_CONTAINS(info, '"editor"', '$.roles[*]')——[*]是通配路径,JSON_CONTAINS()不支持通配符路径,会报错
如果路径不存在(比如查 $.permissions 但字段里没这个 key),JSON_CONTAINS() 返回 NULL,整行被过滤掉 —— 这是预期行为,不是 bug。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
JSON_CONTAINS() 和 JSON_SEARCH() 到底选哪个
绝大多数场景只用 JSON_CONTAINS() 就够了。JSON_SEARCH() 只在两种情况下值得考虑:
- 你要确认某个子字符串是否存在(比如查
'dev'是否在'developer'里)——JSON_CONTAINS()是全值匹配,做不到 - 你需要知道匹配项在数组里的下标(如
$[1])——JSON_CONTAINS()不返回位置信息
但注意:JSON_SEARCH() 对数字完全无效,写 JSON_SEARCH(tags, 'one', 42) 永远返回 NULL;它只认字符串字面量。
性能上,两者都不走索引(除非你建了 MySQL 8.0.17+ 的 multi-valued index),大数据量时都慢;但 JSON_CONTAINS() 内部优化更成熟,实测略快。
容易被忽略的细节:大小写与空格
JSON_CONTAINS() 默认严格匹配:字符串区分大小写,且两端空格也算内容。比如 '" admin "' ≠ '"admin"。
如果你的数据入库时没 trim,或者前端传参不规范,就会漏匹配。没有内置的 ignore-case 选项,只能靠预处理:
- 查之前统一转小写:
JSON_CONTAINS(JSON_EXTRACT(LOWER(tags), '$[*]'), LOWER('"ADMIN"'))—— 不推荐,太重 - 更实际的做法:入库时就
TRIM()+LOWER()存储,查询时保持一致 - 或者改用正则:
tags REGEXP '"admin"'(不推荐,无法利用 JSON 函数语义,且易误匹配)
真正麻烦的是嵌套结构里混用类型,比如 ["admin", 42, true] —— 查 "admin" 没问题,但查 42 或 true 必须确保类型完全一致(不能用字符串 '"42"' 去查数字 42)。










