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

时间:2010-03-08 11:57:18

标签: sql oracle

我有一个SQL语句,我希望通过使用ep_codes子句获取1200 IN的数据。当我在IN子句中包含超过1000个ep_codes时,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的解决方案非常有效。感谢所有提出宝贵建议的人。

5 个答案:

答案 0 :(得分: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)

答案 1 :(得分:18)

不确定在IN()中使用如此多的值实际上是好的 - 尤其是对于表演而言。

当你说“结果很奇怪”时,这可能是因为括号有问题?如果你试试这个,而不是你提出的建议怎么办:

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

是否会使结果更少奇怪

答案 2 :(得分:7)

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

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

详细了解多重问题here

答案 3 :(得分:1)

似乎将性能和可维护性放在一个单独的表格中是一个更好的主意。

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

答案 4 :(得分:0)

是否可以将1200 ep_code值插入临时表,然后INNER JOIN将该值插入到该表中以替换行?

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