Execute anonymous pl/sql block and get resultset in java

前端 未结 3 1019
-上瘾入骨i
-上瘾入骨i 2020-11-28 09:15

I would like to execute the anonymous PL/SQL and need to get the resultset object. I got the code which can be done by using cursors inside the PL/SQL block.

But the

相关标签:
3条回答
  • 2020-11-28 09:47

    Here is a self contained example of how to "execute the anonymous PL/SQL and get the resultset object"

    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();
        }
    }
    

    The above example query "select 1 id, 'hello' name from dual union select 2, 'peter' from dual;" can be replaced by any query.

    0 讨论(0)
  • 2020-11-28 09:48

    Try something like this (pseudo-code):

    [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;
    

    The REF CURSOR which is returned can be processed like a normal dataset.

    And beware of SQL injection when you use an approach like this...

    0 讨论(0)
  • 2020-11-28 09:52

    First off, the code you posted is not valid. An anonymous PL/SQL block cannot return an expression. And no PL/SQL block can return the result of a query like that. You would need to do something like declaring a REF CURSOR and opening that cursor using the various SQL statements.

    Since an anonymous PL/SQL block cannot return anything to a caller, the architecture you're describing is a problematic. At a minimum, you'd need to modify the anonymous block so that there was a bind variable that your JDBC code could register. Something like (adapted from an example in Menon's Expert Oracle JDBC Programming (note that I may have introduced some minor syntax errors)

    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>>
    }
    
    0 讨论(0)
提交回复
热议问题