我正在尝试使用以下代码在我的数据库服务器上运行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)时间:-1307015416548at 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)
出了什么问题,我该如何解决?
答案 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 IMMEDIATE
或DBMS_SQL
执行{{1}命令。