8

这篇文章展示了在单个 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();
    }
}

我究竟做错了什么 ?

4

2 回答 2

7

您没有做错任何事情(除非假设所有 DBMS 工作方式相同)

Oracle(及其 JDBC 驱动程序)根本不支持这一点。

您需要单独运行每个 SELECT。

顺便说一句:这是某些 SQL 注入攻击不适用于 Orace 的原因之一——尤其是著名的“小鲍比桌”卡通片。

于 2011-12-14T11:59:51.723 回答
2

可以在一次调用中将多个结果集从 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();
}

我希望这可以帮助你!

于 2015-12-06T18:35:19.573 回答