Вызов PL / SQL из JDBC, приводящий к «SQLSyntaxErrorException: ORA-00900» - PullRequest
0 голосов
/ 02 июня 2011

Я пытаюсь использовать следующий код для запуска инструкции 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)
в oracle.jdbc.driver.OraclePreparedStatement.executeInternal (OraclePreparedStatement.java:3576)
в oracle.jdbc.driver.OraclePreparedStatement.execute (OraclePreparedStatement.java:3677)
в oracle.jdbc.driver.OraclePreparedStatementWrapper.execute (OraclePreparedStatementWrapper.java:1374)
at Main.prepareStatement (Main.java:58)
в Main.main (Main.java:29)

Что не так, и как я могу это исправить?

Ответы [ 2 ]

4 голосов
/ 02 июня 2011

ANALYZE TABLE является оператором DDL (язык определения данных). Это недопустимо в блоке BEGIN / END в PL / SQL. Если вы хотите выполнить его в 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 голос
/ 02 июня 2011

Используйте CallableStatement вместо PreparedStatement - для выполнения операторов с синтаксисом блока PL / SQL из JDBC .

Однако, как сказал Кодо в другом ответе, ANALYZE TABLE не совсем вызывается из PL / SQL. Это команда SQL и, следовательно, не может быть выполнена в блоке PL / SQL. И, как правильно сказано, DBMS_STATS следует использовать. Это также указано в документации команды ANALYZE:

Примечание:

Для сбора наиболее статистика, используйте DBMS_STATS пакет, который позволяет собирать параллельно собираем статистику статистика для разделенных объектов, и точно настроить вашу статистику Сбор другими способами. Смотри Oracle База данных PL / SQL-пакеты и типы Ссылка для получения дополнительной информации о Пакет DBMS_STATS. Используйте АНАЛИЗ заявление (а не DBMS_STATS) для Сбор статистики, не связанный с Оптимизатор на основе затрат:

  • Для использования VALIDATE или LIST CHAINED ROWS пункты

  • Для сбора информации на freelist блоки

Если вы действительно хотите избежать использования DBMS_STATS (и, честно говоря, я не вижу веской причины избегать этого), используйте EXECUTE IMMEDIATE или DBMS_SQL для выполнения команды ANALYZE TABLE.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...