【问题标题】:PL/SQL call from JDBC resulting in "SQLSyntaxErrorException: ORA-00900"来自 JDBC 的 PL/SQL 调用导致“SQLSyntaxErrorException:ORA-00900”
【发布时间】:2011-09-07 00:51:25
【问题描述】:

我正在尝试使用以下代码在我的数据库服务器上运行 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.java:1010) 时间:-1307015416548

在 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:1374)
在 Main.prepareStatement(Main.java:58)
在 Main.main(Main.java:29)

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

【问题讨论】:

    标签: java sql jdbc plsql


    【解决方案1】:

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

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

    注意:

    为了收藏最多 统计,使用 DBMS_STATS 包,可让您收集 并行统计,收集全局 分区对象的统计信息, 并微调您的统计数据 以其他方式收集。见甲骨文 数据库 PL/SQL 包和类型 有关更多信息的参考 DBMS_STATS 包。使用分析 语句(而不是 DBMS_STATS) 不相关的统计收集 基于成本的优化器:

    • 使用 VALIDATE 或 LIST CHAINED ROWS 子句

    • 收集freelist上的信息 块

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

    【讨论】:

      【解决方案2】:

      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 的方法。

      【讨论】:

      • @Codo...你能告诉我我是否能得到上述查询的结果。像 ResultSet 什么的。
      • ANALYZE TABLE 不是查询。它没有结果。要么运行正常,要么失败。如果失败,会抛出异常。
      猜你喜欢
      • 2023-03-05
      • 1970-01-01
      • 2011-09-13
      • 1970-01-01
      • 1970-01-01
      • 2012-05-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多