8

この投稿では、複数のクエリをセミコロンで区切ることにより、(SQL Server データベースに対して) 1 回の JDBC 呼び出しで複数のクエリを実行する方法を示しました。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 で機能しない理由の 1 つです

于 2011-12-14T11:59:51.723 に答える
2

1 回の呼び出しで複数の結果セットを Oracle から JDBC に戻すことができます。いくつかの方法があります。Oracle-Baseの良い投稿では、その方法が示されています。

私が使用するメカニズムは、呼び出し可能なステートメントで匿名ブロックを作成しSYS_REFCURSOR、出力パラメーターとして for each 結果セットをバインドすることです。

これを行うコードを次に示します。エラー処理が面倒ですが、アイデアは次のように理解できます。

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 に答える