mysql JSON字段如何做集合查询_mysql集合字段用法

来源:这里教程网 时间:2026-02-28 20:46:34 作者:

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
对数字和字符串严格区分,连空格、大小写都敏感。

相关推荐