﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-同一个目标，同一个梦想-文章分类-MySQL</title><link>http://www.blogjava.net/J2EEHOME/category/35947.html</link><description>One Target,One Dream</description><language>zh-cn</language><lastBuildDate>Thu, 13 Nov 2008 10:54:49 GMT</lastBuildDate><pubDate>Thu, 13 Nov 2008 10:54:49 GMT</pubDate><ttl>60</ttl><item><title>Mysql 数据库字符集转换</title><link>http://www.blogjava.net/J2EEHOME/articles/240257.html</link><dc:creator>J2EE Home工作室</dc:creator><author>J2EE Home工作室</author><pubDate>Thu, 13 Nov 2008 02:56:00 GMT</pubDate><guid>http://www.blogjava.net/J2EEHOME/articles/240257.html</guid><wfw:comment>http://www.blogjava.net/J2EEHOME/comments/240257.html</wfw:comment><comments>http://www.blogjava.net/J2EEHOME/articles/240257.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/J2EEHOME/comments/commentRss/240257.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/J2EEHOME/services/trackbacks/240257.html</trackback:ping><description><![CDATA[<div id="article">
<p><font face="Times New Roman">最近discuz发布了新的版本，免费了，用的人更多了，以前使用其它论坛程序和discuz2.5/3.0的纷纷转换或升级到discuz4.0，可见discuz作为中国人开发的PHP论坛程序，确实是非常优秀的，在大家欣喜若狂的时候，也遇到了一些问题 <br />
看到不少用户反映转换完以后是乱码的情况,出现这种现象的主要原因是这类用户使用的都是MySQL4.1以上的版本.下面作一个说明,希望出现这个问题的朋友都能耐心的把这个文档看完!!! <br />
MySQL 4.1开始，对多语言的支持有了很大变化 (这导致了问题的出现)。尽管大部分的地方 (包括个人使用和主机提供商)，MySQL 3、4.0 仍然占主导地位；但 MySQL 4.1 乃至5.0是 MySQL 官方推荐的数据库，已经有主机提供商开始提供并将会越来越多；因为 latin1 在许多地方 (下边会详细描述具体是哪些地方) 作为默认的字符集，成功的蒙蔽了许多 PHP 程序的开发者和用户，掩盖了在中文等语言环境下会出现的问题。 <br />
MySQL 4.1开始把多国语言字符集分的更加详细，所以导致数据库迁移，或则dz论坛升级到4.0后（dz4.0开始使用gbk或utf-8编码）出现乱码问题。 <br />
MySQL 4.1的字符集支持(Character Set Support)有两个方面：字符集(Character set)和排序方式(Collation)。对于字符集的支持细化到四个层次: 服务器(server)，数据库(database)，数据表(table)和连接(connection)。 <br />
查看系统的字符集和排序方式的设定可以通过下面的两条命令： </font></p>
<p><font face="Times New Roman">QUOTE:<br />
MySQL&gt; SHOW VARIABLES LIKE 'character_set_%';<br />
+--------------------------+----------------------------+<br />
| Variable_name | Value |<br />
+--------------------------+----------------------------+<br />
| character_set_client | latin1 |<br />
| character_set_connection | latin1 |<br />
| character_set_database | latin1 |<br />
| character_set_results | latin1 |<br />
| character_set_server | latin1 |<br />
| character_set_system | utf8 |<br />
| character_sets_dir | /usr/share/MySQL/charsets/ |<br />
+--------------------------+----------------------------+<br />
7 rows in set (0.00 sec) <br />
MySQL&gt; SHOW VARIABLES LIKE 'collation_%'; <br />
+----------------------+-------------------+<br />
| Variable_name | Value |<br />
+----------------------+-------------------+<br />
| collation_connection | latin1_swedish_ci |<br />
| collation_database | latin1_swedish_ci |<br />
| collation_server | latin1_swedish_ci |<br />
+----------------------+-------------------+<br />
3 rows in set (0.00 sec) <br />
MySQL 4.1 对于字符集的指定可以细化到一台机器上安装的 MySQL，其中的一个数据库，其中的一张表，其中的一栏，应该用什么字符集。但是，传统的 Web 程序在创建数据库和数据表时并没有使用那么复杂的配置，它们用的是默认的配置，那么，默认的配置从何而来呢？ <br />
编译 MySQL 时，指定了一个默认的字符集，这个字符集是 latin1； <br />
安装 MySQL 时，可以在配置文件 (my.ini) 中指定一个默认的的字符集，如果没指定，这个值继承自编译时指定的； <br />
启动 MySQLd 时，可以在命令行参数中指定一个默认的的字符集，如果没指定，这个值继承自配置文件中的； <br />
此时 character_set_server 被设定为这个默认的字符集； <br />
当创建一个新的数据库时，除非明确指定，这个数据库的字符集被缺省设定为 character_set_server； <br />
当选定了一个数据库时，character_set_database 被设定为这个数据库默认的字符集； <br />
在这个数据库里创建一张表时，表默认的字符集被设定为 character_set_database，也就是这个数据库默认的字符集； <br />
当在表内设置一栏时，除非明确指定，否则此栏缺省的字符集就是表默认的字符集； <br />
这个字符集就是数据库中实际存储数据采用的字符集，MySQLdump 出来的内容就是这个字符集下的； <br />
当我们按照原来的方式通过PHP存取MySQL数据库时，就算设置了表的默认字符集为utf8并且通过UTF-8编码发送查询，你会发现存入数据库的仍然是乱码。问题就出在这个connection连接层上。<br />
想要进行&#8220;正确&#8221;的存储和得到&#8220;正确&#8221;的结果，最方便的是在所有query开始之前执行一下： <br />
SET NAMES 'gbk';<br />
其中gbk是数据库字符集。 <br />
它相当于下面的三句指令：<br />
SET character_set_client = gbk;<br />
SET character_set_results = gbk;<br />
SET character_set_connection = gbk; <br />
4.1和5.0默认使用的是latin1字符集(木头:妈的,老外真霸道,妄想让全世界都是使用瑞典字符集吗)<br />
如果我们只想使用gbk字符集存储和获取数据,<br />
我们在编译MySQL 4.1和 5.0的时候，需要注意在my.ini或者my.cnf中添加两处参数 </font></p>
<p><font face="Times New Roman">[Copy to clipboard] [ - ]<br />
CODE:<br />
[MySQLd]<br />
default-character-set=utf8&nbsp;<br />
&nbsp; </font></p>
<p><font face="Times New Roman">[Copy to clipboard] [ - ]<br />
CODE:<br />
#settings for clients (connection, results, clients)<br />
[MySQL]<br />
default-character-set=utf8 <br />
下面我们来说主题，如何转换数据库字符集<br />
两种方法， </font></p>
<p><font face="Times New Roman">QUOTE:<br />
第一种----更改存储字符集<br />
主要的思想就是把数据库的字符集有latin1改为gbk，big5,或者utf8; 以下操作必须拥有主机权限。假设当前操作的数据库名为：database <br />
导出<br />
首先需要把数据导为MySQL4.0的格式，具体的命令如下： <br />
MySQLdump -uroot -p --default-character-set=latin1 --set-charset=gbk --skip-opt databse &gt; d4.sql <br />
--default-characte-set 以前数据库的字符集，这个一般情况下都是latin1的， <br />
--set-charset 导出的数据的字符集，这个可以设置为gbk，utf8,或者big5 <br />
导入<br />
首先使用下面语句新建一个GBK字符集的数据库（test） <br />
CREATE DATABASE `d4` DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;<br />
然后把刚才导出的数据导入到当前的数据库中就ok了。 <br />
MySQL -uroot -p --default-character-set=gbk -f d4&lt;d4.sql<br />
通过以上的导出和导入就把数据库的字符集改为正确的存储方式了。 <br />
其中d4为新建库的名称，d4.sql为导出文件的名字 <br />
但是这种方法，发现数据库数据存储量无端变大30%，真是郁闷&nbsp;<br />
&nbsp; </font></p>
<p><font face="Times New Roman">QUOTE:<br />
另外一种其实原理相同，但是需要手动操作，一般用于第一种方法失败后的选择<br />
不过这种方法如果数据库很大，估计很难做，因为光打开文件就能让你死机 <br />
首先还是用PHPmyadmin或者用MySQL本身的dump导出 .sql文件 <br />
然后用UltraEdit打开你备份的所有xxxx.sql文件，查找 </font></p>
<p><font face="Times New Roman">[Copy to clipboard] [ - ]<br />
CODE:<br />
DEFAULT CHARSET=latin1 <br />
latin1这里也许是别的，反正是你不想要的，要转成gbk或者big5的字符集<br />
把这个替换为&#8220;空&#8221;<br />
在查找 </font></p>
<p><font face="Times New Roman">[Copy to clipboard] [ - ]<br />
CODE:<br />
CREATE TABLE cdb_sessions (<br />
&nbsp; sid char(6) character set latin1 collate latin1_bin NOT NULL default '',<br />
&nbsp; ip1 tinyint(3) unsigned NOT NULL default '0',<br />
&nbsp; ip2 tinyint(3) unsigned NOT NULL default '0',<br />
&nbsp; ip3 tinyint(3) unsigned NOT NULL default '0',<br />
&nbsp; ip4 tinyint(3) unsigned NOT NULL default '0',<br />
&nbsp; uid mediumint(8) unsigned NOT NULL default '0',<br />
&nbsp; username char(15) NOT NULL default '',<br />
&nbsp; groupid smallint(6) unsigned NOT NULL default '0',<br />
&nbsp; styleid smallint(6) unsigned NOT NULL default '0',<br />
&nbsp; invisible tinyint(1) NOT NULL default '0',<br />
&nbsp; `action` tinyint(1) unsigned NOT NULL default '0',<br />
&nbsp; lastactivity int(10) unsigned NOT NULL default '0',<br />
&nbsp; fid smallint(6) unsigned NOT NULL default '0',<br />
&nbsp; tid mediumint(8) unsigned NOT NULL default '0',<br />
&nbsp; nickname char(15) NOT NULL default '',<br />
&nbsp; UNIQUE KEY sid (sid)<br />
) ENGINE=HEAP MAX_ROWS=1000; <br />
替换为 </font></p>
<p><font face="Times New Roman">[Copy to clipboard] [ - ]<br />
CODE:<br />
CREATE TABLE `cdb_sessions` (<br />
&nbsp; `sid` char(6) binary NOT NULL default '',<br />
&nbsp; `ip1` tinyint(3) unsigned NOT NULL default '0',<br />
&nbsp; `ip2` tinyint(3) unsigned NOT NULL default '0',<br />
&nbsp; `ip3` tinyint(3) unsigned NOT NULL default '0',<br />
&nbsp; `ip4` tinyint(3) unsigned NOT NULL default '0',<br />
&nbsp; `uid` mediumint(8) unsigned NOT NULL default '0',<br />
&nbsp; `username` char(15) NOT NULL default '',<br />
&nbsp; `groupid` smallint(6) unsigned NOT NULL default '0',<br />
&nbsp; `styleid` smallint(6) unsigned NOT NULL default '0',<br />
&nbsp; `invisible` tinyint(1) NOT NULL default '0',<br />
&nbsp; `action` tinyint(1) unsigned NOT NULL default '0',<br />
&nbsp; `lastactivity` int(10) unsigned NOT NULL default '0',<br />
&nbsp; `fid` smallint(6) unsigned NOT NULL default '0',<br />
&nbsp; `tid` mediumint(8) unsigned NOT NULL default '0',<br />
&nbsp; `nickname` char(15) NOT NULL default '',<br />
&nbsp; UNIQUE KEY `sid` (`sid`)<br />
) TYPE=HEAP MAX_ROWS=2000; <br />
这一步更为简单的办法就是删除掉关于cdb_sessions表的这一段，将来全新装一个d4，将这个表导出<br />
将其内容复制，粘贴到 sql文件的最后面 <br />
保存后，再把这个sql文件导入到你的库中 <br />
就OK了 <br />
用这两种方法就可以很方便的把4.1和5.0的MySQL数据库降级到4.0<br />
简单的过程就是<br />
A导出4.1/5.0的库<br />
B进行处理，转换成gbk字符集<br />
C彻底卸载4.1或者5.0<br />
D安装4.0.26<br />
E然后导入处理完的库 <br />
降级的时候导出库可以用这个方法<br />
mysqldump -uroot -p --default-character-set=latin1 --set-charset=gbk --skip-opt databse&nbsp; --compatible=MySQL40 &gt; d4.sql <br />
这样导出的就是4.0的库勒 <br />
至于MySQL版本的升级，<br />
如果数据文件中有中文信息，那么将MySQL 4.0的数据文件，直接拷贝到MySQL 4.1中就是不可以的，即便在my.ini中设置了default-character-set为正确的字符集。虽然貌似没有问题，但MySQL 4.1的字符集有一处非常恼人的地方，以gbk为例，原本MySQL 4.0数据中varchar,char等长度都会变为原来的一半，这样存储中文容量不变，而英文的存储容量就少了一半。这是直接拷贝数据文件带来的最大问题。 <br />
所以，升级的根本，如果想使用&#8220;正确&#8221;的字符集，还是先用MySQLdump导出成文件，然后导入。</font></p>
</div>
<img src ="http://www.blogjava.net/J2EEHOME/aggbug/240257.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/J2EEHOME/" target="_blank">J2EE Home工作室</a> 2008-11-13 10:56 <a href="http://www.blogjava.net/J2EEHOME/articles/240257.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>