关于 mysql 中 find_in_set 与 like 查询的一些思考

本文探讨了MySQL中find_in_set与LIKE两种查询方式的区别,通过实例对比了它们的查询效果及性能,并讨论了不同场景下的适用性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前段时间项目中,使用到了mysql中的find_in_set 查询,因为原先没有使用过此方法,故进行了些许研究。

如mysql官方文档所说,find_in_set (str ,  strlist) 函数,查询字段(strlist)中包含 str 的结果,return 为 符合的结果 或者  null。举例如下:

select * from  (select 1,2,3,'1,2,3' as strlist) as table1 where find_in_set('1',strlist);
返回如下:

另外一种情况:

select * from  (select 1,2,3,'1,2,3' as strlist) as table1 where find_in_set('0',strlist);
结果如下:


经过测试,已经可以看到使用like查询是可以获取到同样结果的。而mysql中也有这样的解释:find_in_set 是精确匹配,字段值以英文 ‘,’ 分隔,而like 是广泛的模糊查询,字段中无需使用分隔符。可以说,两者使用的情景不一样,不过,看到这突然想到两者的查询方式是有何区别呢?于是使用真实的表进行了一下测试:

因find_in_set检测的字段需要使用英文逗号分隔,所以创建sql如下:

SELECT id FROM `consumer` WHERE find_in_set('hoftime',company);      
SELECT id FROM `consumer` WHERE company like ',hoftime,';
结果如下:



由上图可看到,取出的结果集是有相同部分的,原因很简单,like 查询没有使用通配符,而数据存储是无序的,所以单纯使用like查询是只能获取单纯的数据,find_in_set 会全局精确匹配。那么这就有了另外一个想法,那就是,find_in_set 以及 like ‘%%’ 两者那一个比较优质呢?使用explain观察sql执行顺序,以上面的sql为基础,修改查询添加索引的字段,测试如下:

explain SELECT id FROM `consumer` WHERE find_in_set('13888888888',mobile);

explain SELECT id FROM `consumer` WHERE mobile like ',13888888888,';

添加一个等同于第一条的sql,即like'%%'方式(结果与find_in_set一致):

explain SELECT id FROM `consumer` WHERE mobile like '%,13888888888,%';


由此可以看出,查询结果一致的情况下,或者必须使用like‘%%’的情况下,二者任选其一即可,这个作用场景适合字段中以英文逗号分隔的查询语句。如果没有逗号分隔,虽然都可以获取到同样的数据,但那样的话,使用like查询会更友好一些,毕竟like'str ',like'str%' 等都能够使用索引,而同样使用find_in_set 即使能够获取到想要的数据,成本也太高了。





<think>好的,用户想了解MySQLFIND_IN_SET函数的分隔符使用方法或问题。我需要先回忆一下这个函数的用法,以及用户可能关心的点。根据引用资料,FIND_IN_SET用于逗号分隔的字符串列表查找,分隔符是逗号。用户可能需要具体的示例,或者在使用分隔符时遇到的问题,比如能否使用其他分隔符,如何处理大小写、空值等。 首先,要确认FIND_IN_SET是否只能使用逗号作为分隔符。根据引用3和4,函数确实是针对逗号分隔的字符串设计的,所以分隔符必须是逗号,不能自定义。这一点需要明确告诉用户,避免他们尝试其他分隔符导致错误。 然后,用户可能需要示例教程,比如如何正确使用逗号分隔的字段进行查询。引用中提到了基本语法和示例,比如SELECT语句中的使用方式。可以给出一个具体的例子,比如查找tags字段中包含'mysql'的记录,注意逗号分隔的格式是否正确。 接下来,用户可能遇到的问题包括大小写敏感、空值处理、模糊匹配等。引用2中提到可以用LOWER或UPPER处理大小写,以及如何处理NULL和空字符串。这些都需要在回答中说明,并提供示例代码。 另外,用户可能想知道分隔符是否可以更改。根据引用,FIND_IN_SET是硬编码为逗号的,无法修改。如果用户想用其他分隔符,可能需要使用其他方法,比如LIKE或者正则表达式,但需要指出这些方法的局限性。 还要注意INLIKE的区别,如引用4提到的,IN适用于常量列表,而FIND_IN_SET用于字段中的逗号分隔值。同时,LIKE是模糊匹配,可能返回更多结果,而FIND_IN_SET是精确匹配。这部分对比对用户理解应用场景有帮助。 用户还可能关心性能优化,比如引用2提到的限制字符串长度、避免频繁查询使用、考虑缓存机制。这些优化建议可以提升查询效率,避免全表扫描的问题。 最后,总结常见问题和解决方案,比如大小写处理、空值处理、分隔符不可更改等,帮助用户全面了解。需要确保回答结构清晰,分点说明,并给出代码示例,让用户能一步步跟着操作。</think>### MySQL FIND_IN_SET 函数分隔符使用详解 #### 一、FIND_IN_SET 函数基础 1. **功能说明** FIND_IN_SET() 是 MySQL 中专门用于在**逗号分隔的字符串列表**中精确查找特定值的函数。 语法:`FIND_IN_SET(目标值, 逗号分隔字符串字段)`,返回匹配值的位置索引(从1开始),未找到则返回0。 2. **分隔符限制** - **仅支持逗号**:该函数硬编码使用英文逗号 `,` 作为分隔符,**不可自定义其他符号**(如分号、竖线等)[^3][^4]。 - **严格匹配规则**:字符串格式必须为 `值1,值2,值3`,**不可包含空格或其他多余字符**。 #### 二、正确使用逗号分隔符示例 1. **数据准备** ```sql CREATE TABLE articles ( id INT PRIMARY KEY, tags VARCHAR(255) -- 存储逗号分隔的标签,如 "mysql,database,optimization" ); INSERT INTO articles VALUES (1, 'mysql,performance'), (2, 'database,optimization'), (3, 'mysql,database'); ``` 2. **基础查询** ```sql -- 查找包含 "mysql" 的记录 SELECT * FROM articles WHERE FIND_IN_SET('mysql', tags) > 0; ``` **结果**:返回 id=1 和 id=3 的记录。 3. **错误分隔符示例** ```sql -- 错误:字段值包含空格("mysql, performance") SELECT * FROM articles WHERE FIND_IN_SET('mysql', tags) > 0; -- 无法匹配到 "mysql, performance" ``` #### 三、常见问题解决方案 1. **大小写敏感问题** 函数默认**区分大小写**,需统一格式处理: ```sql SELECT * FROM articles WHERE FIND_IN_SET(LOWER('MySQL'), LOWER(tags)) > 0; -- 转换为小写匹配[^2] ``` 2. **空值处理** 避免 NULL 或空字符串导致异常: ```sql SELECT * FROM articles WHERE tags IS NOT NULL AND tags != '' AND FIND_IN_SET('mysql', tags) > 0; -- 排除无效值[^2] ``` 3. **模糊匹配需求** 若需同时支持模糊查询(如部分匹配),可结合 `LIKE`: ```sql SELECT * FROM articles WHERE tags LIKE '%mys%' OR FIND_IN_SET('mysql', tags) > 0; -- 混合查询[^2] ``` #### 四、其他查询方式的对比 | 方法 | 特点 | 适用场景 | |---------------|--------------------------------------------------------------------|------------------------| | `FIND_IN_SET` | 精确匹配逗号分隔字段,需严格遵循格式 | 标签、分类等多值查询 | | `IN` | 匹配常量列表(如 `WHERE id IN (1,2,3)`),不支持字段存储的列表 | 固定值筛选 | | `LIKE` | 模糊匹配,可能返回无关结果(如 `LIKE '%sql%'` 会匹配 "postgresql") | 非结构化文本搜索 | #### 五、性能优化建议 1. **限制字段长度**:避免超长字符串(如超过 255 字符)降低查询效率。 2. **慎用高频查询**:全表扫描特性可能导致性能问题,可考虑缓存机制[^2]。 3. **数据规范化**:若频繁查询,建议改用关系表(如文章-标签关联表)替代逗号分隔存储[^1]。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值