在执行in子句中的1000多条记录时,我的Java代码中出现了ORA-01795错误。我正在考虑使用由OR子句分隔的多个in子句将其分解为1000个条目,如下所示:
select * from table_name
where
column_name in (V1,V2,V3,...V1000)
or
column_name in (V1001,V1002,V1003,...V2000)我有一个类似-18435,16690,1719,1082,1026,100759...的字符串id,它是根据用户选择动态生成的。如何在Java中编写1-1000条记录,1001 - 2000条记录等条件的逻辑。有人能帮我吗?
发布于 2014-11-05 06:20:00
有三种可能的方法可以绕过此限制:
1)正如您已经提到的:以1000个为一批拆分语句
2)使用这些值创建一个派生表,然后连接它们:
with id_list (id) as (
select 'V1' from dual union all
select 'V2' from dual union all
select 'V3' from dual
)
select *
from the_table
where column_name in (select id from id_list);或者,您也可以连接这些值-可能会更快:
with id_list (id) as (
select 'V1' from dual union all
select 'V2' from dual union all
select 'V3' from dual
)
select t.*
from the_table t
join id_list l on t.column_name = l.id;这仍然会生成一个非常非常大的语句,但没有1000个ids的限制。不过,我不确定Oracle会以多快的速度解析它。
3)将值插入(全局)临时表,然后使用IN子句(或JOIN)。这可能是最快的解决方案。
发布于 2014-11-05 06:12:54
最近我自己撞到了这面墙:
在 IN()中,Oracle的体系结构限制为最多1000个术语
有两种解决方法:
选项1取决于具体情况。如果值列表来自查询,则可以重构为连接
选项2也很简单,但性能较差:
List<String> terms;
for (int i = 0; i <= terms.size() / 1000; i++) {
List<String> next1000 = terms.subList(i * 1000, Math.min((i + 1) * 1000, terms.size());
// build and execute query using next1000 instead of terms
}发布于 2014-11-05 07:21:12
有了这么多的值,我尽可能避免在查询中同时使用in和or,以及嵌入值的硬解析惩罚。您可以传递一个SQL值集合,并将table()集合表达式用作可以将实际表联接到的表。
这使用了一个硬编码的整数数组作为示例,但是您可以从用户输入中填充该数组。我使用的是built-in collection type definitions,比如sys.odcinumberlist,它使用数字的varray,并且被限制为32k值,但是如果您喜欢或者可能需要处理更多的值,您可以定义您自己的表类型。
int[] ids = { -18435,16690,1719,1082,1026,100759 };
ArrayDescriptor aDesc = ArrayDescriptor.createDescriptor("SYS.ODCINUMBERLIST", conn );
oracle.sql.ARRAY ora_ids = new oracle.sql.ARRAY(aDesc, conn, ids);
sql = "select t.* "
+ "from table(?) a "
+ "left join table_name t "
+ "on t.column_name = a.column_value "
+ "order by id";
pStmt = (OraclePreparedStatement) conn.prepareStatement(sql);
pStmt.setArray(1, ora_ids);
rSet = (OracleResultSet) pStmt.executeQuery();
...您的数组可以有任意多个值(您使用的集合类型和JVM内存可以处理的值都可以),并且不受in列表1000个成员的限制。
从本质上讲,table(?)最终看起来就像一个包含所有值的表,这将比用所有值填充一个实表或临时表并连接到该表更容易、更快。
当然,不要真正使用t.*,列出您需要的列;我假设您使用了*来简化这个问题……
(Here is a more complete example,但用于略有不同的场景。)
https://stackoverflow.com/questions/26745971
复制相似问题