FIND_IN_SET()仅适用于逗号分隔字符串的精确项匹配,不支持子串或模糊查询;参数顺序不可颠倒,NULL参与即返回NULL;无法使用索引,必致全表扫描。

find_in_set() 不能直接替代 like '%xxx%'
它只适用于字段值是「逗号分隔的字符串列表」这种特定结构。比如 tags 字段存的是 "1,3,5,8",你想查包含标签 3 的记录,才能用 FIND_IN_SET('3', tags)。如果字段是普通文本(如 name 字段存 "张三丰"),直接套用会查不到任何结果——因为 FIND_IN_SET() 不做子串匹配,只做「完整项等值查找」。
什么时候能安全替换 like 并避免误匹配
典型场景是:业务把多个 ID、状态码、分类标识等用逗号拼成一个字段存储。这时 like '%1%' 会错误命中 "10,11,21",而 FIND_IN_SET('1', field) 只匹配独立的 "1" 这一项。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
-
like '%1%'→ 匹配"1"、"10"、"21"、"abc1def" -
FIND_IN_SET('1', field)→ 只匹配"1"、"1,2,3"、"5,1,9"等含独立"1"的列表 - 字段值必须是合法逗号分隔格式;含空格、中文顿号、分号都会导致失效
参数顺序和空值行为必须注意
FIND_IN_SET(str, strlist) 第一个参数是待查项,第二个是目标列表。顺序反了会始终返回 0。另外只要任一参数为 NULL,函数就返回 NULL,在 WHERE 条件中相当于不成立。
-
FIND_IN_SET('a', 'a,b,c')→ 返回1 -
FIND_IN_SET('a', 'A,b,c')→ 返回1(MySQL 默认大小写不敏感) -
FIND_IN_SET('a', 'ab,b,c')→ 返回0(不是前缀匹配) -
FIND_IN_SET(NULL, '1,2,3')或FIND_IN_SET('1', NULL)→ 返回NULL
性能和索引限制没法绕开
FIND_IN_SET() 无法使用索引,不管字段有没有建 B+Tree 索引,执行计划里都显示 type: ALL。它本质是全表扫描 + 字符串拆解判断。如果你的表有百万级数据,又频繁调用这个函数,响应延迟会立刻暴露出来。
- 没有等价的索引优化手段,
LIKE 'xxx%'还能走前缀索引,FIND_IN_SET()完全不行 - 高并发下容易成为慢查询瓶颈,建议配合缓存或提前物化关联关系
- 真正需要模糊搜索文本内容时,应优先考虑全文索引(
FULLTEXT)或迁移到 Elasticsearch

















