Типы данных Oracle JDBC и Oracle CHAR

У меня есть сложная проблема с обработкой драйверов Oracle JDBC для типов данных CHAR . Возьмем эту простую таблицу:

 create table x (c char(4)); insert into x (c) values ('a'); -- inserts 'a ' 

Поэтому, когда я вставляю что-то в CHAR(4) , строка всегда заполняется пробелами. Это также выполняется, когда я выполняю запросы следующим образом:

 select * from x where c = 'a'; -- selects 1 record select * from x where c = 'a '; -- selects 1 record select * from x where c = 'a '; -- selects 1 record 

Здесь константа 'a' заполняется пробелами. Вот почему запись всегда возвращается. Это выполняется, когда эти запросы выполняются с использованием JDBC PreparedStatement . Теперь сложнее всего, когда я хочу использовать переменную bind:

 PreparedStatement stmt = conn.prepareStatement("select * from x where c = ?"); stmt.setString(1, "a"); // This won't return any records stmt.setString(1, "a "); // This will return a record stmt.executeQuery(); 

Это обходное решение:

 PreparedStatement stmt = conn.prepareStatement("select * from x where trim(c) = trim(?)"); stmt.setString(1, "a"); // This will return a record stmt.setString(1, "a "); // This will return a record stmt.executeQuery(); 

EDIT : Теперь это ограничения:

  • Вышеупомянутое обходное решение нежелательно, так как оно изменяет как содержимое c и ? , И это делает использование индексов на c довольно сложно.
  • Перемещение столбца из CHAR в VARCHAR (что должно быть, конечно) невозможно

EDIT : Причины этих ограничений связаны с тем, что я задаю этот вопрос с точки зрения разработчика jOOQ , библиотеки абстракции базы данных. Поэтому мои требования – предоставить очень общее решение, которое не нарушает ничего в клиентском коде jOOQ. Вот почему я не очень большой поклонник обходного пути. И поэтому у меня нет доступа к объявлению столбца CHAR . Но все же, я хочу иметь возможность справиться с этим делом.

Что бы вы сделали вместо этого? Какая хорошая практика для обработки типов данных CHAR когда я хочу игнорировать конечные пробелы?

Если ты хочешь

 stmt.setString(1, "a"); // This won't return any records 

для возврата записи, попробуйте

 conn.prepareStatement("select * from x where c = cast(? as char(4))") 

Я не вижу причин использовать CHAR-тип данных, даже если это char (1) в Oracle. Можете ли вы изменить тип данных вместо этого?

Решение Гэри работает хорошо. Вот альтернатива.

Если вы используете драйвер JDBC Oracle, вызов prepareStatement() фактически вернет OraclePreparedStatement , который имеет метод setFixedCHAR() который автоматически вводит ваши входы с пробелами.

 String sql = "select * from x where c = ?"; OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement(sql); stmt.setFixedCHAR(1, "a"); ... 

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

Единственная причина, по которой я бы предположил, что вы используете это по ответам Гэри, состоит в том, что вы можете resizeы столбцов, не изменяя свой код JDBC. Драйвер набирает правильное количество пробелов без участия разработчика, который должен знать / управлять размером столбца.

У меня есть хорошее решение для этого. Вы должны добавить одно свойство при получении соединения из базы данных.

 NLS_LANG=american_america.AL32UTF8 

или в Java-соединении вы можете использовать код ниже:

 java.util.Properties info = new java.util.Properties(); info.put ("user", user); info.put ("password",password); info.put("fixedString","TRUE"); info.put("NLS_LANG","american_america.AL32UTF8"); info.put("SetBigStringTryClob","TRUE"); String url="jdbc:oracle:thin:@"+serverName; log.debug("url="+url); log.debug("info="+info); Class.forName("oracle.jdbc.OracleDriver"); conn = DriverManager.getConnection(url,info); 
Interesting Posts

Генератор случайных чисел без дубликатов

Как мы отличаемся от требований, не требующих ответа, в разрешениях Runtime Android M?

WPF: слайдер с событием, которое запускается после того, как пользователь перетаскивает

Как заставить cout вести себя как в двоичном режиме?

Есть ли FTP-инструмент, который может искать фразу во всех файлах в каталоге?

Учитывая, что последний блок не заполнен неправильно

Как получить визуально выделенный текст в VimScript

Несколько примечаний с пружиной @RequestMapping

Клавиатура – значения задержки повторения / повторения в Win7

Лучший способ включить Volley (или другую библиотеку) в проект Android Studio

404 перенаправляет ошибку Spring с помощью java config

text-overflow: многоточие не работает на IE

Запустить файл jar в командной строке

Как создать правило в Outlook для обработки писем, которые не отправляются с использованием домена отправителей

Портативный программный инструмент для вывода звука на микрофонный вход

Давайте будем гением компьютера.