MyBatis 精确查询逗号分隔字符串

MyBatis实战:如何精确查询逗号分隔字符串中的目标值?

在日常开发中,我们经常会遇到这样的场景:数据库某个字段存储的是逗号分隔的字符串(比如 "44,4401" 或 "4401,44"),需要精确查询包含某个独立值(比如 "44")的记录。

如果直接用 LIKE '%44%',很容易误匹配到 "4401"、"144" 这类包含 "44" 但并非目标值的情况。今天就来分享一种在 MyBatis 中高效解决这个问题的方案。

问题场景再现

假设数据库表 t_code 中有一个字段 codes,存储的值可能是:

  • "44,4401"(44 和 4401 两个值)
  • "4401,44"(4401 和 44 两个值)
  • "44"(单独的 44)
  • "4401"(不含 44,仅 4401)

现在需要查询所有 codes 中包含独立的 "44" 的记录,预期结果是前三种情况,而 "4401" 不应被匹配。

为什么普通 LIKE 不行?

如果直接写:

sql 复制代码
SELECT * FROM t_code WHERE codes LIKE '%44%'

此时 "4401" 会被误匹配(因为字符串中包含 "44"),不符合「精确查询独立值」的需求。

核心解决方案:用逗号"包裹"目标值

关键思路是:让目标值和字段中的每个子项都处于相同的"逗号包围"状态,再进行匹配。

具体操作:

  1. 给数据库字段 codes 前后各拼接一个逗号,变成 ",原字符串,"(比如 "44,4401" 变成 ",44,4401,");
  2. 给目标值前后也各拼接一个逗号,变成 ",目标值,"(比如 "44" 变成 ",44,");
  3. 用 LIKE 判断拼接后的字段是否包含拼接后的目标值。

这样就能确保只匹配独立的子项,不会误判包含目标值的其他字符串。

MyBatis 代码实现

1. Mapper.xml 编写 SQL

在 Mapper.xml 中,通过 CONCAT 函数完成拼接,SQL 如下:

xml 复制代码
<select id="selectByTargetCode" resultType="com.example.entity.CodeEntity">
    SELECT * FROM t_code
    WHERE 
        -- 字段前后加逗号,目标值前后加逗号,确保精确匹配独立项
        CONCAT(',', codes, ',') LIKE CONCAT('%,', #{targetCode}, ',%')
</select>
  • CONCAT(',', codes, ','):给字段值前后加逗号(处理边界情况,比如值在开头或结尾);
  • CONCAT('%,', #{targetCode}, ',%'):给目标值前后加逗号,并用 % 匹配任意位置。

2. Mapper 接口定义

对应的 Mapper 接口需要接收目标值参数:

java 复制代码
public interface CodeMapper {
    /**
     * 精确查询包含目标值的记录
     * @param targetCode 目标值(如"44")
     * @return 匹配的记录列表
     */
    List<CodeEntity> selectByTargetCode(@Param("targetCode") String targetCode);
}

3. 效果验证

数据库 codes 值 拼接后的值 目标值"44"拼接后 是否匹配 结果是否符合预期
"44,4401" ",44,4401," ",44," 是 符合
"4401,44" ",4401,44," ",44," 是 符合
"44" ",44," ",44," 是 符合
"4401" ",4401," ",44," 否 符合

方案优势

  1. 精确性:彻底避免误匹配(如"4401"不会被当作"44"查询出来);
  2. 通用性 :适用于任何数据库(CONCAT 和 LIKE 是 SQL 标准函数);
  3. 简洁性:无需复杂逻辑,一行 SQL 即可解决问题;
  4. 兼容性:无论目标值在字符串的开头、中间还是结尾,都能正确匹配。

注意事项

  • 如果字段可能为 NULL,建议先处理空值(比如 CONCAT(',', IFNULL(codes, ''), ','));
  • 若数据量极大,这种方式可能影响查询性能(因为 CONCAT 会使索引失效),此时建议考虑拆分字段为关联表(更符合数据库设计规范)。

总结

当需要在逗号分隔的字符串中精确查询独立值时,通过「前后拼接逗号 + LIKE 匹配」的方式,能简单高效地解决问题。这种方案在 MyBatis 中只需几行代码即可实现,兼容性和精确性都能得到保证。

相关推荐
毕业设计7031 小时前
(免费领源码)django空气净化器销售系统09218- java、PHP、python、C#、小程序、大数据、单片机、网络工程等)
python·scrapy·mysql·pycharm·django·flask·pandas
代码什么用2 小时前
MyBatis使用PageHelper && MyBatis的注解式开发
mybatis
CJi0NG3 小时前
【自用】MySQL-事务
数据库·mysql
VX_bysjlw9853 小时前
数码设备销售网站设计与实现39138-计算机毕设原创(免费领源码+带部署教程)
java·vue.js·spring boot·mysql·tomcat·mybatis·idea
PHP实战开发录3 小时前
MySQL数字排序为什么乱
数据库·mysql·php
imDwAaY7 小时前
一条 SQL 发出去之后,MySQL 到底做了什么?
sql·mysql
March.s9 小时前
MySQL 数据库原理与实战:从数据管理到 LAMP 建站全解
数据库·mysql
悟道子HD9 小时前
网络安全基本功——MySQL基础
android·mysql·web安全
晚风叙码9 小时前
MySQL 增删改查(CRUD)完全指南:从入门到面试
数据库·mysql·面试
程序员Sunday1 天前
MySQL 为什么使用 B+ 树索引?把范围查询、回表和覆盖索引连起来
数据库·mysql