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,'')...
вы можете использовать операцию cast to char в своем запросе:
... WHERE PRT_STATUS=cast('ONT' as char(5))
или более общим способом JDBC:
... WHERE PRT_STATUS=cast(? as char(5))
и затем в вашем коде JDBC используйте statement.setString(1, "ONT");