MySQL中无原生集合类型,JSON数组仅是结构形式,不支持去重或交并补;JSON_CONTAINS对类型敏感;复杂集合操作需JSON_TABLE转行集再用SQL处理;高频关系查询应改用关联表。
MySQL 里没有原生的“集合”数据类型,JSON 数组只是 JSON 值的一种结构形式,它不提供去重、交并补等集合运算能力。你存一个 ["a","b","a"],MySQL 完全接受——它不会自动去重,也不认为这是个“集合”。
JSON_CONTAINS() 判断元素是否存在,但要注意类型匹配这是最常用的“类似集合成员判断”的操作,但它对类型敏感:
JSON_CONTAINS('["1", "2"]', '"1"') → 1(字符串匹配)JSON_CONTAINS('[1, 2]', '1') → 1(数字匹配)JSON_CONTAINS('[1, 2]', '"1"') → 0(字符串 "1" 不等于数字 1)如果字段是 JSON 类型列 tags,查是否含标签 "mysql",得写成:
SELECT * FROM posts WHERE JSON_CONTAINS(tags, '"mysql"');
MySQL 8.0+ 提供 JSON_TABLE(),能把 JSON 数组转成行集,之后才能用标准 SQL 做集合操作:
["a","b","a"] 中取唯一值?得先 JSON_TABLE 展开,再 DISTINCT
INNER JOIN 或 IN 子查询JSON_UNION(
) 或 JSON_INTERSECT() 函数例如提取唯一标签:
SELECT DISTINCT tag FROM posts, JSON_TABLE(tags, '$[*]' COLUMNS (tag TEXT PATH '$')) AS jt;
如果业务频繁做成员判断、增删元素、求交并差,JSON 数组很快会成为性能和可维护性瓶颈:
JSON_SET() / JSON_REMOVE() 每次都重写整个字段,无法部分更新更稳的做法是拆成关联表,比如 post_tags(post_id, tag),加联合索引,该走索引就走索引。
JSON 数组适合存配置项、日志片段、前端直接消费的扁平列表——一旦涉及关系、约束、高频查询,它就不是集合,只是个字符串容器。