经常有朋友问到 mysql 的乱码问题。得到的答案多半是说:要保证编码一致,甚至php程序文件也要做到编码一致。其实不然!背景:
我还是在 mysql4 时代使用过 mysql,他没有编码问题,但也没有存储过程。所以就改用 sql server 了。最近因项目需求,又把 mysql 捡起来了。也测试了一下 mysql 的语言编码问题
我安装的是 mysql 5.1.47 版本,安装时选则了 utf8 作为默认语言
但我仍然喜欢使用 gbk 编码,因为编辑 utf-8 编码的文件需要用编程工具,而我只喜欢用 记事本于是我在上述环境中以 DEFAULT CHARSET=gbk 建库建表
并在 mysql_query('set names gbk'); 之后进行数据库操作。一直如此,并无任何问题。后来有一个必须为 utf-8 编码的页面,他还要使用那个 gbk 编码的库中的数据。怎么办呢?直接的想法就是取出数据后再用 iconv 函数转码。很是费劲吧?其实 mysql 已经做的很好了,只需要设置一下语言
mysql_query('set names utf8');
于是查询结果都是 utf-8 编码的了
不错!
于是我向 gbk 编码的表中插入 utf-8 编码的数据,然后用 gbk 编码读回(set names gbk)
真不错!
刚才插入的数据已然以 gbk 编码展示,一点乱码也没有
请有兴趣的朋友发表高论!
谢绝顶贴!

解决方案 »

  1.   

    老大,你这样做有危险,如果一开始set names utf-8,你插入utf-8编码的数据没有问题,出来转换为gbk也没问题。但是如果,你set names gbk之后仍然插入utf-8数据,那就全乱了。
      

  2.   

    set names gbk  ”gbk“可以换啊  做个判断
      

  3.   

    你以为 set names gbk 是什么呢?
    我理解,这是通知 mysql 下面的操作我将以 gbk 编码进行。与 mysql 表的实际编码无关,编码转换由 mysql 自行完成
      

  4.   

    那老大认为,mysql表中的数据是以什么方式存储的,或者是什么编码存储的?
      

  5.   

    我认为set names gbk是通知mysql,我的即将操作的数据是gbk的,但是如果你把utf-8的编码给了mysql,结果它以gbk编码处理,那不就乱了吗?
      

  6.   

    老大发帖了。
    向 gbk 编码的表中插入 utf-8 编码的数据,然后用 gbk 编码读回(set names gbk)
    这样子是可以,但是难道每次进行查询的时候都要set names??
    而且,对于一个网站页面编码不一致,甚至错综复杂的网站来说,比如新闻页,你在这个页面插入utf8的,另一个页面又是gbk的,那你在某个列表显示或详细内容显示的时候(通过参数id动态展示),那你查询之前是set names gbk还是set names utf8???
    而且你set names什么编码,你的页面的编码页得什么编码。
    之所以说要将php或html文件的存储编码也设为一样,是因为如果文件编码不一样,而文件里又直接写入了中文,那这部分中文也会乱码(虽然从数据库里读出的数据不会)
      

  7.   

    意思是:数据库什么样的编码字符都能存,mysql表的编码只是在提供显示的时候自动的将其存储的信息按此编码进行转换、从而显示出来?
      

  8.   

    我有点ben  考虑问题很简单  刚开始学编程的时候  就知道统一编码 其他深的一些都很傻
    呵呵 我还是沉默  当个旁观者吧
      

  9.   

    插入mysql_connect('localhost', 'root','root');
    mysql_select_db('test');
    mysql_query("set names 'gbk'");
    //mysql_query("set names 'utf8'");
    mysql_query("insert into house set `name`='gbk名字', `addr`='gbk地址', `dev`='gbk其他测试'");
    echo 'ok';查询mysql_connect('localhost', 'root','root');
    mysql_select_db('test');
    //mysql_query("set names 'gbk'");
    mysql_query("set names 'utf8'");
    $query=mysql_query("SELECT * FROM `house` WHERE 1");
    $data=array();
    while($rt = mysql_fetch_array($query)){
    $data[]=$rt;
    }
    print_r($data);我的测试,文件的存储编码是utf-8
    mysql_query("set names 'gbk'");和mysql_query("set names 'utf8'");后插入的数据,不管之前set names什么编码,另一部分的编码始终都是乱码的。
      

  10.   

    记事本不能编辑UTF-8?
    估计您是在用WIN98吧?
      

  11.   

    utf8不管什么编码,道理是一样的
      

  12.   

    set names 语言代码
    没有引号,我不知道你的mysql是什么版本,我的如加上引号就错了
      

  13.   

    差不多!
    所以我只远程在服务器上工作XP 的虽能编辑 utf-8 编码文件,但新建的文件保存为 utf-8 时就有 BOM 头了。估计你很喜欢
      

  14.   

    按楼主的方法,set name utf8 ,是为了建立与mysql 的通讯均为 utf 来通讯。但 mysql 仍然以 gbk 方式来存的。所以,我们插入,更新,查询出来的,都是 gbk 来的了,不存在 iconv 这个操作也可以。个人是这样认为的。
      

  15.   

    XP 的虽能编辑 utf-8 编码文件,但新建的文件保存为 utf-8 时就有 BOM 头了。估计你很喜欢
    ===================================这个至少不是全部,我最近一直用xp系统【就2台】,没这种情况
      

  16.   

    无忧的解决方案就是从文件到页面再到数据库统一使用UTF-8编码。免得哪天MySQL升级,PHP升级,Apache升级了处理方式和现在的不一样,那就抓瞎吧~~~~
      

  17.   


    我的是mysql-essential-5.1.45-win32,我一直都加了引号的,没有错啊。
    难道是版本不一样的原因??
      

  18.   

    你能解释下你是如何【向 gbk 编码的表中插入 utf-8 编码的数据】的吗?使用了 set name utf8?1 当向gbk 编码的表中插入 utf-8 编码,并且指定set names utf8的话,
      此时数据的流程大致是utf8->utf8->gbk(数据->处理编码->入库)
    2 取出数据的时候如果指定set names utf8的话,是没有问题的。gbk->utf8->页面
      但是你指定set names gbk的话,大致是gbk->gbk->页面 肯定是有乱码的如果在上述1中,插入并指定set names gbk的话 同时取出时set names gbk 是没问题的。插入取出的页面需皆为utf8编码。记事本完全可以编辑 utf-8,前提条件是不要把记事本的概念局限在windows提供记事本上  世界上有其他非常好用的记事本
      

  19.   


    ===================================
    "SET NAMES ''"//语言,加不加''都可     版本 5.1.30
      

  20.   

    有人能数一下mysql内部是怎么做的就好了
      

  21.   

    我认为你的测试是在phpmyadmin中进行的,所以你不可能得到正确的结论
      

  22.   

    是在页面的
    说的有误导 取出数据的页面是utf8的  有乱码  是gbk的话  没有乱码 恩 得出的结果与你的一样
      

  23.   

    确认下你的意思
    /***************************/
    对于一个编码为gbk的表:
    1 插入数据的时候:你的数据编码为a 那么插入之前set names a
    2 读出数据的时候:你的页面编码为b 那么select之前set names b
    做到以上两点 就可以实现无乱码  就算你插入的数据编码为a 读出的时候编码设为b 也依然可保证无乱码出现
    /***************************/
    不知道这样理解有没有偏差 另外 上述测试在两种编码之间进行的 比如表为默认的latin1  插入utf8 读出gbk是不是也适合上述规律 还需测试一下
      

  24.   

    涉及3种编码的话  有问题 (测试是 表为latin1 插入gbk 读出utf8)
      

  25.   

    同意楼主的观点,mysql表中的内容以gbk还是utf8格式存储的并不重要,重要的是当我们从mysql中存取数据时要告诉mysql我们使用的是什么编码。也就是设置好set names 编码另外附个网上找来的以十六进制查看字符串的函数:function binhex($str) {
    $hex = "";    
    $i = 0;    
    do {        
    $hex .= sprintf("%02x", ord($str{$i}));        
    $i++;    

    while ($i < strlen($str));    
    return $hex;
    }
      

  26.   

    latin1 是单字节编码,估计有点问题。不过 php168 在安装时建议编码是 latin1
    对于这个有何高论?!
      

  27.   

    本帖最后由 xuzuning 于 2010-08-07 18:13:53 编辑
      

  28.   

    前段时间我也发现一个非常奇怪的问题,就是MYSQL用的都是UTF8,页面用的也是UTF8,但为了避免乱码的问题,我还是加上了set names 'utf-8',这下问题就来了,乱码,百思不得其解,编码都是一样的,为什么会乱码呢,搞了好久,于是死马当活马医,把set names 'utf-8'改成set names 'utf8',怪了,又好了,所以顺便也想问一下各位,难道"utf8"与"utf-8"这两种不同的写法造成的处理方式还会不同??
      

  29.   

    假如,有一天,你的数据库要和别的应用程序共享数据,
    那程序默认了utf-8,当调用你的数据时发现是gbk怎么办? 那么,默认情况下该程序就可能不正常显示你的数据了,
    好比,你做好的作品给用户,而这些用户通常是白痴(对于计算机来说),
    他们不懂设置这个那个,甚至也是根本看不明白后台管理的术语。下面举两个例子:再假设,我写程序时,都标了英文注解(utf-8),
    当我有天心血来潮时突然要发布到sourceforge或code.google,
    如果当时我用中文注解(gbk),那岂不是又要重新一次?其实,平时我们尽都可以说家乡话(gbk),但为什么还要说普通话(utf-8)来交流,
    但习惯了家乡话的人上网时会说一些别人看不明的术语。人类有人类的语言,机械有机械的语言,我们选择统一的语言是为了更好的交流,
    但这个统一需要平时的习惯来作支撑。
    ------ 卑人浅见,多谢指教
      

  30.   

    你可以用任何编码,只要mysql支持的,
    关键你用这种编码存储时,当调用那一方也要支持,但调用的程序目前可能是自己,但当别人来调用时,
    别人也是否支持这种编码格式的数据呢?
    我想这个原理大概和Web Service一样,如果不用统一的协议,很难说是什么结论。
      

  31.   


    也正是这个原因,所以你用你的 utf-8 程序访问我的 gbk 数据库时只要声明一下 set names utf8 ,于是我的数据库就以 utf-8 编码向你提供数据;而我的 gbk 程序要从你的 utf8 数据库得到数据,也只需通知你的数据库 set names gbk 我需要 gbk 编码的数据如果仅仅是为了所谓的“统一”,那么为什么不统一到 gbk 下呢?你如何知道中国标准不会成为世界标准呢
      

  32.   

    set names utf8有3个过程
    ---------------------------------------------
    set character_set_client utf8; #通知mysql,客户端发送的是utf-8编码数据
    set character_set_connection utf8 ;#客户端编码与存储引擎连接校对
    set character_set_results utf8 ; #从存储引擎得到的数据转成utf8返回给客户端mysql帮我们完成了转换过程,不管是客户端gbk访问utf-8数据库,还是utf-8客户端访问gbk数据库,都没问题。
    统一编码是为了系统的多语言性,移植性。
    gbk的页面读其它语言的数据就肯定错了。
    gbk要成为世界标准,最起码先得支持世界各国文字,编码区得扩充到和unicode一样。
      

  33.   

    唠叨, 27楼, 38楼说的都是对的。mysql的转换过程就是
    存入时:character_set_client =〉 
             character_set_connection =〉
               character_set_database(table/column )取出时:character_set_database(table/column ) =〉
              character_set_connection  =〉 
                 character_set_results这个转换中,字符集必须相容(能一一对应当然最好),如果有latin1这样字符数很少的字符集,转换后必然会有字符丢失。我以前回复的帖子里有解释得更详细的,可以搜索到。
      

  34.   

    本人用phpmyadmin经常乱码,不知道是不是mysql的问题
      

  35.   


    mysql里只有utf8,没有utf-8的编码名字
      

  36.   

    我从数据库输出的时候是
    $con=@mysql_connect("localhost","root","123") or die("数据库无法连接");
    $db=@mysql_select_db("my") or die("库无法连接");
    header("Content-Type:text/html;charset=utf-8");
    执行updata 语句的时候是
    $con=@mysql_connect("localhost","root","123") or die("数据库无法连接");
    $db=@mysql_select_db("my") or die("库无法连接");
    mysql_query("set names GB2312");
    这样不会有乱码 可是要是同一个网页同时执行这两个操作就乱了。怎么办?都说要统一编码 可是怎么把所有的编码都设置统一啊
      

  37.   

    汗,做PHP的谁不知道这个,居然跑论坛来发这个!
      

  38.   

    <?php
        header("Content-type:text/html;Charset=UTF-8;");
        $link=mysql_connect("localhost","root","123456") or die("无法连接服务!");
        mysql_select_db("codegbk",$link) or die("数据库无法选择");
        mysql_query("set names utf8");
        $rs = mysql_query("select *from user",$link);
        
         $sql = "insert into user values(default,'测试乱码')";
         mysql_query($sql);
        while($row = mysql_fetch_array($rs)){
        echo $row["username"]."<br/>";
        }
    ?>
    经过几次乱码的测试,只要在插入数据时候 set names 这个编码与页面的编码统一,而与数据库的编码无关系。在读数据的时候set names 这个编码与页面编码统一,也就相当与 set names 是告诉mysql 我要读取和存储什么样的编码数据。现在页面一直未出现问题.