MySQL 冷知识:很多人不知道的 FIND_IN_SET() 用法与隐藏问题

在 MySQL 开发中,字段查询几乎每天都会遇到。

尤其是在:

  • Laravel 项目开发
  • 电商系统
  • 权限管理
  • 标签系统
  • 商品分类
  • 多选字段存储

这些业务场景里,经常会看到一种数据:

1,2,3,5,8

例如:

用户角色
商品标签
支持站点
分类 ID
权限列表

很多老项目都会直接把多个值:

用逗号存进一个字段

于是:

FIND_IN_SET()

这个 MySQL 函数就出现了。

很多开发者知道它。

但真正了解它:

  • 返回值
  • 使用场景
  • 性能问题
  • 隐藏坑点

的人其实并不多。

今天就结合实际开发场景,详细聊聊:

  • FIND_IN_SET() 是什么
  • 它到底返回什么
  • 为什么很多老项目喜欢用
  • 为什么它其实有性能风险
  • Laravel 中的实际场景
  • 什么情况下不推荐使用

一、FIND_IN_SET() 是什么

基本语法

FIND_IN_SET(查找值, 字段)

作用:

在逗号分隔字符串中查找某个值

二、最基础用法

例如:

SELECT FIND_IN_SET('php', 'java,php,mysql');

结果:

2

因为:

php 在第 2 个位置

三、没找到会返回什么?

例如:

SELECT FIND_IN_SET('python', 'java,php,mysql');

结果:

0

注意:

不是 false

而是:

0

四、实际开发中的高频场景

1、多角色字段

例如:

roles = '1,2,3'

查询包含管理员角色:

SELECT * 
FROM users
WHERE FIND_IN_SET(1, roles);

2、商品支持站点

例如:

upload_site = 'us,uk,ca'

查询支持美国站:

WHERE FIND_IN_SET('us', upload_site)

五、Laravel 中的常见写法

例如:

DB::table('product')
    ->whereRaw("FIND_IN_SET(?, upload_site)", ['us'])
    ->get();

很多 ERP 系统里都能看到这种写法。


六、为什么很多人喜欢用?

因为:

开发方便

例如:

原本需要:

中间表

很多人直接:

逗号拼接

就解决了。

尤其是:

  • 老系统
  • 快速开发项目
  • 小型后台

非常常见。


七、但它其实有很大性能问题

这是很多人不知道的地方。


八、FIND_IN_SET() 基本无法走索引

例如:

WHERE FIND_IN_SET('us', upload_site)

MySQL 通常需要:

全表扫描

原因:

字段内容不是标准结构化数据

而是:

字符串解析

九、数据量小时感觉不到

很多开发者测试时:

几千条数据

感觉:

很快

但当:

几十万
几百万

数据量出现后。

性能会明显下降。


十、为什么它不适合大型系统?

因为:

关系型数据库本质上不适合存 CSV 字符串

例如:

1,2,3,4

这种结构:

  • 无法高效索引
  • 不利于统计
  • 不利于 JOIN
  • 不利于优化

十一、正确设计其实应该用中间表

例如:

用户角色关系:

user_role

表:

user_id role_id
1 1
1 2

查询时:

JOIN

效率会高很多。


十二、为什么老项目还是很多?

因为:

开发成本低

很多时候:

业务先跑起来

后面再优化。

所以:

FIND_IN_SET()

在:

  • WordPress 插件
  • ERP 系统
  • CMS 系统
  • 老 Laravel 项目

中依然非常常见。


十三、开发中的常见坑

1、空字符串问题

例如:

FIND_IN_SET('us', '')

结果:

0

2、NULL 问题

例如:

FIND_IN_SET('us', NULL)

结果:

NULL

不是:

0

很多人容易忽略。


十四、实际开发建议

小数据量项目

可以使用:

FIND_IN_SET()

开发会比较快。


大数据量项目

建议:

中间表

不要:

逗号存字段

否则:

  • SQL 很难优化
  • 索引失效
  • 查询越来越慢

十五、总结

FIND_IN_SET() 是 MySQL 中一个:

看起来方便
但隐藏问题很多

的函数。

它特别适合:

  • 小型项目
  • 老系统
  • 快速开发

但:

并不适合大型高并发系统

很多开发者前期觉得:

真方便

但项目数据量上来后。

往往都会开始后悔:

为什么当初不用中间表

这也是很多 MySQL 老项目里的经典历史遗留问题。

温馨提示: 本文最后更新于2026-05-17 22:09:27,若文章内容或图片失效,请留言或联系站长反馈!
© 版权声明
THE END
点赞9赞赏 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容