【问题标题】:How to use more than 1000 args in IN clause in mybatis?如何在mybatis的IN子句中使用超过1000个args?
【发布时间】:2018-11-20 22:00:37
【问题描述】:

我使用 Oracle 数据库和 myBatis 作为 ORM 框架,所有查询都在 XML 映射器文件中。我需要在IN caluse 中放置几千个参数,并且我知道有一个限制,即只能放置 1000 个参数。我已经决定解决方案:

WHERE something IN (a1, a2, ..., a1000)
OR something IN (a1001, a1002, ..., a2000)
OR ...

我怎样才能在 XML 映射器文件中做到这一点?

<foreach><if>等标签,但我没有找到任何合适的可以从上面插入SQL代码到模板中。

如果这样的东西可以使它工作,那就太好了:

<some_tag collection="huge_collection" item="huge_collection[1:1000]>

</some_tag>

【问题讨论】:

标签: java oracle orm ibatis spring-mybatis


【解决方案1】:

虽然您可以解决IN 参数的数量:

  1. 数以千计的绑定值可能会产生数兆字节的 SQL。将此 SQL 发送到数据库需要很长时间。

  2. 会因为SQL解析导致效率低下。不仅解析这么长的 SQL 需要很长时间,而且每个绑定参数数量不同的调用都会被单独解析和计划(参见this article which explains it)。

  3. SQL 语句中的绑定参数有硬性限制。您可以重复 OR 几次以解决 IN 限制,但您将在某个时候达到 SQL 语句限制。

对于这种类型的查询,通常最好创建一个temporary tables。在查询之前创建它,将所有标识符插入其中,并在实际查询中将它与这个临时表连接起来,以模拟WHERE 语句。

理想情况下,您可以将查询替换为存储过程。从数据库中提取数以万计的标识符只是为了在下一个查询中将其传回数据库是低效的。

【讨论】:

    【解决方案2】:

    您可以使用&lt; foreach &gt; 标签。这个标签遍历一个集合(集合、列表等),可以组装一个大的 SQL 语句。

    您的示例将如下所示:

    WHERE something IN (
      <foreach item="i1" collection="list1" separator=",">
        #{i1}
      </foreach>
      )
    OR something IN (
      <foreach item="i2" collection="list2" separator=",">
        #{i2}
      </foreach>
      )
    OR ...
    

    以下取自MyBatis Manual 的示例将告诉您更多相关信息:

    <insert id="insertAuthor" useGeneratedKeys="true"
        keyProperty="id">
      insert into Author (username, password, email, bio) values
      <foreach item="item" collection="list" separator=",">
        (#{item.username}, #{item.password}, #{item.email}, #{item.bio})
      </foreach>
    </insert>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-24
      • 2014-10-30
      • 2010-09-28
      • 2017-02-13
      • 2013-03-30
      • 1970-01-01
      • 2013-02-19
      相关资源
      最近更新 更多