JSON_CONTAINS 可查数组中任意值匹配,但需确保类型一致并用合法JSON格式传参,如CAST(123 AS JSON);多值OR查询推荐JSON_OVERLAPS;函数索引需与查询表达式完全一致才能加速。

JSON_CONTAINS 能否查出数组中任意一个值匹配?
可以,但必须注意 JSON_CONTAINS 默认是「全匹配」语义:它检查的是整个 JSON 值是否包含指定子文档,不是简单的“数组里有没有这个元素”。想查数组中是否存在某个值,得把目标值也包装成 JSON 格式传进去。
- 错误写法:
JSON_CONTAINS(json_col, '123')—— 字符串'123'不是合法 JSON,MySQL 会静默转为"123"(带引号),导致匹配失败 - 正确写法:
JSON_CONTAINS(json_col, '"123"')或JSON_CONTAINS(json_col, CAST(123 AS JSON)) - 若字段存的是整数数组
[1,2,123,4],用'"123"'匹配不到,必须用'123'(不带引号)——但此时要确保传入的是合法 JSON 数字字面量,推荐用CAST(123 AS JSON)
如何高效查询 JSON 数组里的多个值(OR 逻辑)?
MySQL 原生不支持 JSON_CONTAINS 的多值 OR 查询(比如“数组里有 100 或 200 或 300”),必须拆成多个 OR 条件,或改用 JSON_OVERLAPS(8.0.17+)。
-
JSON_OVERLAPS更直观:JSON_OVERLAPS(json_col, CAST('[100,200,300]' AS JSON))—— 只要两个数组有交集就返回 true - 低版本只能手写:
JSON_CONTAINS(json_col, CAST(100 AS JSON)) OR JSON_CONTAINS(json_col, CAST(200 AS JSON)) OR ... - 注意性能:每个
JSON_CONTAINS都会触发完整 JSON 解析,字段无索引时大数据量下很慢
给 JSON 数组字段加索引为什么不起作用?
直接在 JSON 字段上建普通索引(INDEX(json_col))对 JSON_CONTAINS 查询无效。MySQL 要求必须建「函数索引」,且索引表达式需和查询条件完全一致。
- 正确做法(以查字符串 ID 为例):
CREATE INDEX idx_json_tags ON t ( (CAST(json_col->>'$.tags' AS CHAR(255))) );
- 更稳妥的生成式索引(适配数组展开):
CREATE INDEX idx_json_tags ON t ( (JSON_EXTRACT(json_col, '$.tags[*]')) );
(MySQL 8.0.17+ 支持数组路径通配符索引) - 关键限制:索引只加速「等值查询」,
JSON_CONTAINS在索引列上仍需配合WHERE过滤,不能替代函数逻辑
用 JSON_SEARCH 查子字符串 vs 用 JSON_CONTAINS 查完整值?
JSON_SEARCH 是模糊匹配(类似 LIKE),JSON_CONTAINS 是精确结构匹配。选错会导致漏查或误查。
- 查「标签数组里是否含字符串
"admin"」→ 用JSON_CONTAINS(json_col, '"admin"') - 查「某个 JSON 字符串字段里是否含子串
"error"」→ 用JSON_SEARCH(json_col, 'one', '%error%') -
JSON_SEARCH返回路径字符串(如"$[0].msg"),需配合IS NOT NULL判断存在性,不能直接用于数值比较 - 二者都不能用标准 B-tree 索引加速,函数索引也不支持
JSON_SEARCH
[1,2,3] 和 ["1","2","3"] 在 MySQL 里是完全不同的 JSON 值,JSON_CONTAINS 对数字和字符串严格区分,连空格、大小写都敏感。










