Невозможно получить правильное значение для запроса китайского значения из поля latin1 Использование JDBC для MySQL - PullRequest
2 голосов
/ 23 декабря 2011

Невозможно получить правильное значение для запроса китайского значения из поля latin1 (varchar или char), используя JDBC для MySQL. Персонаж не может быть изменен. Ниже приведены шаги теста. Можно ли получить правильное значение для этой ситуации? Что еще мне делать?

1. создать базу данных:

CREATE DATABASE TESTDB CHARACTER SET latin1 COLLATE latin1_general_ci;  

2. создать таблицу:

CREATE TABLE TB1 (
    vname varchar(50) default '',
    cname char(50) default ''
) DEFAULT CHARSET=latin1 ;

3. вставить данные:

set names latin1;  
insert into TB1(vname,cname) values('名字v','名字c');  

4. показать набор символов:

mysql> show variables like '%set%';  
+--------------------------+---------------------------------------------------------+  
| Variable_name            | Value                                                   |  
+--------------------------+---------------------------------------------------------+  
| auto_increment_offset    | 1                                                       |  
| character_set_client     | latin1                                                  |  
| character_set_connection | latin1                                                  |  
| character_set_database   | latin1                                                  |  
| character_set_filesystem | binary                                                  |  
| character_set_results    | latin1                                                  |  
| character_set_server     | utf8                                                    |  
| character_set_system     | utf8                                                    |  
| character_sets_dir       | F:\Program Files\MySQL\MySQL Server 5.5\share\charsets\ |  
+--------------------------+---------------------------------------------------------+  

5. он может получить правильное значение при запросе из командной консоли:

mysql> select * from tb1;  
+-------+-------+  
| vname | cname |  
+-------+-------+  
| 名字v     | 名字c     |  
+-------+-------+  
1 row in set (0.00 sec)  

6. невозможно получить правильную оценку при использовании JDBC для запроса:
URL-адрес JDBC: JDBC: MySQL: //192.168.5.74/testdb? characterEncoding = UTF-8

*set names utf8;  
select vname,hex(vname),length(vname),char_length(vname) from tb1;  
select cname,hex(cname),length(cname),char_length(cname) from tb1;  
select vname,cname  
    ,CONVERT(CONVERT(CONVERT(vname USING latin1) USING binary) USING utf8) as c1  
    ,CONVERT(CONVERT(CONVERT(cname USING latin1) USING binary) USING utf8) as c2  
from tb1;*  

vname           hex(vname)     length(vname) char_length(vname)   
--------------- -------------- ------------- ------------------   
??×?v           C3FBD7D676     5             5                    

cname           hex(cname)     length(cname) char_length(cname)   
--------------- -------------- ------------- ------------------   
??×?c           C3FBD7D663     5             5                    

vname             cname     c1      c2      
----------------- --------- ------- ------  
??×?v             ??×?c                 

Ответы [ 3 ]

3 голосов
/ 26 декабря 2011

Я разрешаю это. Многобайтовые символы преобразуются в байты при хранении в поле latin1. Необходимо преобразовать обратно во вставку кодировки. Следующий sql может сделать это:

CONVERT(CONVERT(CONVERT(vname USING latin1) USING binary) USING [INSERT_CHARSET]) 

Моя кодировка вставки gb2312, поэтому sql должен быть:

CONVERT(CONVERT(CONVERT(vname USING latin1) USING binary) USING gb2312) 
2 голосов
/ 23 декабря 2011

Вы должны изменить latin1_general_ci;до utf8_general_ci или utf16_general_ci.Проблема в том, что CHARSET = latin1 не может хранить символы Юникода, такие как китайские символы.

Проверьте это: http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-utf8.html

Идея UTF-8 заключается в том, что различные символы Unicode кодируются с использованием последовательностей байтов различной длины:

Basic Latin letters, digits, and punctuation signs use one byte.

Most European and Middle East script letters fit into a two-byte sequence: 

расширенные латинские буквы (с тильдой, макроном, острым, серьезным и другими акцентами), кириллицей, греческим, армянским, ивритом, арабским, сирийским и др.1014 * 8-битный однобайтовый , в то время как для китайского сценария требуются многобайтовые

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

Другой, более простой способ получения нужных символов - получить байты из столбца и затем преобразовать их в строку внутри приложения.

псевдокод ...

byte[] rawBytes = resultSet.getBytes( "vname" );
String vname = new String( rawBytes, "gb2312" );

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

select vname, length( vname ) as bytelength, char_length( vname ) as stringlength from tb1;

Кроме того, функция hex() также является вашим другом:

select vname, hex( vname ) from tb1;

Это покажет вам шестнадцатеричные значения байтов, которые хранятся в столбце, чтобы вы могли затем просмотреть их (да, Википедия!), Чтобы увидеть, соответствуют ли они отображаемому значению при различных способах его просмотра.

...