JDBC: возврат нескольких наборов результатов с помощью одного вызова базы данных - не работает для Oracle

В этом сообщении показано выполнение нескольких запросов в одном вызове JDBC (по отношению к SQL базы данных сервера), разделив их точкой с запятой. Когда я попытался сделать то же самое с Oracle 10G, возникла ошибка «недопустимый символ»:

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

Что я делаю не так ?


person Daud    schedule 14.12.2011    source источник


Ответы (2)


Вы не делаете ничего плохого (разве что считаете, что все СУБД работают одинаково)

Oracle (и его драйвер JDBC) просто не поддерживает это.

Вам нужно запускать каждый SELECT отдельно.

Кстати: это одна из причин, по которой некоторые атаки путем внедрения SQL-кода не работают с Orace, особенно знаменитый мультфильм "маленькие столы-бобби". .

person a_horse_with_no_name    schedule 14.12.2011
comment
Спасибо. Но есть ли способ, чтобы мне не нужно было делать 2 отдельных вызова БД? - person Daud; 14.12.2011
comment
Если два выбора возвращают одни и те же типы, вы можете использовать объединение. Но это настоящая ПЛОХАЯ практика - person A.B.Cade; 14.12.2011
comment
@Дауд: нет, тебе нужно два звонка. - person a_horse_with_no_name; 14.12.2011

За один вызов можно вернуть несколько наборов результатов из Oracle в JDBC. Есть несколько способов сделать это; хороший пост на Oracle-Base показывает, как .

Механизм, который я использую, состоит в том, чтобы создать анонимный блок в вызываемом операторе, а затем привязать SYS_REFCURSOR для каждого результирующего набора в качестве выходного параметра.

Вот некоторый код, который делает именно это. Он ленив для обработки ошибок, но он передает идею:

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

Я надеюсь, что это поможет вам!

person MikeB    schedule 06.12.2015