2011-02-24 93 views
18

我想执行匿名PL/SQL并需要获取结果集对象。我得到了可以通过在PL/SQL块内使用游标来完成的代码。执行匿名PL/SQL块并获得结果集在java中

但PL/SQL块本身将作为文本来自数据库。所以我无法编辑该PL/SQL块。它将只返回两个列名将始终相同的值。它将返回2列组合值列表。

这里我给出了示例PL/SQL。

BEGIN 

RETURN 'select distinct fundname d, fundname r from <table> where condition order by 1'; 

EXCEPTION 
    WHEN OTHERS THEN 
    RETURN 'SELECT ''Not Available'' d, ''Not Available'' r FROM dual'; 
END; 

任何答复都会有帮助。

回答

34

这里是如何“执行匿名PL/SQL,并获得ResultSet对象”一个自包含的例子

import java.sql.CallableStatement; 
import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.ResultSet; 
import java.sql.Types; 

import oracle.jdbc.OracleTypes; 

public class CallPLSQLBlockWithOneInputStringAndOneOutputStringParameterAndOneOutputCursorParameter { 

    public static void main(String[] args) throws Exception { 

     DriverManager.registerDriver(new oracle.jdbc.OracleDriver()); 

     // Warning: this is a simple example program : In a long running application, 
     // error handlers MUST clean up connections statements and result sets. 

     final Connection c = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:XE", "system", "manager"); 
     String plsql = "" + 
     " declare " + 
     " p_id varchar2(20) := null; " + 
     " l_rc sys_refcursor;" + 
     " begin " + 
     " p_id := ?; " + 
     " ? := 'input parameter was = ' || p_id;" + 
     " open l_rc for " + 
     "  select 1 id, 'hello' name from dual " + 
     "  union " + 
     "  select 2, 'peter' from dual; " + 
     " ? := l_rc;" + 
     " end;"; 

     CallableStatement cs = c.prepareCall(plsql); 
     cs.setString(1, "12345"); 
     cs.registerOutParameter(2, Types.VARCHAR); 
     cs.registerOutParameter(3, OracleTypes.CURSOR); 

     cs.execute(); 

     System.out.println("Result = " + cs.getObject(2)); 

     ResultSet cursorResultSet = (ResultSet) cs.getObject(3); 
     while (cursorResultSet.next()) 
     { 
      System.out.println (cursorResultSet.getInt(1) + " " + cursorResultSet.getString(2)); 
     } 
     cs.close(); 
     c.close(); 
    } 
} 

上面示例查询“中选择1点的ID,从双重联合‘你好’名称选择2,从双‘彼得’;”可以通过任何查询替换

2

尝试这样的事情(伪代码):

[create or replace] function get_dataset (p_query in varchar2) return sys_refcursor 
as 
    l_returnvalue sys_refcursor; 
begin 
    open l_returnvalue for p_query; 
    return l_returnvalue; 
end get_dataset; 

的REF CURSOR被返回可以像一个正常数据集被处理。

而且当心SQL注入的,当你使用这样的方法......

+2

匿名块不能返回一个值。 (SYS_REFCURSOR或其他),它会返回一个PLS-00372错误PLS-00372:在一个过程中,RETURN语句不能包含表达式' – 2011-02-24 07:59:09

+0

@Justin:是的,我将它改为函数。 – ObiWanKenobi 2011-02-24 08:01:00

2

首先,你发布的代码是无效的。匿名PL/SQL块不能返回表达式。没有PL/SQL块可以返回这样的查询结果。你需要做一些事情,比如声明一个REF CURSOR并使用各种SQL语句打开该游标。

由于匿名PL/SQL块无法将任何内容返回给调用者,因此所描述的体系结构存在问题。至少,您需要修改匿名块,以便您的JDBC代码可以注册一个绑定变量。喜欢的东西(适用于Menon's Expert Oracle JDBC Programming(注意从一个例子,我可能引入了一些小的语法错误)

CallableStatement stmt := null; 
ResultSet   rset := null; 
String   query := 'DECLARE 
           FUNCTION get_result 
           RETURN SYS_REFCURSOR 
           AS 
           l_rc SYS_REFCURSOR; 
           BEGIN 
           OPEN l_rc 
           FOR SELECT DISTINCT fundname d, fundname r 
             FROM some_table 
             WHERE some_condition 
             ORDER BY 1; 
           RETURN l_rc; 
           EXCEPTION 
           WHEN others THEN 
            OPEN l_rc 
            FOR SELECT 'Not Available' d, 'Not Available' r 
             FROM dual; 
            RETURN l_rc; 
           END get_result; 
          BEGIN 
           ? := get_result; 
          END;'; 
try { 
    cstmt := conn.prepareCall(query); 
    cstmt.registerOutParameter(1, OracleTypes.CURSOR); 
    cstmt.execute(); 
    rset := (ResultSet) cstmt.getObject(1); 
} 
finally { 
    <<close cstmt & rset>> 
} 
相关问题