mybatis 动态SQL巧用突破in数量限制

MyBatis 动态 SQL 分块处理 IN 子句语法解析

痛点

oracle 11g 只能in1000个条件,大数据量无法处理

功能说明

用于解决数据库 IN 子句参数数量限制问题(如 Oracle 的 1000 元素限制),通过动态分块生成多组 IN 条件。


完整代码示例

<if test="piids != null and piids.size > 0">
    AND (t0.processinstid IN
    <trim suffixOverrides=" OR t0.processinstid IN()">
        <foreach collection="piids" item="item" index="index" open="(" close=")">
            <if test="index != 0">
                <choose>
                    <when test="index % 1000 == 999">) OR t0.processinstid IN (</when>
                    <otherwise>,</otherwise>
                </choose>
            </if>
            #{item}
        </foreach>
    </trim>
    )
</if>

语法逐层解析

  1. 外层条件判断
    <if test="piids != null and piids.size > 0">
  2. trim 标签清理
    <trim suffixOverrides=" OR t0.processinstid IN()">
    解决的问题:消除最后一块可能残留的无效语句
    机制:自动删除结尾匹配的指定字符串
  3. foreach 分块逻辑
    <foreach collection="piids" item="item" index="index" open="(" close=")">

分块规则

<choose>
    <when test="index % 1000 == 999">) OR t0.processinstid IN (</when>
    <otherwise>,</otherwise>
</choose>

分块策略:
每 1000 个元素 分块(索引从0开始计算)
index % 1000 == 999 ➔ 第1000个元素时触发分块
连接方式:
同块元素用 , 连接
分块时用 ) OR t0.processinstid IN ( 连接

数据库适配对照表

数据库IN 列表限制调整方案
Oracle1000保持现有代码:index % 1000 == 999
(索引从0开始,第1000个元素时分块)
SQL Server2100修改为:index % 2100 == 2099
(索引达到2099时触发分块)
MySQL无硬性限制移除分块逻辑,直接逗号连接所有元素
PostgreSQL无硬性限制移除分块逻辑,直接逗号连接所有元素

补充说明:
  1. Oracle/SQL Server 分块逻辑

    • 因数据库对 IN 子句的表达式数量有严格限制,需通过模运算 (%) 控制分块节点。
    • 公式:index % N == (N-1),其中 N 为数据库允许的最大值(Oracle=1000,SQL Server=2100)。
  2. MySQL/PostgreSQL 优化

    • 可直接简化为:
      <foreach collection="piids" item="item" open="(" close=")" separator=",">
          #{item}
      </foreach>
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值