Posts Tagged ‘mysql’

可恶的乱码问题

November 12th, 2009

在打印单据的时候,有两个汉字“玥”和“芃”,始终显示为“?”,这一问题困扰了业务人员一段时间了。以前没有空,就没有投入精力去查原因,上次得了空,终于把这个问题解决掉了。

这个乱码的汉字从哪里来的呢?首先是业务人员通过一个遗留的PHP应用,输入到一个mysql 4数据库中,然后我们的java程序从这个mysql 4中读取,再写入到新的mysql5的数据库中,最后通过java程序生成html在用户的浏览器里显示,结果就看到了这两个汉字乱码。那么这个问题如何解决呢?

只有两个汉字乱码,而不是所有的汉字都乱码,所以我们的程序一定使用了一种包含汉字较少的字符集,而这个出错的汉字恰好不在此字符集中,否则,就应当是大部分汉字乱码,而不仅仅是这两个了。很自然的就让人想到了 gb2312, gbk, gb18030, utf8等字符集之间的关系。其中gb2312中只有六千多个汉字,其它几个字符集支持的汉字数相差不多,我们程序一定是在该使用gbk, gb18030或utf8的地方使用了含有汉字较少的gb2312。

经查阅相关文档,果然发现那两个汉字都不在gb2312里,而在gbk, utf8字符集里。我们的mysql5使用的utf8字符集,生成的html也是utf8编码,如果mysql5中的汉字是正确的话,那么就应该能正常显示,因此,数据进入mysql5的时候就应该出错了。java程序在连接mysql5的时候,在jdbc连接中设置了utf8,所以如果从mysql4数据库中读取出来的是正确的,就不应该写入出问题,因此数据在mysql4中可能就错了,也可能是从mysql4中读取的时候出错了。php的兄弟们说mysql的数据库是gb2312字符集的,mysql的配置文件里也是这么配置的。如果果真如此,那么这个两个汉字在mysql4的数据库中就应该不正常了,所有的程序读出之后都应该是乱码,可是php的录入程序那边确实是能正常显示的。我断定这个数据库里放的实际上是gbk字符集的汉字。选用和mysql4相对应的mysql j connector 3.14,并在jdbc连接url里设置了characterEncoding=gbk,读出来的仍旧不正确!查阅了mysql j connector的文档,原来3 版本的mysql connector根本就不支持characterEncoding这个选项。看来只能修改mysql的配置文件了。修改之后,果然这两个汉字可以正常显示了。

如果计算机是中国人发明的,那么计算机也许一开始就得支持汉字,就再也没有乱码的问题。如果世界上只有一种汉字的编码方案,也不会有乱码的问题,可惜汉字偏偏有很多中编码方案。所以在我们的程序中,一定得搞清楚,我们的汉字数据来自于哪里,使用的哪种编码,每个环节都得配置得当,否则就会有乱码问题。

对于一般的web应用来说,需要关心编码的地方有:
1,数据库以什么编码存储数据
2,程序使用什么字符集连接数据库
3,程序内部运行时使用什么字符集
4,程序源码使用什么字符集
5,生成的html文件是什么字符集
6,程序告知浏览器的字符集
如果以上这些地方的字符集有配置不正确的地方,往往就会乱码。

如果可以的话,最好在所有的地方都使用一种编码,比如对于java应用来说,在所有的地方都使用utf8编码,就可以解决问题。需要注意的是,在windows环境下,默认的文件编码是gb18030的,而不是utf8。

另外,极端鄙视故意使用生僻字火星文的脑残族!!

  • Share/Bookmark

mysql用sum()等函数后始终返回一行

June 8th, 2009

同事在写程序的时候,遇到了诡异的情况。一条sql select 语句,即使没有符合查询条件的记录,还是会返回一条结果,而且里面每个字段为null。这条sql 类似于

SELECT sum(amount) FROM ORDER WHERE 1 <> 1;

我一开始怀疑是jdbc驱动程序的问题,换了两个版本的数据库驱动,都这样。后来怀疑是sum()函数捣的鬼,一查文档,看到如下:

SUM([DISTINCT] expr)
返回expr 的总数。 若返回集合中无任何行,则 SUM() 返回NULL。DISTINCT 关键词可用于 MySQL 5.1 中,求得expr 不同值的总和。

若找不到匹配的行,则SUM()返回 NULL。

印证了我的想法。不仅sum,其他的聚合函数也是这样,看来以后用sum()等时,要小心了。

  • Share/Bookmark

mysql sql 语句中的大小写规则

November 20th, 2007

SQL 中的大小写规则在语句的不同部分是不同的,而且还取决于所引用的东西以及运行的操作系统。下面给出相应的说明:
■ SQL 关键字和函数名。关键字与函数名是不区分大小写的。可按任意的大小写字符给出。
■ 数据库与表名。MySQL 中数据库和表名对应于服务器主机上的基本文件系统中的目录和文件。因此,数据库与表名是否区分大小写取决于主机上的操作系统处理文件名的方式。运行在 UNIX 上的服务器处理数据库名和表名是区分大小写的,因为UNIX 的文件名是区分大小写的。而Windows 文件名是不区分大小写的,所以运行在Windows上的服务器处理数据库名和表名也是不区分大小写的。如果在UNIX 服务器上创建一个某天可能会移到Windows 服务器上的数据库,应该意识到这个特性:如果现在创建了两个分别名为abc 和ABC 的表,它们在Windows 机器上将是没有区别的。避免这种情况发生的一种方法是选择一种字符(如小写),总是以这种字符创建数据库和表名。这样,在将数据库移到不同的服务器时,名称的大小写便不会产生问题。
■ 列与索引名。MySQL 中列和索引名是不区分大小写的。
■ 别名。别名是区分大小写的。可按任意的大小写字符说明一个别名(大写、小写或大小写混合),但是必须在任何查询中都以相同的大小写对其进行引用。不管数据库、表或别名是否是区分大小写的,在同一个查询中的任何地方引用同一个名称都必须使用相同的大小写。对于SQL 关键字、函数名或列名和索引名没有这个要求。可在同一个查询中多个地方用不同的大小写对它们进行引用。当然,如果使用一致的大小写而不是“胡乱写”的风格(如SelECt NamE FrOm …),相应的查询可读性要强得多。

  • Share/Bookmark