我有一个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的解决方案非常有效。感谢所有提出宝贵建议的人。
答案 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 ...