来自JDBC的PL / SQL调用导致“SQLSyntaxErrorException:ORA-00900”

时间:2011-06-02 11:54:39

标签: java sql jdbc plsql

我正在尝试使用以下代码在我的数据库服务器上运行PL / SQL语句。

public class Main {
    public static void main(String[] args) {
        String jdbcURL = "jdbc:oracle:thin:@172.22.88.9:1521/xavier.i.com";

        Connection conn = null;
        Statement stmt = null;
        ResultSet rs = null;

        String user = "bigdb";
        String password = "fakepassword";
        String result = null;
        try {
            Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
            conn = DriverManager.getConnection(jdbcURL, user, password);

            result = runStatement(conn,
              "{begin ANALYZE TABLE BIGDB.scr_fct_exact_access
              ESTIMATE STATISTICS; end}");

        } catch (Exception ex) {
            System.out.println(ex.getMessage());
            ex.printStackTrace();
        }
    }

    private static String runStatement(Connection con, String statement)
      throws Exception {
        PreparedStatement cstmt = con.prepareStatement(statement);
        cstmt.execute(); // this is line 58
        cstmt.close();

        return count;
    }
}

在运行代码时,我得到以下异常:

  

java.sql.SQLSyntaxErrorException:ORA-00900:无效的SQL语句

     

at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:440)
          在oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396)
          在oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:837)
          在oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:445)
          在oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:191)
          在oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:523)
          在oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:207)
          at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1010)时间:-1307015416548

     

at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1315)
          at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3576)
          at oracle.jdbc.driver.OraclePreparedStatement.execute(OraclePreparedStatement.java:3677)
          在oracle.jdbc.driver.OraclePreparedStatementWrapper.execute(OraclePreparedStatementWrapper.java:1374)
          在Main.prepareStatement(Main.java:58)
          在Main.main(Main.java:29)

出了什么问题,我该如何解决?

2 个答案:

答案 0 :(得分:4)

ANALYZE TABLE是一种DDL(数据定义语言)语句。它在PL / SQL的BEGIN / END块中无效。如果你想在PL / SQL中执行它,你需要使用EXECUTE IMMEDIATE。

要从JDBC运行语句,只需创建一个Statement实例并使用executeUpdate

Statement stmt = con.createStatement();
stmt.executeUpdate("ANALYZE TABLE BIGDB.scr_fct_exact_access ESTIMATE STATISTICS");
stmt.close();

但更好的想法是使用DBMS_STATS包来分析您的表。然后你可以使用BEGIN / END的方法。

答案 1 :(得分:1)

使用CallableStatement代替PreparedStatement run statements with the PL/SQL block syntax from JDBC

但是,正如Codo在另一个答案中所述,ANALYZE TABLE并不能完全从PL / SQL中调用。它是一个SQL命令,因此无法在PL / SQL块中执行。正如所建议的那样,DBMS_STATS应该被使用。这也在ANALYZE命令的文档中说明:

  

注意:

     

收集最多   统计信息,使用DBMS_STATS   包,让你收集   并行统计,收集全球   分区对象的统计信息,   并微调您的统计数据   以其他方式收集。见Oracle   数据库PL / SQL包和类型   有关更多信息的参考   DBMS_STATS包。使用ANALYZE   声明(而不是DBMS_STATS)   与...无关的统计数据收集   基于成本的优化器:

     
      
  • 使用VALIDATE或LIST CHAINED   ROWS条款

  •   
  • 收集freelist的信息   块

  •   

如果你真的想避免使用DBMS_STATS(老实说,我认为没有理由避免使用它),请使用EXECUTE IMMEDIATEDBMS_SQL执行{{1}命令。