Вызов JDBC хранимой процедуры Oracle с именованными параметрами завершается с ошибкой «Найден символ ›»

Я получил этот код хранимой процедуры Oracle, вызывающий другую хранимую процедуру:

PROCEDURE xyz_main (
  i_param_a IN VARCHAR2 DEFAULT 'Y',
  i_param_b IN PERSON.NAME%TYPE
  i_param_c IN VARCHAR2 DEFAULT 'BLA'
  o_return_msg OUT VARCHAR2
)
IS
  ...
BEGIN
  ...
END xyz_main;

PROCEDURE xyz_example (
  i_param_b IN PERSON.NAME%TYPE DEFAULT 'Ben'
  o_return_msg OUT VARCHAR2
)
IS
BEGIN
  xyz_main(
    i_param_b => i_param_b,
    i_param_c => 'Great',
    o_return_msg => o_return_msg
  );
END xyz_example;

Теперь моя задача вызвать xyz_main с помощью Java. Я написал этот код:

// Using question mark because later on the values will be provided by function parameters
// Question: is "o_return_msg => ?" correct, even if I don't provide an input value?
String statement = "BEGIN xyz_main(i_param_b => ?, i_param_c => ?, o_return_msg => ?); END;";  

try (Connection conn = getOraConnection();) {
  CallableStatement cs = conn.prepareCall(statement);

  // cs.setString("i_param_a", "Y"); -- omitted because the default value should be used always
  cs.setString("i_param_b", "Ben");
  cs.setString("i_param_c", "Great"); // should overwrite the default value
  cs.registerOutParameter("o_return_msg", Types.VARCHAR);

  cs.execute();
} catch (Exception e) {
  ...
}

Запустив код, я получаю это исключение:

ORA-06550: line 1, column 47:
PLS-00103: Fand das Symbol ">" als eines der folgenden erwartet wurde: .. 

На английском:

PLS-00103: Found Symbol ">" but expected one of this: ..

Что не так с этим кодом?


person Rainer    schedule 07.05.2020    source источник
comment
BEGIN xyz_main(?, ?); END работает?   -  person wolφi    schedule 08.05.2020
comment
Так посоветовал мой коллега. Я пробовал, например. {CALL xyz_main(‹params›)} .. та же ошибка.   -  person Rainer    schedule 08.05.2020
comment
Возможно, ваш вопрос был о том, работает ли он с индексированными параметрами.. да, это работает. Но тогда я не могу опустить параметры.   -  person Rainer    schedule 08.05.2020
comment
это отвечает на ваш вопрос? Кажется, он использует имена для prepareCall, но индексирует для установки значений. Кристоф тоже.   -  person wolφi    schedule 08.05.2020


Ответы (1)


Я предполагал, что при использовании именованных параметров мне всегда нужно использовать синтаксис «par_name =>?». Это была ошибка.

Не проблема написать такой код:

//* don't work:
// String statement = "BEGIN xyz_main(i_param_b => ?, i_param_c => ?, o_return_msg => ?); END;";  // don't work
//* works:
String statement = "BEGIN xyz_main(?, ?, ?); END;"; 

try (Connection conn = getOraConnection();) {
  CallableStatement cs = conn.prepareCall(statement);
  // cs.setString("i_param_a", "Y"); -- omitted because the default value should be used always
  cs.setString("i_param_b", "Ben");
  cs.setString("i_param_c", "Great"); // should overwrite the default value
  cs.registerOutParameter("o_return_msg", Types.VARCHAR);
  cs.execute();
  System.out.println(cs.getString("o_return_msg"));
  cs.close();
} catch (Exception e) {
  ...
}
person Rainer    schedule 08.05.2020
comment
Спасибо! Это действительно очень запутанно. Итак, у вас есть имена либо в prepareCall, либо в setString, но не в обоих? - person wolφi; 08.05.2020
comment
Мне так кажется. В некоторых блогах я нашел примеры с другими параметрами, но пока не исследовал, старые ли эти примеры, или для других баз данных, или что-то еще. Самый важный факт: это работает :) Я добавил строку I в свой ответ, чтобы сделать его более понятным, если у кого-то еще возникнет такая же проблема. - person Rainer; 08.05.2020
comment
Очень хорошо. Кстати, вы можете принять свой собственный ответ, чтобы показать его другим пользователям. что это хорошее решение вопроса. - person wolφi; 08.05.2020