2011-12-14 6 views
8

This publicación mostró la ejecución de múltiples consultas en una sola invocación JDBC (en una base de datos SQL Server) separándolas con punto y coma. Cuando traté de hacer lo mismo con Oracle 10G, un error de "carácter no válido" apuntalado:JDBC: devolver varios conjuntos de resultados mediante una única invocación de base de datos: no funciona para Oracle

class db 
{ 
    public static void main(String aa[])throws Exception 
    { 
     Class.forName("oracle.jdbc.driver.OracleDriver"); 
     Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@//192.168.10.29:1521/ttt","username","password"); 
     PreparedStatement stat = conn.prepareStatement("select voila from app where rownum<4; select code from process where rownum<4"); 
     stat.execute(); 
     while (stat.getMoreResults()){ 
      ResultSet rs = stat.getResultSet(); 
      while (rs.next()){ 
       System.out.println(rs.getString(1));   
      } 
     } 
     conn.close(); 
    } 
} 

¿Qué estoy haciendo mal?

Respuesta

7

Usted está haciendo nada malo (excepto suponer que todos los DBMS funcionan de la misma)

Oracle (y su controlador JDBC) simplemente no soporta esto.

Debe ejecutar cada SELECCIÓN individualmente.

Por cierto: este es uno de los motivos por los que algunos ataques de inyección SQL no funcionan con Orace, especialmente la famosa caricatura "little bobby tables".

+0

Gracias. Pero, ¿hay alguna forma de que no tenga que hacer 2 llamadas a db por separado? – Daud

+1

Si los dos selectores devuelven los mismos tipos, puede usar union. Pero es una verdadera práctica MALO –

+1

@Daud: no, necesitas dos llamadas. –

1

Es posible obtener múltiples conjuntos de resultados de Oracle en JDBC en una sola llamada. Hay algunas maneras de hacerlo; a good post at Oracle-Base shows how.

El mecanismo que uso es hacer un bloque anónimo en una instrucción invocable, luego enlazar un SYS_REFCURSOR para cada conjunto de resultados como un parámetro de salida.

Aquí hay un código que hace precisamente eso. Es perezoso para el tratamiento de errores, pero tiene la idea a través de:

public void getMultiple() throws Exception { 

    // get connection 
    Connection conn = DriverManager.getConnection(TestConfig.JDBC_URL, TestConfig.DB_USERNAME, TestConfig.DB_PASSWORD); 

    // here's the statement; it uses an anonymous block. In that block, 
    // we've declared two SYS_REFCURSOR objects which are opened over our 
    // SELECT statements. Once the statements are opened, we bind the 
    // SYS_REFCURSOR objects so they can be retrieved from JDBC 
    String s = 
      "DECLARE" + 
      " l_rs1 SYS_REFCURSOR; " + 
      " l_rs2 SYS_REFCURSOR; " + 
      "BEGIN "+ 
      " OPEN l_rs1 FOR " + 
      "  SELECT 'Moose' FROM DUAL;" + 
      " OPEN l_rs2 FOR " + 
      "  SELECT 'Squirrel' FROM DUAL; " + 
      " ? := l_rs1;" + 
      " ? := l_rs2;" + 
      "END;"; 

    // prepare the callable statement, registering 
    // the output parameter we want 
    CallableStatement cs = conn.prepareCall(s); 
    cs.registerOutParameter(1, OracleTypes.CURSOR); 
    cs.registerOutParameter(2, OracleTypes.CURSOR); 

    // execute the callable statement 
    cs.execute(); 

    // retrieve the result sets by getting the bound output objects and 
    // casting them to Java ResultSet objects 
    ResultSet rs1 = (ResultSet) cs.getObject(1); 
    ResultSet rs2 = (ResultSet) cs.getObject(2); 

    // advance the first result set and print the string it yields 
    rs1.next(); 
    System.out.printf("Result set 1 has '%s'\n", rs1.getString(1)); 

    // advance the second result set and print the string it yields 
    rs2.next(); 
    System.out.printf("Result set 2 has '%s'\n", rs2.getString(1)); 

    // close everything up 
    rs2.close(); 
    rs1.close(); 
    cs.close(); 
    conn.close(); 
} 

espero que le ayuda a cabo!

Cuestiones relacionadas