免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1966 | 回复: 1
打印 上一主题 下一主题

mysql编码的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2010-06-11 00:33 |只看该作者 |倒序浏览
本帖最后由 磊子菜 于 2010-06-11 00:35 编辑

前些天遇到一个问题,这里分享给各位。。。
写在最前面,保证character_set_client、character_set_results和 character_set_connection 这三种用到的字符集完全一致,那么将会免受mysql中关于字符集的困扰。

1,问题的发现:
select
temp.statisMonth,
temp.platform,
temp.version,
temp.now_use_total,
temp2.maxOnlineCount from
(select
t1.id,
date_format('20100501','%Y-%m') as statisMonth,
platform,
version,
sum(t1.now_use_total) as now_use_total
from
mqq_result.mqq_lc_month t1 inner join statis_test.lc_ext t3 on t1.lc=t3.lc
where
t1.statisMonth = date_format('20100501','%Y-%m') group by 2 ) temp inner join statis_test.kqq_platformVersion_max_online_month temp2
On temp.statisMonth=temp2.statisMonth and temp.platform=temp2.platform and temp.version =temp2.version

这样的语句在展示前台配置好了之后,执行的时候却报下面这样的错误:“Illegal mix of collations (gb2312_chinese_ci,COERCIBLE) and (gbk_chinese_ci,IMPLICIT) for operation '=' ”

2,问题的定位:
a,首先检查了下用到的几张表采用的字符集,发现都是用gbk编码,不存在字符集不一致的情况。
b,由于是在"="操作时候出现的问题,上面的sql语句中,只有
temp.statisMonth=temp2.statisMonth and temp.platform=temp2.platform and temp.version =temp2.version 这三个地方用到了"="操作。于是挨个挨个测试这三个运算中的每一个,发现是temp.statisMonth=temp2.statisMonth 这个"="操作会遇到字符集不一致的情况。
c,由于报的错误又是字符集"gb2312"和"gbk"冲突的情况,所以就检查下,看报表展示前台JDBC连接数据库的编码。发现报表展示前台连接数据库的编码方式是"gb2312"。


3,问题的解决:
a,查了下mysql中的manual,manual中写道:
“对于简单的语句SELECT 'string',字符串使用由character_set_connection和collation_connection系统变量定义的字符集和 校对规则”
所以这里可以看出,在sql中临时表中选择出来的statisMonth 字段是用 character_set_connection 来编码的。于是将下面这个语句
"on temp.statisMonth=temp2.statisMonth and temp.platform=temp2.platform and temp.version =temp2.version" 修改为
"on convert(temp.statisMonth using gbk)=temp2.statisMonth and convert(temp.platform using gbk)=temp2.platform and convert(temp.version using gbk) =temp2.version"
这样就可以得到正确的结果了。

4,又无法解释的一幕来了:
为什么下面这个sql语句就可以执行成功呢?如果按照上面的理论,这样的语句也应该执行不成功呀???
select
temp.statisDay,
temp.platform,
temp.version,
temp.now_use_total,
temp2.maxOnlineCount from
(select
t1.id,
date_format('20100501','%Y-%m-%d') as statisDay,
platform,
version,
sum(t1.now_use_total) as now_use_total
from
mqq_result.mqq_lc_day t1 inner join statis_test.lc_ext t3 on t1.lc=t3.lc
where
t1. statisDay = date_format('20100501','%Y-%m-%d') group by 2 ) temp inner join statis_test.kqq_platformVersion_max_online_day temp2
on temp.statisDay=temp2.statisDay and temp.platform=temp2.platform and temp.version =temp2.version
其实这个也比较好解释,因为 kqq_platformVersion_max_online_day表中statisDay字段是date日期类型,date类型在和临时表中的statisDay字符串进行join的时候可以容忍编码不一致的情况。
而kqq_platformVersion_max_online_month表中statisMonth字段是varchar类型,这样进行join的时候,就会出问题。


相关概念:
1,什么叫做 “字符集” ?
假设我们有一个字母表使用了四个字母:‘A’、‘B’、‘a’、‘b’。我们为每个字母赋予一个数值:‘A’=0,‘B’= 1,‘a’= 2,‘b’= 3。字母‘A’是一个符号,数字0是‘A’的编码,这四个字母和它们的编码组合在一起是一个字符集。
2, mysql中服务器字符集和校对规则可以用作character_set_server和collation_server变量的值。
3,默认数据库的字符集和校对规则可以用作character_set_database和collation_database变量的值
4,当查询离开客户端后,在查询中使用哪种字符集?
服务器使用character_set_client变量作为客户端发送的查询中使用的字符集。
5,服务器接收到查询后应该转换为哪种字符集?
   转换时,服务器使用character_set_connection和collation_connection系统变量。它将客户端发送的查询从character_set_client系统变量转换到character_set_connection(除非字符串文字具有象_latin1或_utf8的引介词)。collation_connection对比较文字字符串是重要的。对于列值的字符串比较,它不重要,因为列具有更高的 校对规则优先级。
6,服务器发送结果集或返回错误信息到客户端之前应该转换为哪种字符集?
character_set_results变量指示服务器返回查询结果到客户端使用的字符集。包括结果数据,例如列值和结果元数据(如列名)。
你能够调整这些变量的设置,或可以依赖默认值(这样,你可以跳过本章)。
7,当一个客户端连接时,它向服务器发送希望使用的字符集名称。服务器为那个字符集设置character_set_client、character_set_results和 character_set_connection变量。(实际上,服务器为使用该字符集执行一个SET NAMES操作。)

论坛徽章:
0
2 [报告]
发表于 2010-06-11 00:35 |只看该作者
其实这个也比较好解释,因为 kqq_platformVersion_max_online_day表中statisDay字段是date日期类型,date类型在和临时表中的statisDay字符串进行join的时候可以容忍编码不一致的情况。
而kqq_platformVersion_max_online_month表中statisMonth字段是varchar类型,这样进行join的时候,就会出问题
=================================
这个解释不怎么彻底和清晰,希望CU达人多多发表看法,和解答
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP