【问题标题】:JDBC Execute select statement based on the result from another select statement [duplicate]JDBC根据另一个选择语句的结果执行选择语句[重复]
【发布时间】:2019-12-30 09:28:55
【问题描述】:

我正在尝试编写一个 java 程序,该程序需要遍历“旧值”列表以从 oracle 数据库表中获取“新值”列表。 OLD 值列表,我想从 shell 脚本中传递这个列表,该脚本将成为 java 程序的包装器。

一个 b c

--select 语句类似

select new_name from items where old_name = ? //loop through the list of old values

第二步是使用上面查询中的 new_name 在下面的 select 语句中使用

select msgid from new_name 

我正在尝试做这样的事情 -

Connection conn = DriverManager.getConnection
     ("jdbc:oracle:thin:@//host:port/SID", "userid", "password");

Statement stmt = conn.createStatement();

for (int i=0; i < arg.length; i++)
{
ResultSet getNewVal = stmt.executeQuery("select new_name from items where old_name = " + old_name[i]);

while (getNewVal.next()){

          String newVal = getNewVal.getString(1);
          ResultSet getMsgID = stmt.executeQuery("select msgid from " + newVal );
          System.out.println (getMsgID.getString(1));

}
}

问题 - 第一个查询的 ResultSet 关闭并在我执行第二个查询时生成异常(关闭的结果集:下一个)

有什么建议吗?

根据要求,包括示例表定义。

create table items ( new_name varchar2(20),old_name  varchar2(20) );
create table new_name ( msgid varchar2(20));

【问题讨论】:

  • 请包括两个表的定义。
  • 你真的是说有以列的值命名的表吗?
  • 你的意思是old_name和new_name都包含在表字段中?
  • 你为什么不用一个查询来做呢? select msgid from new_name where new_name in (select new_name from items where old_name = ?)
  • @a_horse_with_no_name new_name 是第二个查询中的实际表名。我想到了您的建议,但没想到我实际上可以将这 2 条 sql 语句放入一个查询中。

标签: java oracle jdbc


【解决方案1】:

您正在尝试使用相同的Statememt 对象来执行数据库查询。如果您重新使用相同的stmt obj 来执行另一个查询,它将关闭旧的ResultSet 上下文并且您将得到相同的错误/异常。

默认情况下,每个 Statement 对象只能同时打开一个 ResultSet 对象。因此,如果一个 ResultSet 对象的读取与另一个 ResultSet 对象的读取交错,则每个对象都必须由不同的 Statement 对象生成。 Statement 接口中的所有执行方法都会隐式关闭一个语句的当前 ResultSet 对象,如果存在打开的对象。

阅读this for more information...

虽然这可以通过多种方式解决,但我指出了两个不需要太多更改的简单解决方案。

  1. 使用另一个Statement 对象在现有ResultSet 中执行另一个查询。

    Statement stmt = conn.createStatement();
    Statement nestedStmt = conn.createStatement(); // add this line       
    
    .
    .
    .
    ResultSet getMsgID = nestedStmt.executeQuery("select msgid from " + newVal ); // Change this line in while loop
    .
    .
    .
    
  2. 使用临时的 List 或任何合适的集合来临时保存数据,但是如果 resultSet 中的结果太大,这可能会降低性能(我需要更多的 RAM 消耗)

为此,

创建一个简单的List&lt;String&gt; 并将ResultSet 的每个元素添加到这个列表中,然后遍历这个新创建的列表(不在ResultSet 上)然后不需要使用不同的Statement 对象。

我希望这会有所帮助。

【讨论】:

  • 谢谢,我正在使用选项一,非常感谢您的建议@miiiii
  • 很好,但我建议,如果您没有在其他任何地方使用第一个查询的结果,您可以使用@a_horse_with_no_name 建议的single query execution 方法,也许它可以帮助某人。
猜你喜欢
  • 1970-01-01
  • 2021-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多