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

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

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

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

... Где rtrim (PRT_STATUS)='ONT'

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

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

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

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

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

обновление я не могу измените схему базы данных.

решение именно так Oracle сравнивает поля с переданными параметрами.

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

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

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

setObject(n,str,OracleTypes.FIXED_CHAR);

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

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

4 ответов


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

С Правила Сравнения Типов Данных,

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

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


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

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

.. Где PRT_STATUS нравится " ONT%"...

.. ГДЕ PRT_STATUS = 'ONT'... -- 2 белых пятна позади T

.. Где PRT_STATUS = rpad ('ONT', 5,'')...


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


вы можете использовать операцию cast to char в своем запросе:

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

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

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

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