Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/354.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 返回CallableStation.executeQuery()和函数调用的是什么?_Java_Sql_Oracle_Jdbc_Plsql - Fatal编程技术网

Java 返回CallableStation.executeQuery()和函数调用的是什么?

Java 返回CallableStation.executeQuery()和函数调用的是什么?,java,sql,oracle,jdbc,plsql,Java,Sql,Oracle,Jdbc,Plsql,假设有一个Oracle PL/SQL过程,它接收IN参数并返回OUT游标参数。我有一个执行此过程的jdbc代码: DataSource dataSource; //datasource was set CallableStatement statement = null; ResultSet result = null; ResultSet secondaryResult = null; Connection connection = null;

假设有一个Oracle PL/SQL过程,它接收IN参数并返回OUT游标参数。我有一个执行此过程的jdbc代码:

DataSource dataSource;
    //datasource was set
    CallableStatement statement = null;
    ResultSet result = null;
    ResultSet secondaryResult = null;
    Connection connection = null;
    try {
        connection = dataSource.getConnection();
        statement = connection.prepareCall("{? = call pl_sql_func(?)}");
        statement.registerOutParameter(1, OracleTypes.CURSOR);
        statement.setString(2,"param");
        // !
        secondaryResult = statement.executeQuery();
        secondaryResult.close();

        result = (ResultSet) statement.getObject(1);

        while(result.next()){
            //get some data
        }

    } catch (Exception ex){

    }

    finally{
        //closing statement, result, secondaryResult and connection
    }
我尝试执行这段代码,看到secondaryResult没有数据,但result有。这很正常,但有人能解释一下吗

1)语句.executeQuery()真正产生了什么?

2)当语句生成过程调用时,返回的ResultSet是否包含数据?还是它总是空的?


另外,可能的优化不是这个问题的目标。我希望代码按原样解释。

您的语句在输出参数中获得结果。根据Oracle教程,这是如何将结果集获取为CallableStatement.executeQuery返回值

statement = connection.prepareCall("{call pl_sql_func(?)}");
这个例子是针对MySQL的,但是想法很清楚

  • 因为你正在使用

    statement.registerOutParameter(1, OracleTypes.CURSOR);
    
    我可以安全地假设您的数据库SQL过程不应该返回游标,而是调用

    secondaryResult = statement.executeQuery();
    

    如果要导入Oracle的ODBC驱动程序(而不是通用Java驱动程序),请使用:

    从OracleCallableStatement调用executeQuery的行为。CallableStatement不是一个类,而是由JDBC开发人员(在本例中为Oracle)创建的

    (注:您应该安装OracleCallableStatement。)

    当你写作时

    result = (ResultSet) statement.getObject(1);
    
    看起来你是在假装,那样的话,使用它更有意义

    ResultSet result = cstmt.getCursor(1);
    
  • 线路

    statement = connection.prepareCall("{? = call pl_sql_func(?)}");
    
    不生成过程,但为。因此,调用过程应该始终输出您应该从中获取数据的结果集。如果你使用

    secondaryResult.close();
    
    您将使用假装使用的数据关闭结果集(同样,如果您使用的是Oracle JDBC)

  • 1) 虽然它确实创建了一个ResultSet(符合JDBC规范),但无法查询它的数据(因为它不包含您已经了解到的数据)。如果对其执行ResultSet.next(),则会出现“无法对Pl/SQL语句执行fetch”错误

    2) 在Oracle上,它总是空的(至少在我使用的驱动程序上是空的)。例如,在PostgreSQL上,可以从这个结果集获取数据。实际上,您将从第一个结果集中获得另一个基于光标的结果集

     //PostgreSQL
              ResultSet rs=null;
              CallableStatement stmt=null;
              String sqlQuery = "{ call pl_sql_func(?)}";//no out param needed here
              stmt=conn.prepareCall(sqlQuery);      
    
              stmt.setString(1, "param");//just 1 input param
    
              ResultSet rss =null;
              rss = stmt.executeQuery(); 
    
              if(rss!=null&&rss.next()){
                  rs = (ResultSet)rss.getObject(1);
                  rss.close();
              }
    
              while(rs.next()){
                    //get data here
              }
    

    请注意,在PostgreSQL中,您甚至不必使用RegisterOutParameter指定OUT参数(尽管这样做更好)。正如您所见,不同的数据库可以以不同的方式处理此问题。

    请参阅问题后记:“。可能的优化不是此问题的目标。我希望代码按原样解释。”这是错误的。如果存储过程/函数返回游标,则该游标应映射到结果集。@dsp\U用户希望此更正有意义。使用oracle.jdbc.*库应该自动将游标映射到结果集,请参见我答案的最后一行。您可以看到一个示例。
     //PostgreSQL
              ResultSet rs=null;
              CallableStatement stmt=null;
              String sqlQuery = "{ call pl_sql_func(?)}";//no out param needed here
              stmt=conn.prepareCall(sqlQuery);      
    
              stmt.setString(1, "param");//just 1 input param
    
              ResultSet rss =null;
              rss = stmt.executeQuery(); 
    
              if(rss!=null&&rss.next()){
                  rs = (ResultSet)rss.getObject(1);
                  rss.close();
              }
    
              while(rs.next()){
                    //get data here
              }