搞过Oracle的应该都知道Oracle的In不能超过1000如果超过1000会直接报错。这里分享几个方案来解决这个问题。
- 使用 in + union all 的子查询,这种方法对原有代码改动最小。例如:
1 select i.* 2 from table1 i 3 where field1 in ( 4 select '1' from dual 5 union all 6 select '2' from dual 7 union all 8 select '3' from dual 9 )
Mybatis中可以这么写。PS:最好别用#{},经尝试druid解析占位符过多的时候会报错。我的druid版本是:1.0.11
<if test="@Ognl@isNotEmpty(codeList)"> and i.code in <foreach item="code" index="index" collection="codeList" open="(" separator=" union all " close=")"> select '${code}' from dual </foreach> </if>
- 跟上面方法类似,但把子查询用 with a as封装起来。这种方式如果in条件在很多地方用到,性能会比较高。例如:
1 with t as ( 2 select '1' as code from dual 3 union all 4 select '2' as code from dual 5 ) 6 select i.* 7 from table1 i 8 where i.code in ( 9 select t.code from t 10 )
- 使用 a IN (1,2,...,999) or a in (1000,1001,...1999) or ....这种方式性能相对不高。
- 在Java中按1000分批查询,再把结果加起来,这种方式稍复杂,而且查询次数过多,对原代码改动较大,最好让测试测下超过1000的场景。
- 新建临时表,再查询之前把数据都插入到表里,然后再查询。这种方式要控制好并发的场景,不然容易出错。