Oracle10 и JDBC: как заставить CHAR игнорировать конечные пробелы при сравнении? - PullRequest
7 голосов
/ 02 марта 2009

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

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

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

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

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

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

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

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

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

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

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

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

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

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

setObject(n,str,OracleTypes.FIXED_CHAR);

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

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

Ответы [ 4 ]

8 голосов
/ 02 марта 2009

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

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

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

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

1 голос
/ 02 марта 2009

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

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

.. ГДЕ PRT_STATUS, как 'ONT%' ...

.. WHERE PRT_STATUS = 'ONT' ... - 2 пробела позади T

.. ГДЕ PRT_STATUS = rpad ('ONT', 5, '') ...

0 голосов
/ 24 ноября 2017

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

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

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

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

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

0 голосов
/ 02 марта 2009

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

...