是否有
的解决方法 '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+'
);
每次执行查询时,我都会得到ORA-01795: maximum number of expressions in a list is 1000 error
。我试图在TOAD中执行查询,没有区别,同样的错误。如何修改查询以使其工作?
提前致谢
答案 0 :(得分:100)
只需使用多个in-clauses来解决这个问题:
select field1, field2, field3 from table1
where name in ('value1', 'value2', ..., 'value999')
or name in ('value1000', ..., 'value1999')
or ...;
答案 1 :(得分:22)
我最近遇到了这个问题并找到了一种厚颜无耻的做法,而没有将其他IN条款串在一起
你可以使用元组
SELECT field1, field2, field3
FROM table1
WHERE (1, name) IN ((1, value1), (1, value2), (1, value3),.....(1, value5000));
Oracle确实允许> 1000元组但不是简单的值。更多相关信息,
https://community.oracle.com/message/3515498#3515498
和
https://community.oracle.com/thread/958612
当然,如果您没有在IN中使用子查询来从临时表中获取所需的值,那么这当然是可以的。
答案 2 :(得分:18)
一些解决方法是:
1-将IN子句拆分为多个IN子句,其中文字小于1000并使用OR子句组合它们:
将原始“WHERE”子句从一个“IN”条件拆分为几个“IN”条件:
Select id from x where id in (1, 2, ..., 1000,…,1500);
要:
Select id from x where id in (1, 2, ..., 999) OR id in (1000,...,1500);
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));
3-使用临时表:
Select id from x where id in (select id from <temporary-table>);
答案 3 :(得分:7)
请使用in
- 子句中的内部查询:
select col1, col2, col3... from table1
where id in (select id from table2 where conditions...)
答案 4 :(得分:7)
还有一种方法:
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)
);
我不认为它是最佳的,但它确实有效。提示/*+ CARDINALITY(...) */
非常有用,因为Oracle不了解所传递数组的基数,也无法估算最佳执行计划。
作为另一种选择 - 批量插入临时表并使用子查询中的最后一个IN
谓词。
答案 5 :(得分:3)
还有另一种解决此问题的方法。假设你有两个表Table1和Table2。并且需要使用Criteria查询获取Table2中未引用/存在的Table1的所有条目。所以继续这样......
List list=new ArrayList();
Criteria cr=session.createCriteria(Table1.class);
cr.add(Restrictions.sqlRestriction("this_.id not in (select t2.t1_id from Table2 t2 )"));
.
.
。 。 。它将直接在SQL中执行所有子查询功能,而不包括由Hibernate框架转换的SQL中的1000个或更多参数。它对我有用。注意:您可能需要根据您的要求更改SQL部分。
答案 6 :(得分:3)
还有另一种选择: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;
我遇到了这个问题。在我的例子中,我有一个Java数据列表,其中每个项目都有一个item_id和一个customer_id。我在DB中有两个表,用于订阅各个客户的项目。我想获得项目的所有订阅列表或该项目的客户以及项目ID。
我尝试了三种变体:
选项1:从Java中选择多个
基本上,我是第一次
select item_id, token
from item_subs
where (item_id, 0) in ((:item_id_0, 0)...(:item_id_n, 0))
然后
select cus_id, token
from cus_subs
where (cus_id, 0) in ((:cus_id_0, 0)...(:cus_id_n, 0))
然后我用Java构建一个Map,其中cus_id作为键,项目列表作为值,对于每个找到的客户订阅,我添加(从第一个选择返回的列表)所有相关项目的条目ITEM_ID。这是一个更加混乱的代码
选项2:使用语法
使用像
这样的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
选项3:临时表
创建一个包含三个字段的全局临时表:rownr(主键),item_id和cus_id。在那里插入所有数据然后运行一个非常相似的选择2选项,但链接在临时表而不是with data
<强>性能强>
这不是全面科学的性能分析。
因人而异。
也就是说,临时表选项很多更慢。因为双倍如此缓慢。选项1的时间为14-15秒,选项2的时间为15-16,选项3的时间为30。
我将从与DB服务器相同的网络再次尝试它们,并在我有机会时检查是否会改变这些内容。
答案 7 :(得分:2)
我意识到这是一个老问题而且指的是TOAD但是如果你需要使用c#编写代码,你可以通过for循环拆分列表。您可以使用subList();
基本上对Java执行相同的操作public class ImageListAdapter extends ArrayAdapter {
private Context context;
private LayoutInflater inflater;
private String[] imageUrls;
public ImageListAdapter(Context context, String[] imageUrls) {
super(context, R.layout.image_view, imageUrls);
this.context = context;
this.imageUrls = imageUrls;
inflater = LayoutInflater.from(context);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (null == convertView) {
convertView = inflater.inflate(R.layout.image_view, parent, false);
}
Picasso
.with(context)
.load(imageUrls[position])
.fit() // will explain later
.into((ImageView) convertView);
return convertView;
}
}
希望这有助于某人。
答案 8 :(得分:2)
Operato union
select * from tableA where tableA.Field1 in (1,2,...999)
union
select * from tableA where tableA.Field1 in (1000,1001,...1999)
union
select * from tableA where tableA.Field1 in (2000,2001,...2999)
答案 9 :(得分:1)
**Divide a list to lists of n size**
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
public final class PartitionUtil<T> extends AbstractList<List<T>> {
private final List<T> list;
private final int chunkSize;
private PartitionUtil(List<T> list, int chunkSize) {
this.list = new ArrayList<>(list);
this.chunkSize = chunkSize;
}
public static <T> PartitionUtil<T> ofSize(List<T> list, int chunkSize) {
return new PartitionUtil<>(list, chunkSize);
}
@Override
public List<T> get(int index) {
int start = index * chunkSize;
int end = Math.min(start + chunkSize, list.size());
if (start > end) {
throw new IndexOutOfBoundsException("Index " + index + " is out of the list range <0," + (size() - 1) + ">");
}
return new ArrayList<>(list.subList(start, end));
}
@Override
public int size() {
return (int) Math.ceil((double) list.size() / (double) chunkSize);
}
}
Function call :
List<List<String>> containerNumChunks = PartitionUtil.ofSize(list, 999)
更多详细信息:https://e.printstacktrace.blog/divide-a-list-to-lists-of-n-size-in-Java-8/
答案 10 :(得分:0)
还有一种解决方法,可以对数组进行分离,对我来说非常有用,因为其他解决方案很难使用某些旧框架来实现。
select * from tableA where id = 1 or id = 2 or id = 3 ...
但是为了获得更好的性能,如果可能的话,我将结合使用Nikolai Nechai的联合解决方案。
答案 11 :(得分:0)
传递列表和循环中大多数情况下需要返回的记录数=999。
List<List<Long>> getSubLists = batchList(inputList, 999);
List<Long> newList = new ArrayList<>();
for (List<Long> subSet : getSubLists) { newList.addALL(daoCall) // add in the required list in loop }
public static <T> List<List<T>> batchList(List<T> inputList, final int maxSize) {
List<List<T>> sublists = new ArrayList<>();
final int size = inputList.size();
for (int i = 0; i < size; i += maxSize) {
sublists.add(new ArrayList<>(inputList.subList(i, Math.min(size, i + maxSize))));
}
return sublists;
}