3

我的应用程序团队正在尝试使用由他们的程序动态构建的 SELECT 查询从表中获取 85,000 个值。

SELECT * FROM TEST_TABLE
   WHERE (
        ID IN (00001,00002, ..., 01000)
   OR   ID IN (01001,01002, ..., 02000)
   ...
   OR   ID IN (84001,84002, ..., 85000)
   ));

但我收到一个错误“ORA-00913 值太多”。

如果我将 in 子句减少到只有 65,000 个值,我不会收到此错误。IN CLAUSE 的值是否有任何限制(伴随 OR 子句)

4

1 回答 1

5

问题不在于in列表;它是关于 -or分隔的复合条件数量的限制。我相信这个限制并不or特别适用于任何复合条件,使用or,andnot, 带或不带括号的任何组合。而且,重要的是,这似乎没有记录在任何地方,也没有得到甲骨文的任何人的认可。

正如您已经清楚地知道的那样,in列表中有 1000 个项目的限制 - 您已经解决了这个问题。

解析器将条件扩展in为复合的 -or分隔条件。适用于您的限制是我已经提到的限制。

or限制为 65,535 个“原子”条件(与, and,放在一起not)。写出证实这一点的例子并不难。

更好的问题是为什么(当然还有如何解决它)。

我的怀疑:要评估这种复合条件,编译后的代码必须使用堆栈,这很可能实现为数组。该数组由无符号的 16 位整数索引(为什么这么小,只有 Oracle 才能知道)。所以堆栈大小不能超过 2^16 = 65,536; 实际上只少了一个,因为 Oracle 认为数组索引从 1 开始,而不是从 0 开始——所以它们丢失了一个索引值 (0)。

解决方法:创建一个临时表来存储 85,000 个值。请注意,使用元组(实际上是人工的)的想法允许您克服单个in列表的 1000 个值的限制,但它不适用于or- 分隔的复合条件中 65,535 个“原子”条件的限制;此限制适用于最一般的情况,无论条件最初来自何处(in列表或其他任何内容)。

有关 AskTom 的更多信息 - 您可能想从底部开始(我的评论,这是线程中的最后一条):

https://asktom.oracle.com/pls/apex/f?p=100:11:10737011707014::::P11_QUESTION_ID:9530196000346534356#9545388800346146842

https://asktom.oracle.com/pls/apex/f?p=100:11:10737011707014::::P11_QUESTION_ID:778625947169#9545394700346458835

于 2021-10-14T05:33:35.837 回答