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实际用 JSON 做集合字段,最易忽略的是类型一致性:前端传来的
[1,2,3]和
["1","2","3"]在 MySQL 里是完全不同的 JSON 值,
JSON_CONTAINS对数字和字符串严格区分,连空格、大小写都敏感。
