Статьи

Слишком много заполнителей PreparedStatement в Oracle JDBC

Существует несколько причин ошибки ORA-01745 («недопустимая ошибка имени переменной хоста / связывания») при использовании базы данных Oracle. Документация Oracle 9i об ошибках ORA-01500 — ORA-02098 содержит более подробную информацию о ORA-01745 . В нем говорится, что «причина» — это «двоеточие в переменной связывания или спецификация INTO, за которым следует неуместное имя, возможно, зарезервированное слово». В нем также говорится, что «Действие» означает «Изменить имя переменной и повторить операцию». В той же документации Oracle 12g , однако, нет описания «причины» или «действия» для ORA-01745, предположительно, потому что есть несколько причин и множество соответствующих действий, связанных с этим сообщением. В этом посте я остановлюсь на одной из, возможно, менее очевидных причин и соответствующих действий для этой причины.

Некоторые из распространенных причин для ORA-01745, на которых я НЕ буду фокусироваться в этом посте, включают использование зарезервированного имени базы данных Oracle ( зарезервированное слово ) в качестве идентификатора , посторонние или отсутствующие двоеточие или запятую , или попытки связать имена структур (а не переменные) для заполнителей .

В дополнение к только что перечисленным и вероятным в дополнение к другим потенциальным причинам ORA-01745, другая ситуация, которая может вызвать ошибку ORA-01745, использует слишком много ? заполнители в JDBC PreparedStatement с базой данных Oracle. Я продемонстрирую в этом посте, что число ? заполнители в PreparedStatement, которые вызывают это ORA-01745, являются 65536 ( 2 16 )

Ранее я писал в блоге об ошибке ORA-01795, которая возникает при попытке включить более 1000 значений в условие Oracle SQL IN . Существует несколько способов справиться с этим ограничением, и один из альтернативных подходов может заключаться в использовании нескольких OR для « OR » вместе более 1000 значений. Как правило, это будет реализовано с PreparedStatement и с ? заполнитель помещается в оператор SQL для каждого значения, которое OR . Этот PreparedStatement основе альтернативного подхода с использованием ? заполнители будут работать только до тех пор, пока количество объединяемых OR будет превышать 65536.

В приведенном ниже листинге кода показано, как можно сгенерировать SQL-запрос к схеме Oracle HR, чтобы упростить воспроизведение ошибки ORA-01745 при слишком большом количестве ошибок ? заполнители (полный список кодов доступен на GitHub ).

Создание подготовленного заявления с указанным количеством ? Заполнители

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
/**
 * Constructs a query using '?' for placeholders and using
 * as many of these as specified with the int parameter.
 *
 * @param numberPlaceholders Number of placeholders ('?')
 *    to include in WHERE clause of constructed query.
 * @return SQL Query that has provided number of '?" placeholders.
 */
private String buildQuery(final int numberPlaceholders)
{
   final StringBuilder builder = new StringBuilder();
   builder.append("SELECT region_id FROM countries WHERE ");
   for (int count=0; count < numberPlaceholders-1; count++)
   {
      builder.append("region_id = ? OR ");
   }
   builder.append("region_id = ?");
   return builder.toString();
}

Следующий листинг кода демонстрирует построение PreparedStatement на основе запроса, созданного в последнем листинге кода, и установку его заполнителей с количеством последовательных целых чисел, которые соответствуют числу ? заполнители.

Конфигурирование PreparedStatement ‘s ? Заполнители

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
 * Execute the provided query and populate a PreparedStatement
 * wrapping this query with the number of integers provided
 * as the second method argument.
 *
 * @param query Query to be executed.
 * @param numberValues Number of placeholders to be set in the
 *    instance of {@code PreparedStatement} used to execute the
 *    provided query.
 */
private void executeQuery(final String query, final int numberValues)
{
   try (final Connection connection = getDatabaseConnection();
        final PreparedStatement statement = connection.prepareStatement(query))
   {
      for (int count = 0; count < numberValues; count++)
      {
         statement.setInt(count+1, count+1);
      }
      final ResultSet rs = statement.executeQuery();
      while (rs.next())
      {
         out.println("Region ID: " + rs.getLong(1));
      }
   }
   catch (SQLException sqlException)
   {
      out.println("ERROR: Unable to execute query - " + sqlException);
   }
}

Следующий снимок экрана показывает ошибку ORA-01745, возникающую, когда число ? применяется заполнителей 65536.

Этот пример показывает, что существует максимальное количество ? заполнители, которые можно использовать в операторе Oracle SQL. К счастью, есть другие способы реализации этого типа функций, которые не имеют ограничения ORA-01475 65536 ? заполнители или предел 1000 IN элементов, который вызывает ошибку ORA-01795

Опубликовано на Java Code Geeks с разрешения Дастина Маркса, партнера нашей программы JCG . См. Оригинальную статью здесь: Слишком много заполнителей PreparedStatement в Oracle JDBC

Мнения, высказанные участниками Java Code Geeks, являются их собственными.