Вопрос по java – Где мой недопустимый персонаж (ORA-00911)

64

Я пытаюсь вставитьCLOBв базу данных (см.связанный вопрос). Я не могу понять, что не так. У меня есть список из 85 сгустков, которые я хочу вставить в таблицу. Даже при вставке только первого саба я получаюORA-00911: invalid character, Я не могу понять, как получить утверждение изPreparedStatement до того, как он запустится, я не могу быть на 100% уверен, что это правильно, но если я все понял правильно, то он должен выглядеть именно так:

insert all
  into domo_queries values ('select 
substr(to_char(max_data),1,4) as year,
substr(to_char(max_data),5,6) as month,
max_data
from dss_fin_user.acq_dashboard_src_load_success
where source = ''CHQ PeopleSoft FS''')
select * from dual;

В конечном итоге этоinsert all Заявление будет иметь многоinto's, поэтому я просто не делаю регулярныеinsert заявление. Я не вижу там недопустимого символа, не так ли? (О, и этот код вышеruns fine when I run it in my sql developer tool.) И я, если я удалю точку с запятой вPreparedStatementКидаетORA-00933: SQL command not properly ended ошибка.

В любом случае, вот мой код для выполнения запроса (и значения переменных для приведенного выше примера).

public ResultSet executeQuery(String connection, String query, QueryParameter... params) throws DataException, SQLException {
  // query at this point = "insert all
                          //into domo_queries values (?)
                          //select * from dual;"
  Connection conn = ConnectionPool.getInstance().get(connection);
  PreparedStatement pstmt = conn.prepareStatement(query);
  for (int i = 1; i <= params.length; i++) {
    QueryParameter param = params[i - 1];
    switch (param.getType()) { //The type in the example is QueryParameter.CLOB
      case QueryParameter.CLOB:
        Clob clob = CLOB.createTemporary(conn, false, oracle.sql.CLOB.DURATION_SESSION);
        clob.setString(i, "'" + param.getValue() + "'");
        //the value of param.getValue() at this point is:
        /*
         * select 
         * substr(to_char(max_data),1,4) as year,
         * substr(to_char(max_data),5,6) as month,
         * max_data
         * from dss_fin_user.acq_dashboard_src_load_success
         * where source = ''CHQ PeopleSoft FS''
         */
        pstmt.setClob(i, clob);
        break;
      case QueryParameter.STRING:
        pstmt.setString(i, "'" + param.getValue() + "'");
        break;
    }
  }
  ResultSet rs = pstmt.executeQuery(); //Obviously, this is where the error is thrown
  conn.commit();
  ConnectionPool.getInstance().release(conn);
  return rs;
}

Есть ли что-то, что я просто пропускаю?

Поддерживает ли ведение журнала запросов Oracle. Если так, то вы можете увидеть запрос, когда он попадет на сервер. Dan Armstrong
Некоторые драйверы JDBC позволяют toString () показывать вам запрос из PreparedStatement, а некоторые нет. Не уверен насчет Oracle. Dan Armstrong
Можете ли вы просмотреть PreparedStatement в виде строки, чтобы увидеть, что он содержит? Dan Armstrong
Я упоминал об этом в посте. Я не могу понять, как это сделать. Все, что я вижу в интернете, это то, что по какой-то причине это довольно сложно ... kentcdodds
@ DanArmstrong, к сожалению, здесь дело не в этом. Я получаю[email protected] наtoString() распечатка kentcdodds

Ваш Ответ

2   ответа
155

как вы нам показали, проблема заключается в; символ в конце. Вы не можете включить это в строку запроса в вызовах JDBC.

Как вы вставляете только одну строку, обычныйINSERT должно быть прекрасно даже при вставке нескольких строк. Использование пакетного оператора, вероятно, более эффективно в любом случае. Нет необходимости дляINSERT ALL. Кроме того, вам не нужен временный удар и все такое. Вы можете упростить свой метод до чего-то вроде этого (при условии, что я правильно понял параметры):

String query1 = "select substr(to_char(max_data),1,4) as year, " + 
  "substr(to_char(max_data),5,6) as month, max_data " +
  "from dss_fin_user.acq_dashboard_src_load_success " + 
  "where source = 'CHQ PeopleSoft FS'";

String query2 = ".....";

String sql = "insert into domo_queries (clob_column) values (?)";
PreparedStatement pstmt = con.prepareStatement(sql);
StringReader reader = new StringReader(query1);
pstmt.setCharacterStream(1, reader, query1.length());
pstmt.addBatch();

reader = new StringReader(query2);
pstmt.setCharacterStream(1, reader, query2.length());
pstmt.addBatch();

pstmt.executeBatch();   
con.commit();
@ ShannonSeverance: the; являетс определяется как символ завершения оператора по стандарту SQL. Но чтобы увеличить путаницу по этому поводу: SQL Server (не клиент!) Требует некоторые заявления должны быть отправлены с; в конце даже через JDBC. И, видимо, иногда это требу; в начале заявления. a_horse_with_no_name
Я пытался прояснить, что я обсуждаю реализацию SQL Oracle, а не стандартный SQL. SQL Server дурацкий иногда требует; для разделения утверждений, но не требуя; все это время Shannon Severance
Чтобы добавить, многие думают, что; - терминатор операторов в SQL в Oracle. Это не так.; в конце оператора используется клиентом (например, SQLPlus), чтобы сказать, где заканчивается оператор, а затем отправляет оператор, но не ';' на сервер Oracle. В SQLPLus, по умолчанию попробуйтеselect * from dual; --semicolon to terminate. Вы получите2 для остальной части команды, потому что SQL * Plus использует только; если это последний символ в строке, ноselect * from dual --weird that this works; The; является частью комментария, но все еще «завершает» утверждение. Shannon Severance
только что; убивал меня Sumon Bappi
Комментарий выше должен гласить: PL / SQL использует; как терминатор оператора, но это язык отдельный от реализации Oracle Oracle. Shannon Severance
6

q' для строкового литерала

что-то тип

insert all
  into domo_queries values (q'[select 
substr(to_char(max_data),1,4) as year,
substr(to_char(max_data),5,6) as month,
max_data
from dss_fin_user.acq_dashboard_src_load_success
where source = 'CHQ PeopleSoft FS']')
select * from dual;

Отметьте, что одинарные кавычки вашего предиката не экранированы, и строка находится между q '[...]'.

Отлично, я забыла оq'[]'. Спасибо за совет kentcdodds

Похожие вопросы