SQL «отсутствует входной или выходной параметр в индексе»

#java #sql #database #oracle

#java #sql #База данных #Oracle

Вопрос:

у меня есть этот код для создания запроса и выполнения sql-процедуры, но я улавливаю пропущенное исключение

 public String generateQuery(Integer idAccount, Long[] phoneList, Date date){
    StringBuilder query=new StringBuilder();
    query.append("declare arr_pn owa_util.vc_arr;n");
    query.append("beginn");
    int idx = 1;
    for (Long p : phoneList)
    { query.append("arr_pn("   idx   "):='"   String.valueOf(p)   "';n"); idx  ; }
    query.append("call LOC_MAINCLIENT.set_client_relations(");
    query.append("id_account_ => "   idAccount);
    query.append(", phone_number_list_ => arr_pn");
    query.append(", dt_ => "   date);
    query.append("); end;");

    return String.valueOf(query);
}
  

после этого я получаю этот запрос

 declare arr_pn owa_util.vc_arr;
begin
arr_pn(1):='12345';
arr_pn(2):='678970';
arr_pn(3):='5675675';
call LOC_MAINCLIENT.set_client_relations(id_account_ => 123, phone_number_list_ => arr_pn, dt_ => Sun Mar 24 21:54:00 NOVT 2013); end;
  

что я сделал не так?

Комментарии:

1. Как определяется процедура — в частности, ее подпись, если исключение не вызывается из нее?

2. Строка даты, передаваемая в dt_, заключена в одинарные кавычки.

3. @vishad я глупый. пожалуйста, покажите мне, как

4. Какая-либо конкретная причина, по которой вызовы или методы API JDBC не используются?

5. устаревший код. я должен использовать это = (

Ответ №1:

На данный момент строка даты не заключена в кавычки, поэтому она в любом случае действительна, но двоеточия будут интерпретироваться синтаксическим анализатором как маркеры переменных привязки; в частности, он будет искать переменные привязки: 54 и :00.

Быстрый ответ — заключить строку даты в кавычки. Но этот формат даты вряд ли соответствует тому, что ожидает ваша база данных (сеанс), поэтому вам нужно будет отформатировать дату в строку, которую она может использовать, и предоставить формат, чтобы избежать двусмысленности.

     SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    query.append(", dt_ => to_date('"   sdf.format(date)
          "', 'YYYY-MM-DD HH24:MI:SS')");
  

Вам также не нужно call , так что избавьтесь от этого. Это привело бы к появлению строки, подобной этой (с добавлением разрывов строк и отступов, чтобы ее было немного легче увидеть):

 declare
  arr_pn owa_util.vc_arr;
begin
  arr_pn(1):='12345';
  arr_pn(2):='678970';
  arr_pn(3):='5675675';
  LOC_MAINCLIENT.set_client_relations(id_account_ => 123,
    phone_number_list_ => arr_pn,
    dt_ => to_date('2013-03-24 21:54:00', 'YYYY-MM-DD HH24:MI:SS'));
end;
  

Предполагая, что ваша процедура пакета объявлена как:

 procedure set_client_relations(id_account_ number,
    phone_number_list_ owa_util.vc_arr, dt_ date);
  

… это должно выполняться. Конечно, делает ли это то, что вы на самом деле хотите, это другой вопрос.

Вам также может потребоваться что-то сделать с часовым поясом, если база данных не соответствует вашему языку.

Правильный способ сделать это — использовать подготовленный оператор, предоставить все значения в качестве переменных привязки и передать правильные типы данных — передавая дату как дату, а не как строковое представление. Это немного сложнее для массива, но, безусловно, выполнимо. Вы сказали, что это устаревший код, и вы должны использовать это, но вам все равно следует изучить переключение на переменные привязки.