2011-12-14 8 views
8

This post ha mostrato l'esecuzione di più query in una singola chiamata JDBC (contro un database SQL Server) separandole con il punto e virgola. Quando ho provato a fare lo stesso con Oracle 10G, un errore di "carattere non valido" appoggiato:JDBC: restituire più set di risultati tramite un'unica chiamata al database - non funzionante per 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(); 
    } 
} 

Che cosa sto facendo di sbagliato?

risposta

7

Si sta facendo nulla di male (salvo supporre che tutti i DBMS funzionano allo stesso modo)

Oracle (e il suo driver JDBC) semplicemente non supporta questa.

È necessario eseguire ciascuna SELECT singolarmente.

Btw: questo è uno dei motivi per cui alcuni attacchi di SQL injection non funzionano con Orace, in particolare il famoso cartone animato "little bobby tables".

+0

Grazie. Ma esiste un modo tale per cui non devo effettuare 2 chiamate db separate? – Daud

+1

Se i due selezionati restituiscono gli stessi tipi, è possibile utilizzare l'unione. Ma è una pratica BAD reale –

+1

@Daud: no, hai bisogno di due chiamate. –

1

È possibile ottenere più serie di risultati da Oracle a JDBC in una singola chiamata. Ci sono alcuni modi per farlo; a good post at Oracle-Base shows how.

Il meccanismo che utilizzo è creare un blocco anonimo in un'istruzione callable, quindi associare un SYS_REFCURSOR per ogni set di risultati come parametro di output.

Ecco po 'di codice che fa proprio questo. E 'pigro per la gestione degli errori, ma ottiene l'idea attraverso:

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

Spero che ti aiuta!

Problemi correlati