Иностранные / акцентированные символы в SQL-запросе - PullRequest
4 голосов
/ 10 марта 2010

Я использую Java и класс Spring JdbcTemplate для создания SQL-запроса в Java, который запрашивает базу данных Postgres. Однако у меня возникают проблемы при выполнении запросов, которые содержат иностранные / акцентированные символы.

Например (обрезанный) код:

JdbcTemplate select = new JdbcTemplate( postgresDatabase );

String query = "SELECT id FROM province WHERE name = 'Ontario';";

Integer id = select.queryForObject( query, Integer.class );

будет извлекать идентификатор провинции, но если вместо этого я сделал name = 'Québec', тогда запрос не вернет никаких результатов (это значение находится в базе данных, поэтому проблема не в том, что он отсутствует).

Я полагаю, что источником проблемы является то, что база данных, которую я должен использовать, имеет установленную по умолчанию кодировку клиента SQL_ASCII, что в соответствии с это предотвращает автоматические преобразования набора символов. (Кодировка среды Java установлена ​​на «UTF-8», хотя мне сказали, что база данных использует «LATIN1» / «ISO-8859-1»)

Мне удалось вручную указать кодировку, когда наборы результатов содержали значения с иностранными символами в качестве решения предыдущей проблемы с аналогичной природой.

Ex:

String provinceName = new String ( resultSet.getBytes( "name" ), "ISO-8859-1" );

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

Есть ли способ обойти это без необходимости изменять свойства базы данных или реконструировать ее?

PostScript: я обнаружил эту функцию в StackOverflow при создании заголовка, он, похоже, не работал (возможно, я не использовал его правильно, но даже если он работал, это не похоже как будто это может быть лучшим решением.):

Edit: я выбрал свой собственный ответ для этого, так как это будет то, что я использую сейчас; однако, как упоминалось в комментарии ниже, я был бы рад рассмотреть другие предложения, которые могут быть лучше, если у меня есть доступ к базе данных.

Ответы [ 3 ]

3 голосов
/ 11 марта 2010

Хм, ладно, после изучения документации postgreSQL я нашел решение в разделе Строковые функции и операторы .

Я использовал функцию convert(string bytea, src_encoding name, dest_encoding name) и смог получить идентификатор провинции для Квебека.

Ex.

String query = "SELECT id FROM province WHERE name = convert( 'Québec', 'UTF-8', 'ISO-8859-1' );"; 
3 голосов
/ 11 марта 2010

Если вы подключаетесь из Java с кодировкой UTF-8, а база данных - ISO-8859-1, тогда вы должны выполнить эту команду SQL сразу после первоначального подключения к БД:

SET client_encoding = 'UTF8';

Затем PostgreSQL интерпретирует все входные данные как UTF-8, а затем преобразует их в ISO-8859-1 на стороне сервера. Тебе не нужно делать ничего, кроме этого.

0 голосов
/ 11 марта 2010

На самом деле, если ваша база данных имеет кодировку «SQL_ASCII», она в основном понимает ASCII и ничего больше. Это означает, что слово «Québec» было сохранено «как предусмотрено», что означает «как предоставлено в виде набора байтов, в соответствии с кодировкой, используемой инструментом, который обработал порядок вставки или обновления SQL в базе данных в данный момент». Следовательно, когда вы пытаетесь выбрать такие значения, вы должны использовать ту же самую кодировку, но вы должны заранее знать, какая она.

Это первый вопрос, который вам нужно решить, затем вам нужно указать, что ваш запрос должен использовать эту кодировку.

Допустим, он был сохранен в кодировке ISO-8859-1.

Я не уверен, что это может сработать, но я бы попробовал что-то подобное:

String myReq = "SELECT id FROM province WHERE name = 'Québec';";
byte[] iso8859sequence = myReq.getBytes("ISO-8859-1");
String myReqAscii = new String(iso8859sequence, "US-ASCII");
Integer id = select.queryForObject( query, Integer.class );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...