Oracle10 и JDBC:как заставить CHAR игнорировать конечные пробелы при сравнении?

StackOverflow https://stackoverflow.com/questions/603245

  •  03-07-2019
  •  | 
  •  

Вопрос

У меня есть запрос, который имеет

...ГДЕ PRT_STATUS='ONT' ...

Поле prt_status определено как CHAR(5).Поэтому он всегда дополняется пробелами.В результате запроса ничего не соответствует.Чтобы этот запрос работал, мне нужно сделать

...ГДЕ rtrim(PRT_STATUS)='ONT'

который работает.

Это раздражает.

В то же время у пары чисто-java-клиентов СУБД (Oracle SQLDeveloper и AquaStudio), которые у меня есть, НЕ возникает проблем с первым запросом, они возвращают правильный результат.У TOAD тоже нет проблем.

Я предполагаю, что они просто перевели соединение в какой-то режим совместимости (например.ANSI), поэтому Oracle знает, что CHAR(5) будет сравниваться без учета конечных символов.

Как я могу сделать это с объектами Connection, которые я получаю в своем приложении?

ОБНОВЛЯТЬ Я не могу изменить схему базы данных.

РЕШЕНИЕ Действительно, Oracle сравнивает поля с переданными параметрами.

Когда привязка завершена, строка передается через ReaderStatement.setString(), который устанавливает тип VARCHAR, и, таким образом, Oracle использует сравнение без дополнений - и терпит неудачу.

Я пытался использовать setObject(n,str,Types.CHAR).Не удалось.Декомпиляция показывает, что Oracle игнорирует CHAR и снова передает его как VARCHAR.

Вариант, который, наконец, работает:

setObject(n,str,OracleTypes.FIXED_CHAR);

Однако это делает код непереносимым.

Клиенты пользовательского интерфейса преуспевают по другой причине — они используют символьные литералы, а не привязку.Когда я набираю PRT_STATUS='ONT', 'ONT' является литералом и поэтому сравнивается с использованием дополненного способа.

Это было полезно?

Решение

Обратите внимание, что Oracle сравнивает CHAR значения с использованием семантики сравнения с заполнением пробелами.

От Правила сравнения типов данных,

Oracle использует семантику сравнения с пустыми планами только тогда, когда оба значения в сравнении являются либо выражениями DataType Char, Nchar, текстовых литералов или значений, возвращаемых пользовательской функцией.

В вашем примере это 'ONT' передается как параметр привязки или он встроен в запрос в текстовом виде, как вы проиллюстрировали?Если параметр привязки, убедитесь, что он привязан как тип CHAR.В противном случае проверьте используемую версию клиентской библиотеки, поскольку это действительно старые версии Oracle (например,v6) будет иметь другую семантику сравнения для CHAR.

Другие советы

Если вы не можете изменить таблицу базы данных, вы можете изменить свой запрос.

Некоторые альтернативы RTRIM:

..WHERE PRT_STATUS типа 'ONT%'...

..ГДЕ PRT_STATUS = 'ONT' ...-- 2 пробела позади буквы T

..WHERE PRT_STATUS = rpad('ONT',5,' ') ...

Я бы изменил столбец CHAR(5) на varchar2(5) в БД.

Вы можете использовать операцию приведения к символу в своем запросе:

... WHERE PRT_STATUS=cast('ONT' as char(5))

Или более общим способом JDBC:

... WHERE PRT_STATUS=cast(? as char(5))

И затем в вашем коде JDBC используйте statement.setString(1, "ONT");

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top