web-dev-qa-db-fra.com

Exécutez le bloc anonyme pl / sql et obtenez l'ensemble de résultats dans java

Je voudrais exécuter le PL/SQL anonyme et j'ai besoin d'obtenir l'objet de l'ensemble de résultats. J'ai obtenu le code qui peut être fait en utilisant des curseurs à l'intérieur du bloc PL/SQL.

Mais le bloc PL/SQL lui-même proviendra de la base de données sous forme de texte. Je ne peux donc pas modifier ce bloc PL/SQL. Et il ne renverra que deux valeurs dont les noms de colonnes seront toujours les mêmes. Il renverra la liste des valeurs de combinaison de 2 colonnes.

Ici, je donne un exemple 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;

Toute réponse sera si utile.

23
Raju

Voici un exemple autonome de la façon "d'exécuter le PL/SQL anonyme et d'obtenir l'objet d'ensemble de résultats"

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

L'exemple de requête ci-dessus "sélectionnez 1 id, nom" bonjour "de la double union sélectionnez 2," peter "de la double;" peut être remplacé par n'importe quelle requête.

43
Noctiluque

Essayez quelque chose comme ça (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;

Le REF CURSOR qui est retourné peut être traité comme un jeu de données normal.

Et méfiez-vous de l'injection SQL lorsque vous utilisez une approche comme celle-ci ...

3
ObiWanKenobi

Tout d'abord, le code que vous avez publié n'est pas valide. Un bloc PL/SQL anonyme ne peut pas renvoyer une expression. Et aucun bloc PL/SQL ne peut retourner le résultat d'une requête comme ça. Vous devez faire quelque chose comme déclarer un REF CURSOR et ouvrir ce curseur à l'aide des différentes instructions SQL.

Puisqu'un bloc PL/SQL anonyme ne peut rien renvoyer à un appelant, l'architecture que vous décrivez est problématique. Au minimum, vous devez modifier le bloc anonyme afin qu'il y ait une variable de liaison que votre code JDBC puisse enregistrer. Quelque chose comme (adapté d'un exemple dans Menon's Expert Oracle JDBC Programming (notez que j'ai peut-être introduit quelques erreurs de syntaxe mineures)

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>>
}
3
Justin Cave