繁体   English   中英

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

[英]PL/SQL call from JDBC resulting in “SQLSyntaxErrorException: ORA-00900”

我正在尝试使用以下代码在我的数据库服务器上运行 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 语句

在 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)
在 oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.Z93F725A07423FE1C889F448B413D541F436Z010)-

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

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

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 package 来分析您的表。 然后,您可以将您的方法与 BEGIN/END 一起使用。

使用CallableStatement而不是PreparedStatement运行具有 JDBC 中的 PL/SQL 块语法的语句

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

笔记:

对于大多数统计信息的收集,请使用 DBMS_STATS package,它允许您并行收集统计信息,收集分区对象的全局统计信息,并以其他方式微调您的统计信息收集。 有关 DBMS_STATS package 的详细信息,请参阅 Oracle 数据库 PL/SQL 包和类型参考。 使用 ANALYZE 语句(而不是 DBMS_STATS)进行与基于成本的优化器无关的统计信息收集:

  • 使用 VALIDATE 或 LIST CHAINED ROWS 子句

  • 收集有关 freelist 块的信息

如果您真的想避免使用DBMS_STATS (老实说,我认为没有充分的理由避免使用它),请使用EXECUTE IMMEDIATEDBMS_SQL来执行ANALYZE TABLE命令。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM