首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在Java代码中解析ORA-01795

如何在Java代码中解析ORA-01795
EN

Stack Overflow用户
提问于 2014-11-05 06:07:03
回答 4查看 1.5K关注 0票数 1

在执行in子句中的1000多条记录时,我的Java代码中出现了ORA-01795错误。我正在考虑使用由OR子句分隔的多个in子句将其分解为1000个条目,如下所示:

代码语言:javascript
运行
复制
  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条记录等条件的逻辑。有人能帮我吗?

EN

回答 4

Stack Overflow用户

发布于 2014-11-05 06:20:00

有三种可能的方法可以绕过此限制:

1)正如您已经提到的:以1000个为一批拆分语句

2)使用这些值创建一个派生表,然后连接它们:

代码语言:javascript
运行
复制
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);

或者,您也可以连接这些值-可能会更快:

代码语言:javascript
运行
复制
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)。这可能是最快的解决方案。

票数 3
EN

Stack Overflow用户

发布于 2014-11-05 06:12:54

最近我自己撞到了这面墙:

IN()中,Oracle的体系结构限制为最多1000个术语

有两种解决方法:

  1. 重构查询以成为连接
  2. 保持查询不变,但在循环中多次调用它,每次调用使用少于1000个术语

选项1取决于具体情况。如果值列表来自查询,则可以重构为连接

选项2也很简单,但性能较差:

代码语言:javascript
运行
复制
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
}
票数 1
EN

Stack Overflow用户

发布于 2014-11-05 07:21:12

有了这么多的值,我尽可能避免在查询中同时使用inor,以及嵌入值的硬解析惩罚。您可以传递一个SQL值集合,并将table()集合表达式用作可以将实际表联接到的表。

这使用了一个硬编码的整数数组作为示例,但是您可以从用户输入中填充该数组。我使用的是built-in collection type definitions,比如sys.odcinumberlist,它使用数字的varray,并且被限制为32k值,但是如果您喜欢或者可能需要处理更多的值,您可以定义您自己的表类型。

代码语言:javascript
运行
复制
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,但用于略有不同的场景。)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26745971

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档