PL / SQL过程中的空ResultSet返回非空行

时间:2016-08-10 17:33:22

标签: java stored-procedures jdbc oracle11g

我使用JDBC从正在使用SYS_REFCURSOR的Oracle存储过程中获取结果。当我在sqlPlus中执行存储过程时,我得到结果,但在Java中,我得到一个空的结果集。

我在下面找到了问题here,这似乎是完美的解决方案,除了它不起作用。

从我的日志中 - 这是构造的最终字符串: 致电ENT_GET_USERS(?,?,?,?)

有人可以建议我为什么通过Java获取空结果集吗?

我正在使用stmt.registerOutParameter(columnName, OracleTypes.CURSOR);

正如上面的链接所示,我更改了我的代码,为String参数

设置""
case Types.VARCHAR:
                            if (inputValue != null)
                                stmt.setString(columnName, inputValue);
                            else
                                stmt.setString(columnName, "");

我的程序定义如下:

   CREATE OR REPLACE PROCEDURE ENT_GET_USERS(  p_id VARCHAR2 ,  p_id_type VARCHAR2,  p_app_id VARCHAR2 , usr_result OUT SYS_REFCURSOR ) 

EDIT1 : 我从sqlplus打电话,如下所示

SQL> variable rc refcursor;

SQL> exec ENT_GET_USERS(NULL , 'APP' , NULL , :rc ) ;

PL / SQL程序已成功完成。

SQL>打印rc; //返回结果

EDIT2 : 我创建了一个测试程序,并使用缩短版的Procedure而没有运气。代码如下:

             CallableStatement cstmt = conn
                .prepareCall("{call ETTRDV_EMEA.ENT_GET_USERS (?,?,?,?)}");

        cstmt.registerOutParameter("usr_result", OracleTypes.CURSOR); // REF CURSOR

        cstmt.setString("p_id", "-1");
        cstmt.setString("p_id_type", "APP");
        cstmt.setString("p_app_id", "");

      cstmt.execute(); //updated

        ResultSet rs = (ResultSet)cstmt.getObject("usr_result");

        while (rs.next()){
            System.out.println("Next");
        }

输出:接下来..等等 - 它有效!

以下程序:

CREATE OR REPLACE PROCEDURE ENT_GET_USERS(  p_id VARCHAR2 ,  
                                            p_id_type VARCHAR2,  
                                            p_app_id VARCHAR2 , 
                                            usr_result OUT SYS_REFCURSOR) AS
BEGIN
OPEN usr_result for SELECT USR.USR_ID , USR.USR_SID, USR.USR_FIRSTNAME , USR.USR_LASTNAME , USR.REFERENCE_ID , USR.USR_CREATED_BY , USR.USR_CREATED_ON , USR.USR_UPDATED_BY , USR.USR_UPDATED_ON
                              FROM ENT_USERS USR ;
END;

从SQLPLUS执行:

exec ENT_GET_USERS('-1' , 'APP' , '', :rc ) ;

这给了我预期的结果。

我做错了什么?

EDIT3: 更新了上面的工作代码。

1 个答案:

答案 0 :(得分:0)

booleanresult 为假;这并不意味着引用游标是空的。 From the documentation

  

execute方法返回一个布尔值以指示第一个结果的形式。您必须调用方法getResultSet或getUpdateCount来检索结果;你必须调用getMoreResults来移动到任何后续的结果。

     

<强>返回:
  如果第一个结果是ResultSet对象,则为true;否则为false。如果第一个结果是更新计数或没有结果

,则返回false

程序调用没有结果。返回值与此调用恰好具有的out参数以及恰好是游标的out参数是否包含任何内容无关。

由于您已经在SQL * Plus中尝试过此操作,此时它基本上就像您已经完成了exec,但您还没有对{做出任何事情{ {1}}。

您需要获取光标,例如:

:rc

或者您没有使用OracleCallableStatement:

ResultSet rset = cstmt.getCursor("usr_result");

然后迭代结果集,就像使用查询创建的一样。

我已经将命名参数的结果混合在一起,特别是在以与定义它们的顺序不同的顺序设置它们时。您可能会发现需要使用ResultSet rset = (ResultSet) cstmt.getObject("usr_result"); getCursor(4)