2016-07-15 1 views
0

Мне нужно написать простой запрос с использованием оракула, Java и mybatis:В памяти базы данных поддерживает фирменную INSERT ALL оракул синтаксис

select * from FOO foo where foo.id IN (ids) 

Теперь ids большая коллекция строк, около 7000. К сожалению, оракул имеет ограничение 1000 элементов для предложения IN.

Чтобы преодолеть это, я могу либо:

  1. сцепить запрос динамически, так что становится: Я не уверен, если он даже работает, и я очень сомневаюсь, что он выполняет хорошо
  2. использование временного таблицу и перепишите запрос на: select * from FOO foo join SOME_TEMPORARY_ID tempids on foo.id = tempids.id.

Я решил пойти на 2 варианта. Перед выполнением запроса мне нужно как-то сделать эффективную пакетную вставку в Oracle. К сожалению, Oracle имеет собственный синтаксис, чтобы сделать пакетную вставки:

INSERT ALL 
INTO some_table VALUES ('foo') 
INTO some_table VALUES ('foo1') 
INTO some_table VALUES ('foo2') 
.... 
INTO some_table VALUES ('foo12345') 
SELECT * FROM DUAL 

Теперь, я не упомянул, но я хочу написать интеграционный тест для этого, в идеале с использованием H2 или любой другой InMemory базы данных. Конечно, H2 не поддерживает этот синтаксис. Также HSQLDB.

Вы знаете какую-либо базу данных в памяти, которая полностью поддерживает проприетарный синтаксис оракула? Или, по крайней мере, это конкретное предложение INSERT ALL?

ответ

2

Спасибо, что вы описали свою основную проблему. Проверьте, может быть, это может помочь вам

where (foo.id, 0) in (('1', 0), ('2', 0),...) 

Это простое решение не имеет ограничений. Если этот ответ не подходит, дайте мне знать. Я удаляю этот ответ и снова думаю о вашей проблеме с детьми.

+0

Как насчет производительности? Что должно быть более результативным - с использованием временных таблиц или 7K элементов IN? – slnowak

+0

@slnowak Вы заметили, что ids является коллекцией, Почему просто smt как этот 'select * from FOO foo где foo.id IN (выберите * из таблицы (коллекции идентификаторы))'. Где ids - вложенная таблица. Вы можете вытаскивать в нем идентификаторы, а затем запускать запрос. О производительности Я думаю, что вложенная таблица - лучшая, временная вторая и в-третьих - третья. –

+0

Не могли бы вы немного объяснить синтаксис и функцию? Я не знал, что это существует. Это более или менее эквивалентно созданию временной таблицы? И не страдает ли этот предел 1k IN? – slnowak

0

Предел длины одного INSERT заявления (т.е. # записей можно указать значения) намек, что эта операция действительно лучше всего проводить с кратномуinsert заявления.

Можете ли вы перечислить значения из id значений в программе, вставив один (или несколько) за раз в вашу временную таблицу, после чего вы можете перейти к вашему окончательному запросу?

Конечно, это в конечном счете напоминает ваш первоначальный вариант №1, но на самом деле это комбинация # 1 и # 2, я думаю. Во всяком случае, это сработает! :)

+0

Речь идет не о пределе инструкции INSERT, а о пределе предложения IN. – slnowak

+1

Я предлагаю избегать использования предложения 'IN', присоединившись к таблице temp, содержащей все идентификаторы. Как указывает OP, задача тогда заключается в том, как вставить идентификатор в таблицу temp, и это то, что помогает мой ответ. Вы по-прежнему присоединяетесь к «списку id», но с 'JOIN' вместо' IN'. – SlimsGhost

1

Хорошо, поэтому я решил, что если я действительно хочу/должен использовать проприетарные функции/синтаксис oracle, то давайте протестируем его против прямого оракула.

Так что, если вы не заботитесь о времени выполнения и случается иметь доступ сделать Docker на сервере CI, то я рекомендую вам эти прекрасные библиотеки: https://mvnrepository.com/artifact/org.testcontainers (https://github.com/testcontainers/testcontainers-java), в том числе оракула-х модулей.

Я смог развернуть контейнер oracle-xe во время моих тестов интеграции и протестировать экземпляр live oracle.

Смежные вопросы