2011-12-14 4 views
8

This post pokazał wykonywanie wielu zapytań w jednym wywołaniu JDBC (w stosunku do bazy danych SQL Server), oddzielając je średnikami. Kiedy próbowałem zrobić to samo z Oracle 10G, podniosłem błąd "nieprawidłowy znak":JDBC: zwracanie wielu zestawów wyników za pośrednictwem pojedynczego wywołania bazy danych - nie działa dla 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(); 
    } 
} 

Co robię źle?

Odpowiedz

7

Robisz nic złego (z wyjątkiem założyć, że wszystkie DBMS działają tak samo)

Oracle (i jego sterownik JDBC) po prostu nie obsługuje tej funkcji.

Musisz uruchomić każde SELECT indywidualnie.

Przy okazji: jest to jeden z powodów, dla których niektóre ataki polegające na wstrzyknięciu SQL nie działają z Orace - szczególnie słynna "little bobby tables".

+0

Dzięki. Ale czy jest jakiś sposób, żebym nie musiał wykonywać dwóch oddzielnych wywołań db? – Daud

+1

Jeśli dwa zaznaczenia zwracają te same typy, można użyć zrostu. Ale jest to prawdziwa Zła praktyka –

+1

@Daud: nie, potrzebujesz dwóch połączeń. –

1

Możliwe jest odzyskanie wielu zestawów wyników z Oracle do JDBC w jednym wywołaniu. Można to zrobić na kilka sposobów; a good post at Oracle-Base shows how.

Mechanizm, którego używam, polega na utworzeniu anonimowego bloku w instrukcji wywoływalnej, a następnie powiązaniu SYS_REFCURSOR dla każdego zestawu wyników jako parametru wyjściowego.

Oto kod, który właśnie to robi. Jest leniwy, jeśli chodzi o obsługę błędów, ale wpada na pomysł:

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

Mam nadzieję, że wam pomogę!