Skip to content

in 值过多怎末处理,避免 SQL 语句过长的问题

这段 MyBatis XML 片段的作用是动态生成一个 SQL 查询条件,主要用于处理 deptIds 列表的过滤,并且处理较大的 deptIds 列表,以避免生成过长的 SQL 语句。下面逐步解释这个片段的逻辑:

代码解析

xml
<where>
    <if test="deptIds != null and deptIds.size > 0">
        and (main dept id in
        <foreach collection="deptIds" index="index" item="item" open="(" separator="," close=")">
            <choose>
                <when test="((index + 1) % 900) != 0">
                    #{item}
                </when>
                <otherwise>
                    #{item}) or main dept id in (#{item}
                </otherwise>
            </choose>
        </foreach>
        )
    </if>
    and user status = 1
</where>

详细解释

  1. <where> 标签:

    • 用于自动添加 SQL 查询的 WHERE 子句。它会自动处理 ANDOR 逻辑。
  2. <if test="deptIds != null and deptIds.size > 0">:

    • 只有当 deptIds 列表不为空时,才会生成后续的查询条件。
  3. and (main dept id in ... ):

    • 生成的查询条件会在 main dept id 列表中检查。
  4. <foreach collection="deptIds" index="index" item="item" open="(" separator="," close=")">:

    • 遍历 deptIds 列表生成 SQL 中的 IN 子句。open="("close=")" 分别用于在生成的 SQL 语句前后加上括号,separator="," 用于分隔每个 ID。
  5. <choose> 标签:

    • 类似于 switch 语句,用于根据条件选择不同的 SQL 片段。
  6. <when test="((index + 1) % 900) != 0">:

    • 当当前 index 加 1 之后不是 900 的倍数时,直接输出 #{item}。这是为了避免生成过长的 SQL 语句。
  7. <otherwise> 标签:

    • index + 1 是 900 的倍数时,添加 ) or main dept id in ( 以处理 SQL 语句的长度限制。#{item}) 后再跟随一个新的 IN 子句开始。
  8. and user status = 1:

    • 附加条件,筛选出 user status 为 1 的记录。

生成的 SQL

假设 deptIds 列表包含 2000 个 ID,这段 MyBatis 代码会生成如下 SQL 片段(简化版):

sql
WHERE main dept id IN (1, 2, 3, ..., 899)
OR main dept id IN (900, 901, ..., 1799)
OR main dept id IN (1800, 1801, ..., 2000)
AND user status = 1
  • 每 900 个 ID 会被分割成一个新的 IN 子句,以避免 SQL 语句过长的问题。
  • user status = 1 用于进一步筛选结果。

这样处理是为了确保生成的 SQL 不会因为 IN 子句过长而导致性能问题或数据库错误。