JDBC:通过单个数据库调用返回多个结果集 - 不适用于Oracle

时间:2011-12-14 11:53:52

标签: java oracle jdbc multiple-resultsets

This post显示在单个JDBC调用(针对SQL Server数据库)中执行多个查询,方法是用分号分隔它们。当我尝试对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();
    }
}

我做错了什么?

2 个答案:

答案 0 :(得分:7)

你没有做错任何事(除了假设所有DBMS都一样)

Oracle(及其JDBC驱动程序)根本不支持此功能。

您需要单独运行每个SELECT。

Btw:这是一些SQL注入攻击无法与Orace一起工作的原因之一 - 尤其是着名的“little bobby tables”漫画。

答案 1 :(得分:1)

可以在一次调用中将多个结果集从Oracle返回到JDBC。有几种方法可以做到;一个good post at Oracle-Base shows how

我使用的机制是在可调用语句中创建一个匿名块,然后将每个结果集的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();
}

我希望能帮到你!