小谈MySQL字符集

首先,这片文章纯粹是我的个人经验之谈,适用于我常见的环境及项目中.
个人建议,数据库字符集尽量使用utf8(HTML页面对应的是utf-8),以使你的数据能很顺利的实现迁移,因为utf8字符集是目前最适合于实现多种不同字符集之间的转换的字符集,尽管你在命令行工具上可能无法正确查看数据库中的内容,我依然强烈建议使用utf8作为默认字符集.
接下来是完整的一个例子:
1.创建数据库表
mysql>CREATE DATABASE IF NOT EXISTS my_db default charset utf8 COLLATE utf8_general_ci;
#注意后面这句话 "COLLATE utf8_general_ci",大致意思是在排序时根据utf8校验集来排序
#那么在这个数据库下创建的所有数据表的默认字符集都会是utf8了

mysql>create table my_table (name varchar(20) not null default '')type=myisam default charset utf8;
#这句话就是创建一个表了,制定默认字符集为utf8

2.写数据
例子1是通过php直接插入数据:
a.php
<?php
mysql_connect('localhost','user','password');
mysql_select_db('my_db');

//请注意,这步很关键,如果没有这步,所有的数据读写都会不正确的
//它的作用是设置本次数据库联接过程中,数据传输的默认字符集
//其他编程语言/接口也类似,例如 .net/c#/odbc
//jdbc则设置连接字符串为类似"jdbc:mysql://localhost/db?user=user&password=123456&useUnicode=true&characterEncoding=UTF-8"

mysql_query("set names utf8;");

//必须将gb2312(本地编码)转换成utf-8,也可以使用iconv()函数
mb_convert_encoding("insert into my_table values('测试');", "utf-8", "gb2312");
?>

例子是通过页面提交插入数据2:
b.php
<?php
//输出本页编码为utf-8
header("content-type:text/html; charset=utf-8");

mysql_connect('localhost','user','password');
mysql_select_db('my_db');

mysql_query("set names utf8;");

if(isset($_REQUEST['name'))
{
//由于上面已经指定本页字符集为utf-8了,因此无需转换编码
mysql_query(sprintf("insert into my_table values('%s');", $_REQUEST['name']));
}

$q = mysql_query("select * from my_table");
while($r = mysql_fetch_row($q))
{
print_r($r);
}
?>

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<form action="" method="post">
<input type="text" name="name" value="">
<input type="submit" value='submit'>
</form>

自此,使用utf8字符集的完整的例子结束了.
如果你想使用gb2312编码,那么建议你使用latin1作为数据表的默认字符集,这样就能直接用中文在命令行工具中插入数据,并且可以直接显示出来.而不要使用gb2312或者gbk等字符集,如果担心查询排序等问题,可以使用binary属性约束,例如:
create table my_table ( name varchar(20) binary not null default '')type=myisam default charset latin1;

附1:旧数据升级办法
以原来的字符集为latin1为例,升级成为utf8的字符集。原来的表: old_table (default charset=latin1),新表:new_table(default charset=utf8)。
第一步:导出旧数据
mysqldump --default-character-set=latin1 -hlocalhost -uroot -B my_db --tables old_table > old.sql
第二步:转换编码(类似unix/linux环境下)
iconv -t utf-8 -f gb2312 -c old.sql > new.sql
或者可以去掉 -f 参数,让iconv自动判断原来的字符集
iconv -t utf-8 -c old.sql > new.sql
在这里,假定原来的数据默认是gb2312编码。
第三步:导入
修改old.sql,在插入/更新语句开始之前,增加一条sql语句:

"SET NAMES utf8;"

,保存。
mysql -hlocalhost -uroot my_db < new.sql
大功告成!!

附2:支持查看utf8字符集的MySQL客户端有
1.) MySQL-Front,据说这个项目已经被MySQL AB勒令停止了,不知为何,如果国内还有不少破解版可以下载(不代表我推荐使用破解版 :-P)。
2.) Navicat,另一款非常不错的MySQL客户端,汉化版刚出来,还邀请我试用过,总的来说还是不错的,不过也需要付费。
3.) PhpMyAdmin,开源的php项目,非常好。
4.) Linux下的终端工具(Linux terminal),把终端的字符集设置为utf8,连接到MySQL之后,执行 SET NAMES UTF8; 也能读写utf8数据了。

附3:本站提供转换文件内容字符集工具(CCT),可以支持最大2Mb的文件字符集转换,欢迎使用。


评论

比如标点的转换,还有特殊字符

放心,除非有不能识别的生僻字,常见的字符都能支持的。

\\\这种转义的字符呢?

我的是RH9 数据库是MYSQL5,用的是RPM安装。默认的字符是latin1.手动插入中文,用JSP读取后出现乱码。这是怎么回事?
mysql的默认数据库放在/var/lib下,我能不能将新建的数据放到其它地方?

另外:
在windows下mysql为什么用GBK字符,JSP才能正常读取中文?用UTF8怎么会出乱码?

这几个问题一直困扰我好几天,一直没想明白。还请指点。在此不胜感激!
我的邮箱:pmy54@163.com
谢谢·

你应该是通过jdbc连接mysql的吧,大致的解决办法可以在这里找到!
对jsp和jdbc我不是了解,抱歉。

表的默认字符集是latin1也不能保证你在用JDBC连接数据库时就定不会出现乱码。
记住JAVA是unicode编码的。所以在连接数据库的url中一定要指定编码类型。

另外向表里插入记录时最好使用getBytes("iso-8859-1")转换一下。
从表里取出后,也可以用此方法getBytes("latin1")转一下码。

这个就更不会出问题了,放心。ascii字符它不会转成别的。

欢迎来到MySQL中文网: http://imysql.cn

给你的祝福,要让你招架不住!

那我想咨询一下,如果是类似于like的单字符搜索结果会准确吗?例如:like '%徐%',请帮忙测试一下,我用的版本是5.0.19,谢谢!

如果是非英文字符的,最好加binary修饰符,例如:
select x from xx where binary xx like '%徐%';
但仍旧可能会把不包含'徐'字的内容给检索出来,比较好的办法就是用utf-8字符集来存储,并且指定是utf-8校验字符集。

欢迎来到MySQL中文网: http://imysql.cn

给你的祝福,要让你招架不住!

您的这句:
select x from xx where binary xx like '%徐%';
中,binary XX应该是字段名吧?
再问:如果表或字段都没有在定义时指定 binary ,是否可以这样用呢?
------------------------------
任凭岁月悠悠,我心依然风流.

"旧数据升级办法"---不好意思,这个地方看的不是很懂能否说的具体点.谢谢....

哪里看不懂?欢迎用邮件(首选)或者msn跟我交流。。。

欢迎来到MySQL中文网: http://imysql.cn

给你的祝福,要让你招架不住!

我在使用varchar(非binary)时,"coco"和"球球"编码(gb)重合了,请问可否在不改变字段和编码的情况下,区分开这两个词?

你试着改改一下数据表的COLLATION,然后试试看。
参见ALTER TABLE语法。

欢迎来到MySQL中文网: http://imysql.cn

给你的祝福,要让你招架不住!

我用的是mysql5.0.24,设定为utf8,使用WP很正常,但用phpmyadmin和命令行操作mysql的是候显示的中文还是乱码~~为什么会这样的呢??

请加入本站的msn群详细讨论。

欢迎来到MySQL中文网: http://imysql.cn

给你的祝福,要让你招架不住!

按上述设置后
CREATE DATABASE `中文`
CHARACTER SET 'utf8'
COLLATE 'utf8_general_ci';
后,在data目录下的文件夹名是乱码.
windowsxp系统,mysql5,请问大家有没有遇到这个情况?如何解决?

谢谢! :-)

mysql 5.x中,系统文件夹(数据库文件夹)的字符集都是utf8的,因此如果你的操作系统不支持utf8的话,显示起来就似乎是'乱码',但是并不影响你正常使用。
另外,强烈建议采用英文来命名,否则很容易产生兼容性问题,将来麻烦的很。

欢迎来到MySQL中文网: http://imysql.cn

给你的祝福,要让你招架不住!

谢谢,我看到5.1里有一个设置set filesystem charset 默认是 binary 但是我改了以后反而不能用了,不知道这个是不是可以更改存盘的charset?

还有就是字段名称使用汉字是否功能键全?

谢谢!

欢迎来到MySQL中文网: http://imysql.cn

给你的祝福,要让你招架不住!

系统全局变量character_set_filesystem跟你的文件系统相关,最好是不要改动它.另外,还是那句话,除非迫不得已,一定不要采用中文命名数据库/表/字段等.

欢迎来到MySQL中文网: http://imysql.cn

给你的祝福,要让你招架不住!

谢谢,今天把所有中文字段都改成英文啦,呵呵,挺无奈的,等mysql升级吧。

有些特殊的词用英语不容易表达,有些遗憾。 :-)

呵呵,可以用英文单词的第一个字母组合啊,很简单的哦

欢迎来到MySQL中文网: http://imysql.cn
欢迎加入Google MySQL中文用户群:http://groups.google.com/group/imysql

给你的祝福,要让你招架不住!

mysql的乱码确实很烦人,utf8页面的表单,又没有文件上传好像还不一样。

具体区别在哪呢,我好像没碰到过...

MySQL方案、培训、支持

给你的祝福,要让你招架不住!

你好。
原来mysql5.0.21 wordpress 用的是原默认latin1
直接拷备的/mysql/var/wordpress/* 和 htdocs/wordpress
现在是mysql5.0.41,新数据库设置默认都 为utf8
把它俩再拷回到相应目录下。再设置worpress数据库的用户和密码
而现在的worpress数据库是原来的latin1
用浏览器上wordpress 全是乱码
请问:如何,改成utf8??

按照上面所说的,先用iconv之类的工具转换一下编码后,重新倒入。

MySQL方案、培训、支持

给你的祝福,要让你招架不住!

也许我没说明白
我备份只是mysql下wordpress目录和apache目录下相关的目录!
而不是直接备份的数据库??
能说清每个步骤吗????

也许我没说明白
我备份只是mysql下wordpress目录和apache目录下相关的目录!
而不是直接备份的数据库??
能说清每个步骤吗????

改用mysqldump来备份呗?

MySQL方案、培训、支持

给你的祝福,要让你招架不住!

你可以把 在 phpmyadmin 里 把数据先 导出,然后,改 .sql 里的 CHARSET=latin1

改成 CHARSET=utf8

然后在 导入 到你要放的 数据库 里,就可以了

希望你成功!!

如有问题可以和我联系!!

QQ:36380150
MSN:guopeng623@hotmail.com

也许我没说明白
我备份只是mysql下wordpress目录和apache目录下相关的目录!
而不是直接备份的数据库??
能说清每个步骤吗????

实属好文章!
转码函数有笔误,对初学者可能会走弯路,希望叶兄修正:

mb_convet_encoding("insert into my_table values('测试');", "utf-8", "gb2312");

应为:

mb_convert_encoding("insert into my_table values('测试');", "utf-8", "gb2312");

mysql_query("set names utf8;");
改成:
mysql_query("set names gb2312;");

则本地网页,php 文件都可以用 gb2312 编码,而且在查询和插入数据库时,都不必做转码的。

你好咨询个问题:
MySql 输入中文条件为何查找不到记录。
如在c#中执行
string sql = "select uid,username from cdb_members where binary username='你好'";
DataTable dt = center.Query(sql);

如果把'你好'改为英文字母就可已查找到记录。

日志中出现此错误时,请教该如何下手处理?

./discuz/cdb_tags' had no or invalid character set, and default character set is multi-byte, so character column sizes may have changed

贴上 SHOW CREATE TABLE cdb_tags;  的结果

MySQL方案、培训、支持

very helpful, thx!

i love mysql, php, drupal, wordpress etc...
recently, i've got an idea to build a site based on drupal and named 'iDrupal'. its chinese name is 爱猪泡. and i hope we can exchange links with each other if you like...
lol

感謝張貼這一點,使公眾開放。我一直在尋找困難,處理這個同樣的情況現在幾個星期。我非常感謝有偶然發現了這個網站。