如何将超过 1000 个值放入 Oracle IN 子句中
有什么办法可以绕过 Oracle 10g 静态 IN 子句中 1000 个项目的限制吗? 我有一个逗号分隔的许多 ID 列表,我想在 IN 子句中使用它们,有时此列表可能超过 1000 个项目,此时 Oracle 会抛出错误。 查询类似于此...
select * from table1 where ID in (1,2,3,4,...,1001,1002,...)
Is there any way to get around the Oracle 10g limitation of 1000 items in a static IN clause? I have a comma delimited list of many of IDs that I want to use in an IN clause, Sometimes this list can exceed 1000 items, at which point Oracle throws an error. The query is similar to this...
select * from table1 where ID in (1,2,3,4,...,1001,1002,...)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
将值放入临时表中,然后执行 select where id in (select id from temptable)
Put the values in a temporary table and then do a select where id in (select id from temptable)
我几乎确定您可以使用 OR 将值拆分到多个 IN:
I am almost sure you can split values across multiple INs using OR:
您可以尝试使用以下表格:
You may try to use the following form:
你首先从哪里获取 id 列表? 由于它们是数据库中的 ID,它们是否来自之前的某些查询?
当我过去看到这种情况时,这是因为:-
我认为可能有更好的方法来重写这段代码,让这个 SQL 语句正常工作。 如果您提供更多详细信息,您可能会得到一些想法。
Where do you get the list of ids from in the first place? Since they are IDs in your database, did they come from some previous query?
When I have seen this in the past it has been because:-
I think there may be better ways to rework this code that just getting this SQL statement to work. If you provide more details you might get some ideas.
使用 ...from table(... :
这是极少数需要提示的情况之一,否则 Oracle 将不会在列 id 上使用索引。这种方法的优点之一是 Oracle 不需要一次又一次地硬解析查询在大多数情况下会变慢
编辑1简化了过程(感谢jimmyorr)+示例
示例:
这将输出:
Use ...from table(... :
This is one of the rare cases where you need a hint, else Oracle will not use the index on column id. One of the advantages of this approach is that Oracle doesn't need to hard parse the query again and again. Using a temporary table is most of the times slower.
edit 1 simplified the procedure (thanks to jimmyorr) + example
Example:
This will output:
我也来到这里寻找解决方案。
根据您需要查询的高端项目数量,并假设您的项目是唯一的,您可以将查询拆分为 1000 个项目的批量查询,并在您的末端组合结果(此处为伪代码):
这可能是在您通常不会超过 1000 个项目的情况下,这是一个很好的权衡 - 因为拥有超过 1000 个项目将是您的“高端”边缘情况。 例如,如果您有 1500 个项目,则两个 (1000, 500) 查询不会那么糟糕。 这还假设每个查询本身并不是特别昂贵。
如果您的预期项目的典型数量要大得多(例如,在 100000 范围内),需要 100 个查询,则此不是合适的。 如果是这样,那么您可能应该更认真地考虑使用上面提供的全局临时表解决方案作为最“正确”的解决方案。 此外,如果您的项目不是唯一的,您还需要解决批次中的重复结果。
I wound up here looking for a solution as well.
Depending on the high-end number of items you need to query against, and assuming your items are unique, you could split your query into batches queries of 1000 items, and combine the results on your end instead (pseudocode here):
This may be a good trade-off in the scenario where you don't typically have over 1000 items - as having over 1000 items would be your "high end" edge-case scenario. For example, in the event that you have 1500 items, two queries of (1000, 500) wouldn't be so bad. This also assumes that each query isn't particularly expensive in of its own right.
This wouldn't be appropriate if your typical number of expected items got to be much larger - say, in the 100000 range - requiring 100 queries. If so, then you should probably look more seriously into using the global temporary tables solution provided above as the most "correct" solution. Furthermore, if your items are not unique, you would need to resolve duplicate results in your batches as well.
是的,甲骨文的情况非常奇怪。
如果您在 IN 子句中指定 2000 个 id,则会失败。
这会失败:
但是如果你只是将 2000 个 id 放入另一个表(例如临时表)中,它就会起作用
下面的查询:
你可以做什么,实际上可以将记录分成很多 1000 条记录,然后逐组执行它们。
Yes, very weird situation for oracle.
if you specify 2000 ids inside the IN clause, it will fail.
this fails:
but if you simply put the 2000 ids in another table (temp table for example), it will works
below query:
what you can do, actually could split the records into a lot of 1000 records and execute them group by group.
下面是一些 Perl 代码,尝试通过创建内联视图然后从中进行选择来解决该限制。 通过使用每行包含 12 个项目的行来压缩语句文本,而不是单独从 DUAL 中选择每个项目,然后通过将所有列合并在一起来解压缩。 解压缩中的 UNION 或 UNION ALL 在这里应该没有区别,因为它全部进入 IN 内部,无论如何,IN 都会在加入之前强加唯一性,但在压缩中,UNION ALL 用于防止大量不必要的比较。 由于我过滤的数据都是整数,因此引用不是问题。
人们会像这样使用它:
Here is some Perl code that tries to work around the limit by creating an inline view and then selecting from it. The statement text is compressed by using rows of twelve items each instead of selecting each item from DUAL individually, then uncompressed by unioning together all columns. UNION or UNION ALL in decompression should make no difference here as it all goes inside an IN which will impose uniqueness before joining against it anyway, but in the compression, UNION ALL is used to prevent a lot of unnecessary comparing. As the data I'm filtering on are all whole numbers, quoting is not an issue.
One would use that like so:
您可以尝试对另一个正在获取 id 的表使用
JOIN
,而不是使用IN
子句。 这样我们就不用担心限制了。 只是我的一个想法。Instead of using
IN
clause, can you try usingJOIN
with the other table, which is fetching the id. that way we don't need to worry about limit. just a thought from my side.而不是 SELECT * FROM table1 WHERE ID IN (1,2,3,4,...,1000);
使用:
SELECT * FROM table1 WHERE ID IN (SELECT rownum AS ID FROM 双连接 BY level <= 1000);
*请注意,如果这是依赖项,您需要确保该 ID 不引用任何其他外部 IDS。 为了确保只有现有的 ID 可用,请执行以下操作:
SELECT * FROM table1 WHERE ID IN (SELECT unique(ID) FROM tablewhereidsareavailable);
干杯
Instead of
SELECT * FROM table1 WHERE ID IN (1,2,3,4,...,1000);
Use this :
SELECT * FROM table1 WHERE ID IN (SELECT rownum AS ID FROM dual connect BY level <= 1000);
*Note that you need to be sure the ID does not refer any other foreign IDS if this is a dependency. To ensure only existing ids are available then :
SELECT * FROM table1 WHERE ID IN (SELECT distinct(ID) FROM tablewhereidsareavailable);
Cheers