Oracle SQL:如何在IN子句中使用超过1000个项目

Meh*_*lar 11 sql oracle

我有一个SQL语句,我希望ep_codes通过使用IN子句获得1200 的数据.当我ep_codes在IN子句中包含超过1000个内容时,Oracle说我不允许这样做.为了解决这个问题,我尝试更改SQL代码,如下所示:

SELECT period, ...
FROM   my_view
WHERE  period = '200912'
       ...
       AND ep_codes IN (...1000 ep_codes...)
       OR  ep_codes IN (...200 ep_codes...)
Run Code Online (Sandbox Code Playgroud)

代码已成功执行,但结果很奇怪(计算结果是针对所有期间提取的,而不仅仅是针对200912,这不是我想要的).是否适合使用ORbetween IN子句执行此操作,还是应该执行两个单独的代码,一个代码为1000,另一个代码代表200个ep_codes?


Pascal Martin的解决方案非常完美.感谢所有提出宝贵建议的人.

ret*_*nym 27

在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)
Run Code Online (Sandbox Code Playgroud)

  • 我们最近将一些代码从使用"in"更改为使用临时查找表.对于某些查询,性能从几分钟到一秒钟内急剧增加. (3认同)
  • 但这是对服务器的多个并行请求的有效实现吗?据我了解,Oracle 服务器上可能有几个打开的事务,试图创建`LOOKUP` 表 (2认同)

Pas*_*TIN 18

不确定在a中使用如此多的值IN()是否真的很好 - 尤其是对于表演而言.

当你说" 结果很奇怪 "时,也许这是因为括号有问题?如果您尝试这样做,而不是您提出的建议,该怎么办:

SELECT ...
FROM ...
WHERE ...
      AND (
          ep_codes IN (...1000 ep_codes...)
          OR  ep_codes IN (...200 ep_codes...)
      )
Run Code Online (Sandbox Code Playgroud)

它会让结果变得不那么奇怪吗?


Sco*_*ley 7

实际上你可以在这里使用集合/多集.您需要一个数字表类型来存储它们.

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

在这里阅读有关多集的更多信息: