Как использовать более 1000 аргументов в предложении IN в mybatis? - PullRequest
0 голосов
/ 11 июня 2018

Я использую базу данных 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>

Ответы [ 2 ]

0 голосов
/ 11 июня 2018

Хотя вы можете обойти количество IN параметров:

  1. Тысячи связанных значений приведут к потенциально мегабайтам SQL.Отправка этого SQL в базу данных займет много времени.

  2. Это будет неэффективно из-за синтаксического анализа SQL.Анализ этого длинного SQL не только занимает много времени, но каждый вызов с различным количеством связанных параметров будет анализироваться и планироваться отдельно (см. эту статью, которая объясняет это ).

  3. В операторе SQL существует жесткое ограничение связанных параметров.Вы можете повторить OR несколько раз, чтобы обойти ограничение IN, но в какой-то момент вы достигнете предела операторов SQL.

Для запросов такого типа обычно лучшедля создания временных таблиц .Создайте его перед запросом, вставьте в него все идентификаторы и объедините его с этой временной таблицей в фактическом запросе для имитации оператора WHERE.

В идеале вы можете заменить запрос хранимой процедурой.Вытащить десятки тысяч идентификаторов из базы данных, чтобы передать их обратно в базу данных в следующем запросе, просто неэффективно.

0 голосов
/ 11 июня 2018

Вы можете использовать тег < foreach >.Этот тег перебирает коллекцию (набор, список и т. Д.) И может собирать большой оператор 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 расскажет вам больше об этом:

<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...