是否有解决方法
'ORA-01795: maximum number of expressions in a list is 1000 error'
我有一个查询,它是根据一个字段的值选择字段.我使用的是in子句,有10000多个值
例:
select field1, field2, field3
from table1
where name in
(
'value1',
'value2',
...
'value10000+'
);
Run Code Online (Sandbox Code Playgroud)
每次我执行查询时,我都会得到ORA-01795: maximum number of expressions in a list is 1000 error.我试图在TOAD中执行查询,没有区别,同样的错误.如何修改查询以使其工作?
提前致谢
Fab*_*ney 108
只需使用多个in-clauses来解决这个问题:
select field1, field2, field3 from table1
where name in ('value1', 'value2', ..., 'value999')
or name in ('value1000', ..., 'value1999')
or ...;
Run Code Online (Sandbox Code Playgroud)
小智 23
我最近遇到了这个问题并找到了一种厚颜无耻的方式,而没有将其他IN子句串联在一起
你可以使用元组
SELECT field1, field2, field3
FROM table1
WHERE (1, name) IN ((1, value1), (1, value2), (1, value3),.....(1, value5000));
Run Code Online (Sandbox Code Playgroud)
Oracle确实允许> 1000个元组,但不允许简单的值.更多相关信息,
https://community.oracle.com/message/3515498#3515498
和
https://community.oracle.com/thread/958612
当然,如果您没有在IN中使用子查询来从临时表中获取所需的值.
Ahm*_*OUR 18
一些解决方案解决方案是:
1-将IN子句拆分为多个IN子句,其中文字小于1000,并使用OR子句组合它们:
将原始"WHERE"子句从一个"IN"条件拆分为几个"IN"条件:
Select id from x where id in (1, 2, ..., 1000,…,1500);
Run Code Online (Sandbox Code Playgroud)
至:
Select id from x where id in (1, 2, ..., 999) OR id in (1000,...,1500);
Run Code Online (Sandbox Code Playgroud)
2-元组的使用:限制1000适用于单个项目集:(x)IN((1),(2),(3),...).如果集合包含两个或更多项目,则没有限制:(x,0)IN((1,0),(2,0),(3,0),...):
Select id from x where (x.id, 0) IN ((1, 0), (2, 0), (3, 0),.....(n, 0));
Run Code Online (Sandbox Code Playgroud)
3-临时表的使用:
Select id from x where id in (select id from <temporary-table>);
Run Code Online (Sandbox Code Playgroud)
小智 7
请使用in-clause中的内部查询:
select col1, col2, col3... from table1
where id in (select id from table2 where conditions...)
Run Code Online (Sandbox Code Playgroud)
还有一种方法:
CREATE OR REPLACE TYPE TYPE_TABLE_OF_VARCHAR2 AS TABLE OF VARCHAR(100);
-- ...
SELECT field1, field2, field3
FROM table1
WHERE name IN (
SELECT * FROM table (SELECT CAST(? AS TYPE_TABLE_OF_VARCHAR2) FROM dual)
);
Run Code Online (Sandbox Code Playgroud)
我不认为它是最佳的,但它的工作原理.提示/*+ CARDINALITY(...) */非常有用,因为Oracle不了解传递的数组的基数,也无法估计最佳执行计划.
作为另一种选择 - 批量插入临时表并使用子查询中的最后一个用于IN谓词.
还有另一种选择:with语法。要使用 OP 示例,这将如下所示:
with data as (
select 'value1' name from dual
union all
select 'value2' name from dual
union all
...
select 'value10000+' name from dual)
select field1, field2, field3
from table1 t1
inner join data on t1.name = data.name;
Run Code Online (Sandbox Code Playgroud)
我遇到了这个问题。在我的例子中,我有一个 Java 数据列表,其中每个项目都有一个 item_id 和一个 customer_id。我在数据库中有两个表,分别订阅了各个客户的项目。我想获得所有订阅项目或该项目的客户的列表,以及项目 ID。
我尝试了三种变体:
选项 1:从 Java 中进行多项选择
基本上,我先
select item_id, token
from item_subs
where (item_id, 0) in ((:item_id_0, 0)...(:item_id_n, 0))
Run Code Online (Sandbox Code Playgroud)
然后
select cus_id, token
from cus_subs
where (cus_id, 0) in ((:cus_id_0, 0)...(:cus_id_n, 0))
Run Code Online (Sandbox Code Playgroud)
然后我用 cus_id 作为键和项目列表作为值在 Java 中构建一个 Map,并为每个找到的客户订阅添加(到从第一个选择返回的列表)所有具有该 item_id 的相关项目的条目。这是更混乱的代码
选项 2:with 语法
使用 SQL 一次性获取所有内容
with data as (
select :item_id_0 item_id, :cus_id_0 cus_id
union all
...
select :item_id_n item_id, :cus_id_n cus_id )
select I.item_id item_id, I.token token
from item_subs I
inner join data D on I.item_id = D.item_id
union all
select D.item_id item_id, C.token token
from cus_subs C
inner join data D on C.cus_id = D.cus_id
Run Code Online (Sandbox Code Playgroud)
选项 3:临时表
创建一个包含三个字段的全局临时表:rownr(主键)、item_id 和 cus_id。在那里插入所有数据,然后运行与选项 2 非常相似的选择,但链接到临时表而不是with data
表现
这不是一个完全科学的性能分析。
天啊。
也就是说,临时表选项要慢得多。因为在双所以慢。我的选项 1 为 14-15 秒,选项 2 为 15-16 秒,选项 3 为 30 秒。
我将在与数据库服务器相同的网络上再次尝试它们,并在有机会时检查是否会发生变化。