后端mySQL很容易犯的bug,bug记录解决

场景介绍

我的场景如下

用户可以根据前置课程,编程语言以及相关技术三个字段,以及是否只显示收藏来筛选论文。

且支持搜索功能。

这时候经常出现一个问题。

当搜索框输入内容且搜索时,功能一切正常。

但是当搜索框没有内容的时候,功能出现问题。

给大家看一下我的后端代码

XML 复制代码
    <select id="selectByFilter" resultMap="PaperResultMap">
        select distinct p.*, t.name as teacherName, t.address as teacherAddress,
        t.phone as teacherPhone, t.wechat as teacherWechat, t.qq as teacherQQ, t.email as teacherEmail,
        t.research_direction as teacherResearchDirection, t.avatar as teacherAvatar
        from `paper` p
        left join `paper-sys`.paper_course pc on p.id = pc.paper_id
        left join `paper-sys`.paper_language pl on p.id = pl.paper_id
        left join `paper-sys`.paper_technology pt on p.id = pt.paper_id
        left join `paper-sys`.teacher t on p.teacher_id = t.id
        <where>
            <if test="studentId != null">
                and p.id in (
                select paper_id from `collect` where student_id = #{studentId}
                )
            </if>
            <if test="courseIds != null and courseIds.size() > 0">
                and pc.course_id IN
                <foreach collection="courseIds" item="item" open="(" close=")" separator=",">#{item}</foreach>
            </if>
            <if test="languageIds != null and languageIds.size() > 0">
                and pl.language_id IN
                <foreach collection="languageIds" item="item" open="(" close=")" separator=",">#{item}</foreach>
            </if>
            <if test="technologyIds != null and technologyIds.size() > 0">
                and pl.language_id IN
                <foreach collection="technologyIds" item="item" open="(" close=")" separator=",">#{item}</foreach>
            </if>
            <if test="keyword != null">
                and t.name like concat('%', #{keyword},'%') or p.name like concat('%', #{keyword} , '%')
            </if>
            <if test="id != null">
                and p.id = #{id}
            </if>
        </where>
    </select>

问题分析

我想问题一定出在sql语句上面。

所以我试了一下把sql语句代入后,在数据库直接查询会出现什么结果。

这时候就看出来问题了。

去掉那些if标签的test时是这样

java 复制代码
WHERE (p.id in ( select paper_id from `collect` where student_id = ? ) and t.name like concat('%', ?,'%')) or p.name like concat('%', ? , '%')

在 SQL 里,AND 运算符的优先级高于 OR 运算符。

那么其实我的代码实际执行逻辑和我想象的是不一样的。

这就意味着,只要论文名称(p.name)符合关键字条件,无论 p.id 是否在指定学生收藏的论文 ID 列表里,该论文都会被查询出来,从而导致筛选 studentId 的条件失效。

解决方案

解决方案就非常简单了

只需要给扩上括号就好了。

所以大家在使用and和or的时候一定要注意。

否则可能会发生难以察觉的bug

相关推荐
Bert.Cai2 分钟前
Oracle LENGTH函数详解
数据库·oracle
云和数据.ChenGuang3 分钟前
大模型厂商常用的数据库有哪些?
数据库·人工智能·pytorch·深度学习·numpy
不吃土豆的马铃薯12 分钟前
高并发服务器数据库连接池设计详解
服务器·网络·数据库·c++·mysql
Nontee16 分钟前
新手数据库进阶:大白话图解MySQL的“官方档案”——Binlog
数据库·mysql
倒流时光三十年19 分钟前
PostgreSQL VALUES 列表详解
数据库·postgresql
Nightwish520 分钟前
Oracle 数据库巡检检查清单
数据库·oracle·ffmpeg
吴声子夜歌22 分钟前
SQL经典实例——插入、更新和删除
数据库·sql
基德爆肝c语言25 分钟前
MySQL:数据库基础
数据库·mysql
倒流时光三十年26 分钟前
PostgreSQL GREATEST 条件表达式函数详解
服务器·数据库·postgresql
山峰哥30 分钟前
VBA数据结构之争:Dictionary vs Collection,性能差3倍!
服务器·数据结构·数据库·windows·sql·算法·哈希算法