2

使用 JDBC for MySQL 从 latin1 字段(varchar 或 char)查询中文值无法获取正确值。性格无法改变。以下是测试步骤。是否有可能在这种情况下获得正确的值?我还应该做什么?

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查询时无法得到正确的值:
jdbc url : 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                 
4

3 回答 3

4

我解决它。当存储在 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) 
于 2011-12-26T03:50:00.467 回答
2

你应该改变 latin1_general_ci; 到 utf8_general_ci 或 utf16_general_ci。问题是CHARSET=latin1不能像汉字一样存储unicode字符。

看看这个: 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: 

扩展的拉丁字母(带波浪号、长音符号、尖音符、重音符和其他口音)、西里尔字母、希腊字母、亚美尼亚字母、希伯来字母、阿拉伯字母、叙利亚字母等。

**Korean, Chinese, and Japanese ideographs use three-byte sequences.**

Latin1 字符集只有8bit 单字节,而中文脚本需要多字节

于 2011-12-23T10:43:51.757 回答
0

获取所需字符的另一种更简单的方法是从列中获取字节,然后在应用程序中将它们转换为字符串。

伪代码...

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;

这将向您显示存储在列中的字节的十六进制值,以便您可以查找它们(是的,维基百科!)以查看它们是否与以各种不同方式查看显示的值匹配。

于 2012-03-11T10:48:10.650 回答