Oracle SQL: как использовать более 1000 элементов внутри предложения IN

У меня есть оператор SQL, где я хотел бы получить данные 1200 ep_codes, используя предложение IN. Когда я включаю более 1000 ep_codes внутри предложения IN, Oracle говорит, что мне не разрешено это делать. Чтобы преодолеть это, я попытался изменить код SQL следующим образом:

SELECT period, ...
FROM   my_view
WHERE  period = '200912'
       ...
       AND ep_codes IN (...1000 ep_codes...)
       OR  ep_codes IN (...200 ep_codes...)

Код был выполнен успешно, но результаты странные (результаты вычислений выбираются для всех периодов, а не только для 200912, что не то, что я хочу). Уместно ли это сделать с помощью OR между предложениями IN или я должен выполнить два отдельных кода как один с 1000, а другой с 200 ep_codes?


Решение Pascal Martin отлично работало. Спасибо всем, кто внес ценные предложения.

Ответ 1

Не уверен, что использование большого количества значений в IN() является хорошим, на самом деле - особенно для выступлений.

Когда вы говорите "результаты странные", может быть, это потому, что проблема с круглыми скобками? Что, если вы попробуете это, а не то, что вы предложили:

SELECT ...
FROM ...
WHERE ...
      AND (
          ep_codes IN (...1000 ep_codes...)
          OR  ep_codes IN (...200 ep_codes...)
      )

Делают ли результаты менее странными?

Ответ 2

Рекомендуемый способ справиться с этим в Oracle - создать временную таблицу, записать в нее значения и присоединиться к ней. Использование динамически созданных предложений IN означает, что оптимизатор запросов выполняет "жесткий анализ" каждого запроса.

create global temporary table LOOKUP
(
    ID NUMBER
) on commit delete rows;

-- Do a batch insert from your application to populate this table
insert into lookup(id) values (?)

-- join to it
select foo from bar where code in (select id from lookup)

Ответ 3

На самом деле вы можете использовать коллекции/мультимножества здесь. Для их хранения вам понадобится тип таблицы номеров.

CREATE TYPE NUMBER_TABLE AS TABLE OF NUMBER;
...
SELECT *
FROM my_view
WHERE period MEMBER OF NUMBER_TABLE(1,2,3...10000)

Подробнее о мультисетах здесь:

Ответ 4

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

SELECT ...
FROM ...
WHERE ...
   AND ep_code in (select code from ep_code_table)

Ответ 5

можете ли вы вставить значения 1200 ep_code во временную таблицу, а затем INNER JOIN в эту таблицу для фильтрации строк?

SELECT a.*
FROM mytable a
INNER JOIN tmp ON (tmp.ep_code = a.ep_code)
WHERE ...