mysql 中文亂碼 解決方法集錦
更新時間:2009年06月14日 18:22:16 作者:
主要是針對 1.4x版本的一些亂碼問題,其實新版本中錯誤也差不多,大家注意下編碼問題。
第一個方法:
MySQL 4.1 中文亂碼的問題
最近要將 MySQL 4.0 升級到 MySQL 4.1 ,發(fā)現(xiàn)了中文亂碼的問題,希望以下見解對大家有用。
1. MySQL 4.1 在文字上有很大改進,它有了 Character Set 與 Collation 的慨念。
2. 在 MySQL 4.0 ,一般的程式都會將文字以拉丁文 ( latin) 來儲存,就算我們輸入中文字,結(jié)果仍是放在以拉丁文設(shè)置的文字欄里頭,這對 MySQL 4.0 與以 MySQL 4.0 為基楚的程式來說,并不會有問題。
3. 可是 MySQL 4.1 的系統(tǒng)編碼是預(yù)設(shè)用 UTF-8 的,當要 restore MySQL 4.0 的 backup 檔到 MySQL 4.1 時,亂碼就出現(xiàn)了。原因在于 MySQL 4.1 將 latin 碼轉(zhuǎn)換過來,而后轉(zhuǎn)換是并不完全完美的,這導(dǎo)致了出現(xiàn)少量文字出現(xiàn)亂碼現(xiàn)象。
解決PHP存取MySQL 4.1亂碼問題
QUOTE:
從MySQL 4.1開始引入的多語言支持確實很棒,而且一些特性已經(jīng)超過了其他的數(shù)據(jù)庫系統(tǒng)。不過我在測試過程中發(fā)現(xiàn)使用適用于MySQL 4.1之前的PHP語句操作MySQL數(shù)據(jù)庫會造成亂碼,即使是設(shè)置過了表字符集也是如此。我讀了一下新的MySQL在線手冊中第十章 "Character Set Support"后終于找到了解決方法并測試通過。
MySQL 4.1的字符集支持(Character Set Support)有兩個方面:字符集(Character set)和排序方式(Collation)。對于字符集的支持細化到四個層次: 服務(wù)器(server),數(shù)據(jù)庫(database),數(shù)據(jù)表(table)和連接(connection)。
查看系統(tǒng)的字符集和排序方式的設(shè)定可以通過下面的兩條命令:
CODE:
mysql> SHOW VARIABLES LIKE 'character_set_%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
7 rows in set (0.00 sec)
mysql> SHOW VARIABLES LIKE 'collation_%';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
| collation_database | latin1_swedish_ci |
| collation_server | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.00 sec)
上面列出的值就是系統(tǒng)的默認值。如果你奇怪系統(tǒng)怎么默認是latin1的瑞典語排序方式,原因是MySQL由瑞典的T.c.X.DataKonsultAB公司(目前公司名稱為MySQL AB)開發(fā),不用再多說了吧。
當我們按照原來的方式通過PHP存取MySQL數(shù)據(jù)庫時,就算設(shè)置了表的默認字符集為utf8并且通過UTF-8編碼發(fā)送查詢,你會發(fā)現(xiàn)存入數(shù)據(jù)庫的仍然是亂碼。問題就出在這個connection連接層上。解決方法是在發(fā)送查詢前執(zhí)行一下下面這句:
SET NAMES 'utf8';
它相當于下面的三句指令:
CODE:
SET character_set_client = utf8;
SET character_set_results = utf8;
SET character_set_connection = utf8;
再試試看,正常了吧?
就是連接之后加個查詢
CODE:
$this->query(”SET NAMES ‘utf8'”);
看了手冊第10章覺得主要還是Character Sets的問題。
character_set_client,character_set_results,character_set_connection三個運行變量是造成亂碼的關(guān)鍵。mysql把客戶端提交的查詢由character_set_client轉(zhuǎn)換為character_set_connection
,由于默認網(wǎng)頁提交的查詢是gb2312(表單頁面meta里可以看到),而mysql默認將其當作utf8(可以查到此時的 character_set_client=utf8),所以必然亂碼。同理,mysql返回的結(jié)果是已經(jīng)轉(zhuǎn)換成 character_set_results編碼的(與表的編碼無關(guān)),同樣默認是utf8,而網(wǎng)頁頁面把它當gb2312處理,所以必然有標題等由數(shù)據(jù)庫讀出的字段是亂碼而其他部門文字不亂碼的現(xiàn)象。
以上這個例子是utf8字符集,用此方法,設(shè)置為gbk,即可解決
第三個方法:
mysql 4.1亂碼終極解決方案
請注意,本文只針對mysql 4.1,其它版本的mysql請看別的文章。
mysql4.1是比較煩人,支持多語言的細化設(shè)置,再加上phpmyadmin2.6也比較笨,默認就是改不動的utf8,怎么弄都亂碼。
好了,廢話少說,我們來一步步解決這個問題:
1.修改/etc/my.cnf文件,改成這樣:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
default-character-set=utf8
[mysql.server]
user=mysql
basedir=/var/lib
[mysqld_safe]
err-log=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
注意:就是加入了一句default-character-set=utf8。
2./etc/init.d/mysqld restart 重新啟動mysql;
3.打開phpmyadmin,選擇lang為"Chines simplifies(zh-utf-8)",選擇"MySQL 連接校對"為"utf8_general_ci "點“顯示 MySQL 的運行信息”--“變量”,可以看到:
character set client utf8 utf8
character set connection utf8 utf8
character set database utf8 utf8
character set results utf8 utf8
character set server utf8 utf8
character set system utf8 utf8
collation connection utf8_general_ci utf8_general_ci
collation database utf8_general_ci utf8_general_ci
collation server utf8_general_ci utf8_general_ci
從這里可以看到character全部變成utf8了。
有人要問,為什么都要改成utf8呢?改成GB2312不行嗎?
解釋如下:
我也不想改成utf8,只是phpmyadmin2.6在mysql4.1的時候只會用utf8,連其他頁面的charset也都是utf8,改成gb2312一定會亂碼,我們只能湊phpmyadmin了。
只有在mysql3.23的時候,phpmyadmin才會多一個gb2312的頁面charset,這時候是正常的。
3.將以前的mysql3的庫文件導(dǎo)入mysql4.1的庫
有兩種情況:
一是從phpmyadmin上導(dǎo)入,這時候你要注意的是在選擇庫文件的頁面左下腳有個“文件的字符集:”,默認是utf8,要改成gb2312,否則導(dǎo)進去亂碼;
二是在linux下導(dǎo)入,這時候你需要先在庫文件的頭部加一行:
SET NAMES 'gb2312'; 注意最后也是;號,別漏了。
然后執(zhí)行mysql -u用戶名 -p密碼 xxx.sql > 庫名
導(dǎo)入完成以后再用phpmyadmin打開看,里面的中文字就是正確的。
4.從mysql4.1里導(dǎo)出庫文件
一.用phpmyadmin導(dǎo)出
導(dǎo)出倒是問題不大,如果phpmyadmin的瀏覽頁面里顯示的中文是正常的,那么導(dǎo)出肯定也是正常的
二.在linux上導(dǎo)出
如果用mysqldump導(dǎo)出出現(xiàn)了亂碼也沒有關(guān)系,可以運行iconv來轉(zhuǎn)換一下
iconv -c -f UTF-8 -t GB2312 庫文件名 > 新的gb2312的庫文件名
綜上所述,你要注意:
1。盡量在需要導(dǎo)入的庫文件的開頭加入SET NAMES 'gb2312';告訴mysql你要導(dǎo)入的是一個gb2312的文件;
2??赡苣阈枰@個:
SET NAMES 'utf8';
在登陸到mysql后用,把character的一些默認參數(shù)改到utf8上,有時可以減少一些困擾,不過也不是必須的。
在mysql上使用:
SHOW VARIABLES LIKE 'character_set_%';
用來查看當前的狀態(tài)。
3.如果出現(xiàn)亂碼也不要怕,一是你要注意留存原有的備份,二是用iconv來進行轉(zhuǎn)化。
在正常使用之前注意做導(dǎo)入導(dǎo)出的測試,確保萬無一失。
下面再說明一下,網(wǎng)上很多朋友說Mysql4.1的只能升,不能降. 這是不正確的. 同樣使用mysqldump 導(dǎo)出數(shù)據(jù)庫時加一個 --compatible 的參數(shù).也千萬不能忘了--default-character-set=這個設(shè)定字符集的參數(shù).
示范: mysqldump -uroot -pPassword --compatible=mysql40 --default-character-set=gb2312 discuz>d:discuz.sql
ok 這樣導(dǎo)出來的文件,就可以在Mysql4.0.X和Mysql.3.2.X版本中使用了.
Linux下 Mysql 5 中文亂碼的徹底解決及應(yīng)用的一些注意事項
一. 自從mysql4.1開始,mysql對中文的支持問題是比較煩人的,怎么弄都亂碼,如今mysql5 據(jù)說是mysql的新紀元,但從官方下載安裝的mysql5仍存在亂碼現(xiàn)象,這里就是針對此現(xiàn)象做的討論:
建議最好是下載mysql的源碼進行編譯,這是由于官方編譯的mysql的默認支持編碼是latin字符集,所以中文字符在數(shù)據(jù)庫里查看的時候看到的是亂碼。編譯MySQL時使用withcharset=編碼,可以方便地把mysql編譯成該編碼形式,這樣MySQL就會直接支持中文查找和排序,-- with-extra-charsets參數(shù)指定其它可用的字符集。
下載并解壓源碼包,打開INSTALL-SOURCE,這里介紹了linux下詳細的安裝方法,所以大家所要注意的只是下面的configure指令:
groupadd mysql
useradd -g mysql mysql
./configure --with-charset=gbk --with-collation=gbk_chinese_ci --with-extra-charsets=gb2312,big5,utf8,binary,ascii --prefix=/usr/local/mysql
make
make install
cp support-files/my-medium.cnf /etc/my.cnf
cd /usr/local/mysql
bin/mysql_install_db --user=mysql
chown -R root .
chown -R mysql var
chgrp -R mysql .
bin/mysqld_safe --user=mysql &
bin/mysql
mysql> show variables;
你可以看到全局的字符集參數(shù)全是gbk,gb2312字集應(yīng)該包含在gbk里,所以不討論。
進行和平常mysql4.0一樣的php操作,你會發(fā)現(xiàn)仍然出現(xiàn)中文亂碼現(xiàn)象。
這里要說明的是:從mysql 4.1開始,必需在mysql數(shù)據(jù)庫連接后對應(yīng)用的字符集做出說明,否則非英文字母的文字存取都無法解釋變成?號。
解決方法就是要適應(yīng)新版mysql的要求:
在連接mysql數(shù)據(jù)庫后執(zhí)行set character set 字符集,該指令在最新版的mysql 5如果默認字集和存儲相符可以免設(shè):
set character set gbk;
在php里應(yīng)該是這么寫:mysql_query("set character set gbk");
指令大小寫均可
phpwind和discuz是廣泛應(yīng)用的國產(chǎn)php論壇,大量的朋友在應(yīng)用它,了解了以上步驟,你也可以對論壇源碼進行很小的修改,安全地把數(shù)據(jù)庫升級到mysql5:
找到include/db_mysql.php,修改function connect(...){.....}
在選擇數(shù)據(jù)庫mysql_select_db($dbname);后面加上一句mysql_query('set character set gbk');存盤。
二. 文件的導(dǎo)入導(dǎo)出:如果存入非gbk字符,這時候你需要先在導(dǎo)入文件的頭部加一行: SET NAMES '字符集'; 并注意最后也是;號,別漏了。
文件導(dǎo)入和導(dǎo)出執(zhí)行
mysql -u用戶名 -p密碼 數(shù)據(jù)庫名
mysqldump -u用戶名 -p密碼 數(shù)據(jù)庫名>data.sql
如果用mysqldump導(dǎo)出數(shù)據(jù)出現(xiàn)了亂碼也沒有關(guān)系,可以運行iconv來轉(zhuǎn)換一下:
iconv -c -f utf8 -t gbk 庫文件名>新的gbk的庫文件名
綜上所述,你要注意:
1。盡量在需要導(dǎo)入的庫文件的開頭加入set names 'gbk';告訴mysql你要導(dǎo)入的是一個gbk的文件;
2。在mysql上使用 show variables;或show variables like 'character_set_%'; 用來查看當前的字集狀態(tài)。
3。如果出現(xiàn)亂碼也不要怕,其一是你要注意留存原有的備份,其二是用iconv來進行轉(zhuǎn)化。
#PHP連接問題:
由于MySQL 4.1版本開始密碼的hash算法改變,所以連接數(shù)據(jù)庫時可能會出現(xiàn)Client does not support authentication protocol問題
此問題在mysql 5中不存在,mysql 5不需要以下的設(shè)置。
可以通過一下兩種方法解決數(shù)據(jù)庫用戶密碼不符問題:
其一: mysql> SET PASSWORD FOR 'some_user'@'some_host' = OLD_PASSWORD('newpwd');
其二: mysql> Update mysql.user SET Password = OLD_PASSWORD('newpwd') Where Host = 'some_host' AND User = 'some_user'
PHP輸出的其它亂碼問題:
如果將mysql編譯為默認編碼gbk的話,又會造成非gbk數(shù)據(jù)直接導(dǎo)入顯示為亂碼,比如部份utf8存儲的字符,如果你大部份數(shù)據(jù)是utf8字集,當然得把mysql編譯為默認編碼utf8才合適。
Mysql 4.1.x出來以后,引入了collation (校勘)的概念,終于有辦法讓mysql同時支持多種編碼的數(shù)據(jù)庫了,所以PHP要用以下SQL語句來創(chuàng)建utf-8編碼的數(shù)據(jù)庫:
Create DATABASE `mytest` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
但是僅僅是將數(shù)據(jù)庫的??备臑閡tf-8是不夠的,還必須在連接了mysql數(shù)據(jù)庫之后用這個語句來設(shè)置:set names 'utf8';才能在php程序里得到正確編碼的字符,并將其顯示在web頁面里。
mysql_query("set names 'utf8'",$connection);
下面再說明一下,網(wǎng)上很多朋友說Mysql4.1的只能升,不能降. 這是不正確的. 同樣使用mysqldump 導(dǎo)出數(shù)據(jù)庫時加一個 --compatible 的參數(shù).也千萬不能忘了--default-character-set=這個設(shè)定字符集的參數(shù)。
示范: mysqldump -uroot -pPassword --compatible=mysql40 --default-character-set=gb2312 discuz>d:discuz.sql
ok 這樣導(dǎo)出來的文件,就可以在Mysql4.0.X和Mysql.3.2.X版本中使用了.
下面要寫的是一篇非常無聊的東西,充斥了大量各式各樣的編碼、轉(zhuǎn)換、客戶端、服務(wù)器端、連接……呃,我自己都不愿意去看它,但想一想,寫下來還是有點意義的,原因有四:
MySQL 4.1 對多語言的支持有了很大變化 (這導(dǎo)致了問題的出現(xiàn));
盡管大部分的地方 (包括個人使用和主機提供商),MySQL 3 仍然占主導(dǎo)地位;但 MySQL 4.1 是 MySQL 官方推薦的數(shù)據(jù)庫,已經(jīng)有主機提供商開始提供并將會越來越多;
許多 PHP 程序以 MySQL 作為默認的數(shù)據(jù)庫管理軟件,但它們一般不區(qū)分 MySQL 4.1 與 4.1 以下版本的區(qū)別,籠統(tǒng)地稱“MySQL 3.xx.xx 以上版本”就滿足安裝需求了;
因為 latin1 在許多地方 (下邊會詳細描述具體是哪些地方) 作為默認的字符集,成功的蒙蔽了許多 PHP 程序的開發(fā)者和用戶,掩蓋了在中文等語言環(huán)境下會出現(xiàn)的問題;
簡單的說,MySQL 自身的變化和使用 MySQL 的 PHP 程序?qū)Υ撕雎裕瑢?dǎo)致了問題的出現(xiàn)和復(fù)雜化,而由于大部分用戶使用的是英文,使這種問題不被重視。這里提到的 PHP 程序,主要就 WordPress 而言。
MySQL 4.1 字符集支持的原理MySQL 4.1 對于字符集的指定可以細化到一臺機器上安裝的 MySQL,其中的一個數(shù)據(jù)庫,其中的一張表,其中的一欄,應(yīng)該用什么字符集。但是,傳統(tǒng)的 Web 程序在創(chuàng)建數(shù)據(jù)庫和數(shù)據(jù)表時并沒有使用那么復(fù)雜的配置,它們用的是默認的配置,那么,默認的配置從何而來呢?
編譯 MySQL 時,指定了一個默認的字符集,這個字符集是 latin1;
安裝 MySQL 時,可以在配置文件 (my.ini) 中指定一個默認的的字符集,如果沒指定,這個值繼承自編譯時指定的;
啟動 mysqld 時,可以在命令行參數(shù)中指定一個默認的的字符集,如果沒指定,這個值繼承自配置文件中的;
此時 character_set_server 被設(shè)定為這個默認的字符集;
當創(chuàng)建一個新的數(shù)據(jù)庫時,除非明確指定,這個數(shù)據(jù)庫的字符集被缺省設(shè)定為 character_set_server;
當選定了一個數(shù)據(jù)庫時,character_set_database 被設(shè)定為這個數(shù)據(jù)庫默認的字符集;
在這個數(shù)據(jù)庫里創(chuàng)建一張表時,表默認的字符集被設(shè)定為 character_set_database,也就是這個數(shù)據(jù)庫默認的字符集;
當在表內(nèi)設(shè)置一欄時,除非明確指定,否則此欄缺省的字符集就是表默認的字符集;
這個字符集就是數(shù)據(jù)庫中實際存儲數(shù)據(jù)采用的字符集,mysqldump 出來的內(nèi)容就是這個字符集下的;
簡單的總結(jié)一下,如果什么地方都不修改,那么所有的數(shù)據(jù)庫的所有表的所有欄位的都用 latin1 存儲,不過我們?nèi)绻惭b MySQL,一般都會選擇多語言支持,也就是說,安裝程序會自動在配置文件中把 default_character_set 設(shè)置為 UTF-8,這保證了缺省情況下,所有的數(shù)據(jù)庫的所有表的所有欄位的都用 UTF-8 存儲。
當一個 PHP 程序與 MySQL 建立連接后,這個程序發(fā)送給 MySQL 的數(shù)據(jù)采用的是什么字符集?MySQL 無從得知 (它最多只能猜測),所以 MySQL 4.1 要求客戶端必須指定這個字符集,也就是 character_set_client,MySQL 的怪異之處在于,得到的這個字符集并不立即轉(zhuǎn)換為存儲在數(shù)據(jù)庫中的那個字符集,而是先轉(zhuǎn)換為 character_set_connection 變量指定的一個字符集;這個 connection 層究竟有什么用我不大明白,但轉(zhuǎn)換為 character_set_connection 的這個字符集之后,還要轉(zhuǎn)換為數(shù)據(jù)庫默認的字符集,也就是說要經(jīng)過兩次轉(zhuǎn)換;當這個數(shù)據(jù)被輸出時,又要由數(shù)據(jù)庫默認的字符集轉(zhuǎn)換為 character_set_results 指定的字符集。
一個典型的環(huán)境典型的環(huán)境以我自己的電腦上安裝的 MySQL 4.1 為例,我自己的電腦上安裝著 Apache 2,PHP 5 和 WordPress 1.5.1.3,MySQL 配置文件中指定了 default_character_set 為 utf8。于是問題出現(xiàn)了:
WordPress 按照默認情況安裝,所以所有的表都用 UTF-8 存儲數(shù)據(jù);
WordPress 默認采用的瀏覽字符集是 UTF-8 (Options->Reading 中設(shè)置),因此所有 WP 頁面的 meta 中會說明 charset 是 utf-8;
所以瀏覽器會以 utf-8 方式顯示所有的 WP 頁面;這樣一來 Write 的所有 Post,和 Comment 都會以 UTF-8 格式從瀏覽器發(fā)送給 Apache,再由 Apache 交給 PHP;
所以 WP 從所有的表單中得到的數(shù)據(jù)都是 utf-8 編碼的;WP 不加轉(zhuǎn)換的直接把這些數(shù)據(jù)發(fā)送給 MySQL;
MySQL 默認設(shè)置的 character_set_client 和 character_set_connection 都是 latin1,此時怪異的事情發(fā)生了,實際上是 utf-8 格式的數(shù)據(jù),被“當作 latin1”轉(zhuǎn)換成……居然還是轉(zhuǎn)換成 latin1,然后再由這個 latin1 轉(zhuǎn)換成 utf-8,這么兩次轉(zhuǎn)換,有一部分 utf-8 的字符就丟失了,變成 ??,最后輸出的時候 character_set_results 默認是 latin1,也就輸出為奇怪的東西了。
最神奇的還不是這個,如果 WordPress 中設(shè)置以 GB2312 格式閱讀,那么 WP 發(fā)送給 MySQL 的 GB2312 編碼的數(shù)據(jù),被“當作 latin1”轉(zhuǎn)換后,存進數(shù)據(jù)庫的是一種奇怪的格式 (真的是奇怪的格式,mysqldump 出來就能發(fā)現(xiàn),無論當作 utf-8 還是當作 gb2312 來讀都是亂碼),但如果這種格式以 latin1 輸出出來,居然又能變回 GB2312!
這會導(dǎo)致什么現(xiàn)象呢?WP 如果使用 MySQL 4.1 數(shù)據(jù)庫,把編碼改用 GB2312 就正常了,可惜,這種正常只是貌似正常。
如何解決問題如果你已經(jīng)不耐煩了 (幾乎是肯定的),google 一下,會發(fā)現(xiàn)絕大部分的解答是,query 之前先執(zhí)行一下:SET NAMES 'utf8',沒錯,這是解決方案,但本文的目的是說明,這為什么是解決方案。
要保證結(jié)果正確,必須保證數(shù)據(jù)表采用的格式是正確的,也就是說,至少能夠存放所有的漢字,那么我們只有兩種選擇,gbk 或者 utf-8,下面討論 utf-8 的情況。
因為配置文件設(shè)置的 default_character_set 是 utf8,數(shù)據(jù)表默認采用的就是 utf-8 建立的。這也應(yīng)該是所有采用 MySQL 4.1 的主機提供商應(yīng)該采用的配置。所以我們要保證的只是客戶端與 MySQL 交互之間指定編碼的正確。
這只有兩種可能,客戶端以 gb2312 格式發(fā)送數(shù)據(jù),或者以 utf-8 格式發(fā)送數(shù)據(jù)。
如果以 gb2312 格式發(fā)送:
SET character_set_client='gb2312'
SET character_set_connection='utf8' 或者
SET character_set_connection='gb2312'
都是可以的,都能夠保證數(shù)據(jù)在編碼轉(zhuǎn)換中不出現(xiàn)丟失,也就是保證存儲入數(shù)據(jù)庫的是正確的內(nèi)容。
怎么保證取出的是正確的內(nèi)容呢?考慮到絕大部分客戶端 (包括 WP),發(fā)送數(shù)據(jù)的編碼也就是它所希望收到數(shù)據(jù)的編碼,所以:
SET character_set_results='gb2312'
可以保證取出給瀏覽器顯示的格式就是 gb2312。
如果是第二種情況,客戶端以 utf-8 格式發(fā)送 (WP 的默認情況),可以采用下述配置:
SET character_set_client='utf8'
SET character_set_connection='utf8'
SET character_set_results='utf8'
這個配置就等價于 SET NAMES 'utf8'。
WP 應(yīng)該作什么修改還是那句話,客戶端要發(fā)給數(shù)據(jù)庫什么編碼的數(shù)據(jù),數(shù)據(jù)庫是不可能確切知道的,只能讓客戶端自己說明白,所以,WP 是必須發(fā)送正確的 SET... 給 MySQL 的。怎么發(fā)送最合適呢?臺灣的 pLog 同仁給出了一些建議:
首先,測試服務(wù)器是否 >= 4.1,編譯時是否加入了 UTF-8 支持;是則繼續(xù)
然后測試數(shù)據(jù)庫以什么格式存儲 ($dbEncoding);
SET NAMES $dbEncoding
對于第二點,WP 的情況是不同的,按照上面的典型配置,只要用 WP,肯定數(shù)據(jù)庫是用 UTF-8 存儲的,所以要根據(jù)用戶設(shè)置的以 GB2312 還是 UTF-8 瀏覽來判斷 (bloginfo('charset')),但這個值是要連接數(shù)據(jù)庫以后才能得到的,所以效率最高的方式是連接數(shù)據(jù)庫之后,根據(jù)這個配置設(shè)置一次 SET NAMES,而不必每次查詢之前都設(shè)置一遍。
我的修改方式是這樣的,在 wp_includes/wp-db.php 中增加:
function set_charset($charset)
{
// check mysql version first.
$serverVersion = mysql_get_server_info($this->dbh);
$version = explode('.', $serverVersion);
if ($version[0] < 4) return;
// check if utf8 support was compiled in
$result = mysql_query("SHOW CHARACTER SET like 'utf8'",
$this->dbh);
if (mysql_num_rows($result) < = 0) return;
if ($charset == 'utf-8' || $charset == 'UTF-8')
$charset = 'utf8';
@mysql_query("SET NAMES '$charset'", $this->dbh);
}
在 wp-settings.php 的 require (ABSPATH . WPINC . '/vars.php'); 后增加:
$wpdb->set_charset(get_bloginfo('charset'));
1. MySQL 4.1 在文字上有很大改進,它有了 Character Set 與 Collation 的慨念。
2. 在 MySQL 4.0 ,一般的程式都會將文字以拉丁文 ( latin) 來儲存,就算我們輸入中文字,結(jié)果仍是放在以拉丁文設(shè)置的文字欄里頭,這對 MySQL 4.0 與以 MySQL 4.0 為基楚的程式來說,并不會有問題。
3. 可是 MySQL 4.1 的系統(tǒng)編碼是預(yù)設(shè)用 UTF-8 的,當要 restore MySQL 4.0 的 backup 檔到 MySQL 4.1 時,亂碼就出現(xiàn)了。原因在于 MySQL 4.1 將 latin 碼轉(zhuǎn)換過來,而后轉(zhuǎn)換是并不完全完美的,這導(dǎo)致了出現(xiàn)少量文字出現(xiàn)亂碼現(xiàn)象。
4. 要解決這亂碼問題并不難。首先,在 MySQL 4.0 備份時,先將所有文字欄變成 binary 類型,然后進行正常備份。第二步,可在 MySQL 4.1 里將剛才的備份 restore。最后,將較早前所變更到 binay 類型的文字欄,再次復(fù)原到文字類型。這樣中文編碼的問題就應(yīng)該可以完全解決。
5. 將文字欄變更到 binay 類型時,必需設(shè)定 binary 欄的長度大過或等于 (>=) 文字欄的長度,否則資料會失去。
6. 另外,經(jīng)這樣升級的 MySQL 數(shù)據(jù)庫,在 MySQL 4.1 里將會正常工作,就算是怎樣 backup 與 restore 都不會再有亂碼問題。
作者: MySQL 發(fā)布日期: 2005-12-14
mysql4.1是比較煩人,支持多語言的細化設(shè)置,再加上phpmyadmin2.6也比較笨,默認就是改不動的utf8,怎么弄都亂碼。
好了,廢話少說,我們來一步步解決這個問題:
1.修改/etc/my.cnf文件,改成這樣:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
default-character-set=utf8
[mysql.server]
user=mysql
basedir=/var/lib
[mysqld_safe]
err-log=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
注意:就是加入了一句default-character-set=utf8。
2./etc/init.d/mysqld restart 重新啟動mysql;
3.打開phpmyadmin,選擇lang為"Chines simplifies(zh-utf-8)",選擇"MySQL 連接校對"為"utf8_general_ci "點“顯示 MySQL 的運行信息”--“變量”,可以看到:
character set client utf8 utf8
character set connection utf8 utf8
character set database utf8 utf8
character set results utf8 utf8
character set server utf8 utf8
character set system utf8 utf8
collation connection utf8_general_ci utf8_general_ci
collation database utf8_general_ci utf8_general_ci
collation server utf8_general_ci utf8_general_ci
從這里可以看到character全部變成utf8了。
有人要問,為什么都要改成utf8呢?改成GB2312不行嗎?
解釋如下:
我也不想改成utf8,只是phpmyadmin2.6在mysql4.1的時候只會用utf8,連其他頁面的charset也都是utf8,改成gb2312一定會亂碼,我們只能湊phpmyadmin了。
只有在mysql3.23的時候,phpmyadmin才會多一個gb2312的頁面charset,這時候是正常的。
3.將以前的mysql3的庫文件導(dǎo)入mysql4.1的庫
有兩種情況:
一是從phpmyadmin上導(dǎo)入,這時候你要注意的是在選擇庫文件的頁面左下腳有個“文件的字符集:”,默認是utf8,要改成gb2312,否則導(dǎo)進去亂碼;
二是在linux下導(dǎo)入,這時候你需要先在庫文件的頭部加一行:
SET NAMES 'gb2312'; 注意最后也是;號,別漏了。
然后執(zhí)行mysql -u用戶名 -p密碼 xxx.sql > 庫名
導(dǎo)入完成以后再用phpmyadmin打開看,里面的中文字就是正確的。
4.從mysql4.1里導(dǎo)出庫文件
一.用phpmyadmin導(dǎo)出
導(dǎo)出倒是問題不大,如果phpmyadmin的瀏覽頁面里顯示的中文是正常的,那么導(dǎo)出肯定也是正常的
二.在linux上導(dǎo)出
如果用mysqldump導(dǎo)出出現(xiàn)了亂碼也沒有關(guān)系,可以運行iconv來轉(zhuǎn)換一下
iconv -c -f UTF-8 -t GB2312 庫文件名 > 新的gb2312的庫文件名
綜上所述,你要注意:
1。盡量在需要導(dǎo)入的庫文件的開頭加入SET NAMES 'gb2312';告訴mysql你要導(dǎo)入的是一個gb2312的文件;
2??赡苣阈枰@個:
SET NAMES 'utf8';
在登陸到mysql后用,把character的一些默認參數(shù)改到utf8上,有時可以減少一些困擾,不過也不是必須的。
在mysql上使用:
SHOW VARIABLES LIKE 'character_set_%';
用來查看當前的狀態(tài)。
3.如果出現(xiàn)亂碼也不要怕,一是你要注意留存原有的備份,二是用iconv來進行轉(zhuǎn)化。
在正常使用之前注意做導(dǎo)入導(dǎo)出的測試,確保萬無一失。
我升級了MYSQL到4.1.2,phpmyadmin用的是2.6.2。數(shù)據(jù)表里面有中文的字段中文都變成了亂碼,導(dǎo)出數(shù)據(jù)也是亂碼。我用以前的2.5.7沒有問題,想問一下,應(yīng)該在phpmyadmin的那個文件里改哪個設(shè)置一下才能顯示出來的是正常的中文字?
和字符相關(guān)的變量中這幾個和sql很有關(guān)系:
character_set_client
character_set_connection
character_set_results
此外就是數(shù)據(jù)庫中對相應(yīng)字段設(shè)置的charact set,如果沒有對字段設(shè)置,缺省是table的charact set,table也沒有指定則缺省使用database的。
上面3個變量的作用是這樣的,client表示客戶端發(fā)送過來的字符集,results表示發(fā)送到客戶端的字符集(這兩個分開是因為發(fā)送過來和發(fā)送過去的不一定是同一個客戶端),connection則在客戶端和數(shù)據(jù)庫起一個連接作用。
具體是這樣:比如我在mysql命令行設(shè)置client為gbk,connection為utf8,results為gbk,數(shù)據(jù)庫為big5,
當我發(fā)送一個insert語句的時候,這個語句作為gbk代碼,先轉(zhuǎn)為utf8代碼(connection),再轉(zhuǎn)為big5(database)插入數(shù)據(jù)庫。
而運行一個select語句的時候,從數(shù)據(jù)庫得到的結(jié)果則相反的過程,由big5轉(zhuǎn)為utf8,再轉(zhuǎn)為gbk,你得到gbk的結(jié)果。
因此最主要的是讓client和results和你使用的客戶端一致。比如你的網(wǎng)頁是utf8編碼,你就要設(shè)置這兩個為utf8。
而在mysql命令行的時候,我用的是2000,需要設(shè)置為gbk
而我們用的set names XXX,實際上就是同時設(shè)置這3個變量為XXX。
在這樣的情況下,我們可以把一個數(shù)據(jù)庫中的不同表或不同字段設(shè)為不同的字符集,只要上面3個設(shè)置正確,就可以在數(shù)據(jù)庫中同時使用不同的字符集。
注意要保證你的數(shù)據(jù)庫中的字符已經(jīng)使用了正確的字符集,比如如果一開始你設(shè)置錯誤,插入數(shù)據(jù)后,本身數(shù)據(jù)的編碼就是不正確的,然后即使設(shè)置改回來,也不可能得到正確的顯示了。
還有一個是編碼互相之間的兼容性,如果一個字符在gbk中有,在utf8中沒有,那么在gbk-》utf8-》gbk的過程中,它就變成了“?”
再說一下具體解決的辦法。
首先要指定你的升級后的database及table及field的character set,一般來說我們用gb2312或者utf8的,如果不同時使用多種編碼,只要指定database就可以,可以在建庫的sql語句加上相應(yīng)的 character set,在phpMyAdmin里也可以修改。
然后是導(dǎo)入舊數(shù)據(jù)。首先要確定自己的數(shù)據(jù)文件的編碼。如果用phpMyAdmin導(dǎo)入,在界面上有文件編碼的選項,一定要和數(shù)據(jù)文件的編碼一致。
如果從mysql的命令行導(dǎo)入,就要自己設(shè)置上面說到的3個變量,set names xxx。
使用其它的客戶端程序一樣要注意。
這樣就可以讓舊數(shù)據(jù)轉(zhuǎn)入新數(shù)據(jù)庫后的編碼才是正確的,如果這一步錯了,后面不可能得到正確的顯示。
然后是自己的程序,在連接后就可以執(zhí)行一次set names xxx,根據(jù)你的網(wǎng)頁編碼而定。
這樣基本就可以保證編碼正確了。
你很有可能是導(dǎo)入的數(shù)據(jù)編碼已經(jīng)不對了。
MYSQL數(shù)據(jù)庫默認語言為瑞典語, 現(xiàn)有一GB2312字符的數(shù)據(jù)庫.
結(jié)構(gòu)OK. 為什么內(nèi)容是亂碼? 不重裝數(shù)據(jù)庫有辦法解決碼?
從MySQL 4.1開始引入的多語言支持確實很棒,而且一些特性已經(jīng)超過了其他的數(shù)據(jù)庫系統(tǒng)。不過我在測試過程中發(fā)現(xiàn)使用適用于MySQL 4.1之前的PHP語句操作MySQL數(shù)據(jù)庫會造成亂碼,即使是設(shè)置過了表字符集也是如此。我讀了一下新的MySQL在線手冊中第十章 "Character Set Support"后終于找到了解決方法并測試通過。
MySQL 4.1的字符集支持(Character Set Support)有兩個方面:字符集(Character set)和排序方式(Collation)。對于字符集的支持細化到四個層次: 服務(wù)器(server),數(shù)據(jù)庫(database),數(shù)據(jù)表(table)和連接(connection)。
查看系統(tǒng)的字符集和排序方式的設(shè)定可以通過下面的兩條命令:
mysql> SHOW VARIABLES LIKE 'character_set_%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
7 rows in set (0.00 sec)
mysql> SHOW VARIABLES LIKE 'collation_%';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
| collation_database | latin1_swedish_ci |
| collation_server | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.00 sec)
上面列出的值就是系統(tǒng)的默認值。(很奇怪系統(tǒng)怎么默認是latin1的瑞典語排序方式)...
當我們按照原來的方式通過PHP存取MySQL數(shù)據(jù)庫時,就算設(shè)置了表的默認字符集為utf8并且通過UTF-8編碼發(fā)送查詢,你會發(fā)現(xiàn)存入數(shù)據(jù)庫的仍然是亂碼。問題就出在這個connection連接層上。解決方法是在發(fā)送查詢前執(zhí)行一下下面這句:
SET NAMES 'utf8';
它相當于下面的三句指令:
SET character_set_client = utf8;
SET character_set_results = utf8;
SET character_set_connection = utf8;
再試試看,正常了吧?^_^ Enjoy!
具體講
在你的查詢前加一行:
mysql_query("SET NAMES 'gb2312';",$this->con);
真應(yīng)該把手冊仔細看一遍.
和字符相關(guān)的變量中這幾個和sql很有關(guān)系:
character_set_client
character_set_connection
character_set_results
此外就是數(shù)據(jù)庫中對相應(yīng)字段設(shè)置的charact set,如果沒有對字段設(shè)置,缺省是table的charact set,table也沒有指定則缺省使用database的。
上面3個變量的作用是這樣的,client表示客戶端發(fā)送過來的字符集,results表示發(fā)送到客戶端的字符集(這兩個分開是因為發(fā)送過來和發(fā)送過去的不一定是同一個客戶端),connection則在客戶端和數(shù)據(jù)庫起一個連接作用。
具體是這樣:比如我在mysql命令行設(shè)置client為gbk,connection為utf8,results為gbk,數(shù)據(jù)庫為big5,
當我發(fā)送一個insert語句的時候,這個語句作為gbk代碼,先轉(zhuǎn)為utf8代碼(connection),再轉(zhuǎn)為big5(database)插入數(shù)據(jù)庫。
而運行一個select語句的時候,從數(shù)據(jù)庫得到的結(jié)果則相反的過程,由big5轉(zhuǎn)為utf8,再轉(zhuǎn)為gbk,你得到gbk的結(jié)果。
因此最主要的是讓client和results和你使用的客戶端一致。比如你的網(wǎng)頁是utf8編碼,你就要設(shè)置這兩個為utf8。
而在mysql命令行的時候,我用的是2000,需要設(shè)置為gbk
而我們用的set names XXX,實際上就是同時設(shè)置這3個變量為XXX。
在這樣的情況下,我們可以把一個數(shù)據(jù)庫中的不同表或不同字段設(shè)為不同的字符集,只要上面3個設(shè)置正確,就可以在數(shù)據(jù)庫中同時使用不同的字符集。
注意要保證你的數(shù)據(jù)庫中的字符已經(jīng)使用了正確的字符集,比如如果一開始你設(shè)置錯誤,插入數(shù)據(jù)后,本身數(shù)據(jù)的編碼就是不正確的,然后即使設(shè)置改回來,也不可能得到正確的顯示了。
還有一個是編碼互相之間的兼容性,如果一個字符在gbk中有,在utf8中沒有,那么在gbk-》utf8-》gbk的過程中,它就變成了“?”
再說一下具體解決的辦法。
首先要指定你的升級后的database及table及field的character set,一般來說我們用gb2312或者utf8的,如果不同時使用多種編碼,只要指定database就可以,可以在建庫的sql語句加上相應(yīng)的 character set,在phpMyAdmin里也可以修改。
然后是導(dǎo)入舊數(shù)據(jù)。首先要確定自己的數(shù)據(jù)文件的編碼。如果用phpMyAdmin導(dǎo)入,在界面上有文件編碼的選項,一定要和數(shù)據(jù)文件的編碼一致。
如果從mysql的命令行導(dǎo)入,就要自己設(shè)置上面說到的3個變量,set names xxx。
使用其它的客戶端程序一樣要注意。
這樣就可以讓舊數(shù)據(jù)轉(zhuǎn)入新數(shù)據(jù)庫后的編碼才是正確的,如果這一步錯了,后面不可能得到正確的顯示。
然后是自己的程序,在連接后就可以執(zhí)行一次set names xxx,根據(jù)你的網(wǎng)頁編碼而定。
-----------------------------------------
mysql 導(dǎo)入亂碼問題- -
mysql從4.1使用mysqldump導(dǎo)出數(shù)據(jù)并在4.0導(dǎo)入的時候會出現(xiàn)sql語句錯誤,并且所有數(shù)據(jù)變成亂碼。使用下面的參數(shù)就可以解決
mysqldump -uxunai -p --compatible=mysql40 --default-character-set=latin1 xunai>xunai.sql
mysql -uroot -p fmx < fmx3.sql -f --default-character-set=latin1
MySQL 4.1 中文亂碼的問題
最近要將 MySQL 4.0 升級到 MySQL 4.1 ,發(fā)現(xiàn)了中文亂碼的問題,希望以下見解對大家有用。
1. MySQL 4.1 在文字上有很大改進,它有了 Character Set 與 Collation 的慨念。
2. 在 MySQL 4.0 ,一般的程式都會將文字以拉丁文 ( latin) 來儲存,就算我們輸入中文字,結(jié)果仍是放在以拉丁文設(shè)置的文字欄里頭,這對 MySQL 4.0 與以 MySQL 4.0 為基楚的程式來說,并不會有問題。
3. 可是 MySQL 4.1 的系統(tǒng)編碼是預(yù)設(shè)用 UTF-8 的,當要 restore MySQL 4.0 的 backup 檔到 MySQL 4.1 時,亂碼就出現(xiàn)了。原因在于 MySQL 4.1 將 latin 碼轉(zhuǎn)換過來,而后轉(zhuǎn)換是并不完全完美的,這導(dǎo)致了出現(xiàn)少量文字出現(xiàn)亂碼現(xiàn)象。
解決PHP存取MySQL 4.1亂碼問題
QUOTE:
從MySQL 4.1開始引入的多語言支持確實很棒,而且一些特性已經(jīng)超過了其他的數(shù)據(jù)庫系統(tǒng)。不過我在測試過程中發(fā)現(xiàn)使用適用于MySQL 4.1之前的PHP語句操作MySQL數(shù)據(jù)庫會造成亂碼,即使是設(shè)置過了表字符集也是如此。我讀了一下新的MySQL在線手冊中第十章 "Character Set Support"后終于找到了解決方法并測試通過。
MySQL 4.1的字符集支持(Character Set Support)有兩個方面:字符集(Character set)和排序方式(Collation)。對于字符集的支持細化到四個層次: 服務(wù)器(server),數(shù)據(jù)庫(database),數(shù)據(jù)表(table)和連接(connection)。
查看系統(tǒng)的字符集和排序方式的設(shè)定可以通過下面的兩條命令:
CODE:
mysql> SHOW VARIABLES LIKE 'character_set_%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
7 rows in set (0.00 sec)
mysql> SHOW VARIABLES LIKE 'collation_%';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
| collation_database | latin1_swedish_ci |
| collation_server | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.00 sec)
上面列出的值就是系統(tǒng)的默認值。如果你奇怪系統(tǒng)怎么默認是latin1的瑞典語排序方式,原因是MySQL由瑞典的T.c.X.DataKonsultAB公司(目前公司名稱為MySQL AB)開發(fā),不用再多說了吧。
當我們按照原來的方式通過PHP存取MySQL數(shù)據(jù)庫時,就算設(shè)置了表的默認字符集為utf8并且通過UTF-8編碼發(fā)送查詢,你會發(fā)現(xiàn)存入數(shù)據(jù)庫的仍然是亂碼。問題就出在這個connection連接層上。解決方法是在發(fā)送查詢前執(zhí)行一下下面這句:
SET NAMES 'utf8';
它相當于下面的三句指令:
CODE:
SET character_set_client = utf8;
SET character_set_results = utf8;
SET character_set_connection = utf8;
再試試看,正常了吧?
就是連接之后加個查詢
CODE:
$this->query(”SET NAMES ‘utf8'”);
看了手冊第10章覺得主要還是Character Sets的問題。
character_set_client,character_set_results,character_set_connection三個運行變量是造成亂碼的關(guān)鍵。mysql把客戶端提交的查詢由character_set_client轉(zhuǎn)換為character_set_connection
,由于默認網(wǎng)頁提交的查詢是gb2312(表單頁面meta里可以看到),而mysql默認將其當作utf8(可以查到此時的 character_set_client=utf8),所以必然亂碼。同理,mysql返回的結(jié)果是已經(jīng)轉(zhuǎn)換成 character_set_results編碼的(與表的編碼無關(guān)),同樣默認是utf8,而網(wǎng)頁頁面把它當gb2312處理,所以必然有標題等由數(shù)據(jù)庫讀出的字段是亂碼而其他部門文字不亂碼的現(xiàn)象。
以上這個例子是utf8字符集,用此方法,設(shè)置為gbk,即可解決
第三個方法:
mysql 4.1亂碼終極解決方案
請注意,本文只針對mysql 4.1,其它版本的mysql請看別的文章。
mysql4.1是比較煩人,支持多語言的細化設(shè)置,再加上phpmyadmin2.6也比較笨,默認就是改不動的utf8,怎么弄都亂碼。
好了,廢話少說,我們來一步步解決這個問題:
1.修改/etc/my.cnf文件,改成這樣:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
default-character-set=utf8
[mysql.server]
user=mysql
basedir=/var/lib
[mysqld_safe]
err-log=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
注意:就是加入了一句default-character-set=utf8。
2./etc/init.d/mysqld restart 重新啟動mysql;
3.打開phpmyadmin,選擇lang為"Chines simplifies(zh-utf-8)",選擇"MySQL 連接校對"為"utf8_general_ci "點“顯示 MySQL 的運行信息”--“變量”,可以看到:
character set client utf8 utf8
character set connection utf8 utf8
character set database utf8 utf8
character set results utf8 utf8
character set server utf8 utf8
character set system utf8 utf8
collation connection utf8_general_ci utf8_general_ci
collation database utf8_general_ci utf8_general_ci
collation server utf8_general_ci utf8_general_ci
從這里可以看到character全部變成utf8了。
有人要問,為什么都要改成utf8呢?改成GB2312不行嗎?
解釋如下:
我也不想改成utf8,只是phpmyadmin2.6在mysql4.1的時候只會用utf8,連其他頁面的charset也都是utf8,改成gb2312一定會亂碼,我們只能湊phpmyadmin了。
只有在mysql3.23的時候,phpmyadmin才會多一個gb2312的頁面charset,這時候是正常的。
3.將以前的mysql3的庫文件導(dǎo)入mysql4.1的庫
有兩種情況:
一是從phpmyadmin上導(dǎo)入,這時候你要注意的是在選擇庫文件的頁面左下腳有個“文件的字符集:”,默認是utf8,要改成gb2312,否則導(dǎo)進去亂碼;
二是在linux下導(dǎo)入,這時候你需要先在庫文件的頭部加一行:
SET NAMES 'gb2312'; 注意最后也是;號,別漏了。
然后執(zhí)行mysql -u用戶名 -p密碼 xxx.sql > 庫名
導(dǎo)入完成以后再用phpmyadmin打開看,里面的中文字就是正確的。
4.從mysql4.1里導(dǎo)出庫文件
一.用phpmyadmin導(dǎo)出
導(dǎo)出倒是問題不大,如果phpmyadmin的瀏覽頁面里顯示的中文是正常的,那么導(dǎo)出肯定也是正常的
二.在linux上導(dǎo)出
如果用mysqldump導(dǎo)出出現(xiàn)了亂碼也沒有關(guān)系,可以運行iconv來轉(zhuǎn)換一下
iconv -c -f UTF-8 -t GB2312 庫文件名 > 新的gb2312的庫文件名
綜上所述,你要注意:
1。盡量在需要導(dǎo)入的庫文件的開頭加入SET NAMES 'gb2312';告訴mysql你要導(dǎo)入的是一個gb2312的文件;
2??赡苣阈枰@個:
SET NAMES 'utf8';
在登陸到mysql后用,把character的一些默認參數(shù)改到utf8上,有時可以減少一些困擾,不過也不是必須的。
在mysql上使用:
SHOW VARIABLES LIKE 'character_set_%';
用來查看當前的狀態(tài)。
3.如果出現(xiàn)亂碼也不要怕,一是你要注意留存原有的備份,二是用iconv來進行轉(zhuǎn)化。
在正常使用之前注意做導(dǎo)入導(dǎo)出的測試,確保萬無一失。
下面再說明一下,網(wǎng)上很多朋友說Mysql4.1的只能升,不能降. 這是不正確的. 同樣使用mysqldump 導(dǎo)出數(shù)據(jù)庫時加一個 --compatible 的參數(shù).也千萬不能忘了--default-character-set=這個設(shè)定字符集的參數(shù).
示范: mysqldump -uroot -pPassword --compatible=mysql40 --default-character-set=gb2312 discuz>d:discuz.sql
ok 這樣導(dǎo)出來的文件,就可以在Mysql4.0.X和Mysql.3.2.X版本中使用了.
Linux下 Mysql 5 中文亂碼的徹底解決及應(yīng)用的一些注意事項
一. 自從mysql4.1開始,mysql對中文的支持問題是比較煩人的,怎么弄都亂碼,如今mysql5 據(jù)說是mysql的新紀元,但從官方下載安裝的mysql5仍存在亂碼現(xiàn)象,這里就是針對此現(xiàn)象做的討論:
建議最好是下載mysql的源碼進行編譯,這是由于官方編譯的mysql的默認支持編碼是latin字符集,所以中文字符在數(shù)據(jù)庫里查看的時候看到的是亂碼。編譯MySQL時使用withcharset=編碼,可以方便地把mysql編譯成該編碼形式,這樣MySQL就會直接支持中文查找和排序,-- with-extra-charsets參數(shù)指定其它可用的字符集。
下載并解壓源碼包,打開INSTALL-SOURCE,這里介紹了linux下詳細的安裝方法,所以大家所要注意的只是下面的configure指令:
groupadd mysql
useradd -g mysql mysql
./configure --with-charset=gbk --with-collation=gbk_chinese_ci --with-extra-charsets=gb2312,big5,utf8,binary,ascii --prefix=/usr/local/mysql
make
make install
cp support-files/my-medium.cnf /etc/my.cnf
cd /usr/local/mysql
bin/mysql_install_db --user=mysql
chown -R root .
chown -R mysql var
chgrp -R mysql .
bin/mysqld_safe --user=mysql &
bin/mysql
mysql> show variables;
你可以看到全局的字符集參數(shù)全是gbk,gb2312字集應(yīng)該包含在gbk里,所以不討論。
進行和平常mysql4.0一樣的php操作,你會發(fā)現(xiàn)仍然出現(xiàn)中文亂碼現(xiàn)象。
這里要說明的是:從mysql 4.1開始,必需在mysql數(shù)據(jù)庫連接后對應(yīng)用的字符集做出說明,否則非英文字母的文字存取都無法解釋變成?號。
解決方法就是要適應(yīng)新版mysql的要求:
在連接mysql數(shù)據(jù)庫后執(zhí)行set character set 字符集,該指令在最新版的mysql 5如果默認字集和存儲相符可以免設(shè):
set character set gbk;
在php里應(yīng)該是這么寫:mysql_query("set character set gbk");
指令大小寫均可
phpwind和discuz是廣泛應(yīng)用的國產(chǎn)php論壇,大量的朋友在應(yīng)用它,了解了以上步驟,你也可以對論壇源碼進行很小的修改,安全地把數(shù)據(jù)庫升級到mysql5:
找到include/db_mysql.php,修改function connect(...){.....}
在選擇數(shù)據(jù)庫mysql_select_db($dbname);后面加上一句mysql_query('set character set gbk');存盤。
二. 文件的導(dǎo)入導(dǎo)出:如果存入非gbk字符,這時候你需要先在導(dǎo)入文件的頭部加一行: SET NAMES '字符集'; 并注意最后也是;號,別漏了。
文件導(dǎo)入和導(dǎo)出執(zhí)行
mysql -u用戶名 -p密碼 數(shù)據(jù)庫名
mysqldump -u用戶名 -p密碼 數(shù)據(jù)庫名>data.sql
如果用mysqldump導(dǎo)出數(shù)據(jù)出現(xiàn)了亂碼也沒有關(guān)系,可以運行iconv來轉(zhuǎn)換一下:
iconv -c -f utf8 -t gbk 庫文件名>新的gbk的庫文件名
綜上所述,你要注意:
1。盡量在需要導(dǎo)入的庫文件的開頭加入set names 'gbk';告訴mysql你要導(dǎo)入的是一個gbk的文件;
2。在mysql上使用 show variables;或show variables like 'character_set_%'; 用來查看當前的字集狀態(tài)。
3。如果出現(xiàn)亂碼也不要怕,其一是你要注意留存原有的備份,其二是用iconv來進行轉(zhuǎn)化。
#PHP連接問題:
由于MySQL 4.1版本開始密碼的hash算法改變,所以連接數(shù)據(jù)庫時可能會出現(xiàn)Client does not support authentication protocol問題
此問題在mysql 5中不存在,mysql 5不需要以下的設(shè)置。
可以通過一下兩種方法解決數(shù)據(jù)庫用戶密碼不符問題:
其一: mysql> SET PASSWORD FOR 'some_user'@'some_host' = OLD_PASSWORD('newpwd');
其二: mysql> Update mysql.user SET Password = OLD_PASSWORD('newpwd') Where Host = 'some_host' AND User = 'some_user'
PHP輸出的其它亂碼問題:
如果將mysql編譯為默認編碼gbk的話,又會造成非gbk數(shù)據(jù)直接導(dǎo)入顯示為亂碼,比如部份utf8存儲的字符,如果你大部份數(shù)據(jù)是utf8字集,當然得把mysql編譯為默認編碼utf8才合適。
Mysql 4.1.x出來以后,引入了collation (校勘)的概念,終于有辦法讓mysql同時支持多種編碼的數(shù)據(jù)庫了,所以PHP要用以下SQL語句來創(chuàng)建utf-8編碼的數(shù)據(jù)庫:
Create DATABASE `mytest` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
但是僅僅是將數(shù)據(jù)庫的??备臑閡tf-8是不夠的,還必須在連接了mysql數(shù)據(jù)庫之后用這個語句來設(shè)置:set names 'utf8';才能在php程序里得到正確編碼的字符,并將其顯示在web頁面里。
mysql_query("set names 'utf8'",$connection);
下面再說明一下,網(wǎng)上很多朋友說Mysql4.1的只能升,不能降. 這是不正確的. 同樣使用mysqldump 導(dǎo)出數(shù)據(jù)庫時加一個 --compatible 的參數(shù).也千萬不能忘了--default-character-set=這個設(shè)定字符集的參數(shù)。
示范: mysqldump -uroot -pPassword --compatible=mysql40 --default-character-set=gb2312 discuz>d:discuz.sql
ok 這樣導(dǎo)出來的文件,就可以在Mysql4.0.X和Mysql.3.2.X版本中使用了.
下面要寫的是一篇非常無聊的東西,充斥了大量各式各樣的編碼、轉(zhuǎn)換、客戶端、服務(wù)器端、連接……呃,我自己都不愿意去看它,但想一想,寫下來還是有點意義的,原因有四:
MySQL 4.1 對多語言的支持有了很大變化 (這導(dǎo)致了問題的出現(xiàn));
盡管大部分的地方 (包括個人使用和主機提供商),MySQL 3 仍然占主導(dǎo)地位;但 MySQL 4.1 是 MySQL 官方推薦的數(shù)據(jù)庫,已經(jīng)有主機提供商開始提供并將會越來越多;
許多 PHP 程序以 MySQL 作為默認的數(shù)據(jù)庫管理軟件,但它們一般不區(qū)分 MySQL 4.1 與 4.1 以下版本的區(qū)別,籠統(tǒng)地稱“MySQL 3.xx.xx 以上版本”就滿足安裝需求了;
因為 latin1 在許多地方 (下邊會詳細描述具體是哪些地方) 作為默認的字符集,成功的蒙蔽了許多 PHP 程序的開發(fā)者和用戶,掩蓋了在中文等語言環(huán)境下會出現(xiàn)的問題;
簡單的說,MySQL 自身的變化和使用 MySQL 的 PHP 程序?qū)Υ撕雎裕瑢?dǎo)致了問題的出現(xiàn)和復(fù)雜化,而由于大部分用戶使用的是英文,使這種問題不被重視。這里提到的 PHP 程序,主要就 WordPress 而言。
MySQL 4.1 字符集支持的原理MySQL 4.1 對于字符集的指定可以細化到一臺機器上安裝的 MySQL,其中的一個數(shù)據(jù)庫,其中的一張表,其中的一欄,應(yīng)該用什么字符集。但是,傳統(tǒng)的 Web 程序在創(chuàng)建數(shù)據(jù)庫和數(shù)據(jù)表時并沒有使用那么復(fù)雜的配置,它們用的是默認的配置,那么,默認的配置從何而來呢?
編譯 MySQL 時,指定了一個默認的字符集,這個字符集是 latin1;
安裝 MySQL 時,可以在配置文件 (my.ini) 中指定一個默認的的字符集,如果沒指定,這個值繼承自編譯時指定的;
啟動 mysqld 時,可以在命令行參數(shù)中指定一個默認的的字符集,如果沒指定,這個值繼承自配置文件中的;
此時 character_set_server 被設(shè)定為這個默認的字符集;
當創(chuàng)建一個新的數(shù)據(jù)庫時,除非明確指定,這個數(shù)據(jù)庫的字符集被缺省設(shè)定為 character_set_server;
當選定了一個數(shù)據(jù)庫時,character_set_database 被設(shè)定為這個數(shù)據(jù)庫默認的字符集;
在這個數(shù)據(jù)庫里創(chuàng)建一張表時,表默認的字符集被設(shè)定為 character_set_database,也就是這個數(shù)據(jù)庫默認的字符集;
當在表內(nèi)設(shè)置一欄時,除非明確指定,否則此欄缺省的字符集就是表默認的字符集;
這個字符集就是數(shù)據(jù)庫中實際存儲數(shù)據(jù)采用的字符集,mysqldump 出來的內(nèi)容就是這個字符集下的;
簡單的總結(jié)一下,如果什么地方都不修改,那么所有的數(shù)據(jù)庫的所有表的所有欄位的都用 latin1 存儲,不過我們?nèi)绻惭b MySQL,一般都會選擇多語言支持,也就是說,安裝程序會自動在配置文件中把 default_character_set 設(shè)置為 UTF-8,這保證了缺省情況下,所有的數(shù)據(jù)庫的所有表的所有欄位的都用 UTF-8 存儲。
當一個 PHP 程序與 MySQL 建立連接后,這個程序發(fā)送給 MySQL 的數(shù)據(jù)采用的是什么字符集?MySQL 無從得知 (它最多只能猜測),所以 MySQL 4.1 要求客戶端必須指定這個字符集,也就是 character_set_client,MySQL 的怪異之處在于,得到的這個字符集并不立即轉(zhuǎn)換為存儲在數(shù)據(jù)庫中的那個字符集,而是先轉(zhuǎn)換為 character_set_connection 變量指定的一個字符集;這個 connection 層究竟有什么用我不大明白,但轉(zhuǎn)換為 character_set_connection 的這個字符集之后,還要轉(zhuǎn)換為數(shù)據(jù)庫默認的字符集,也就是說要經(jīng)過兩次轉(zhuǎn)換;當這個數(shù)據(jù)被輸出時,又要由數(shù)據(jù)庫默認的字符集轉(zhuǎn)換為 character_set_results 指定的字符集。
一個典型的環(huán)境典型的環(huán)境以我自己的電腦上安裝的 MySQL 4.1 為例,我自己的電腦上安裝著 Apache 2,PHP 5 和 WordPress 1.5.1.3,MySQL 配置文件中指定了 default_character_set 為 utf8。于是問題出現(xiàn)了:
WordPress 按照默認情況安裝,所以所有的表都用 UTF-8 存儲數(shù)據(jù);
WordPress 默認采用的瀏覽字符集是 UTF-8 (Options->Reading 中設(shè)置),因此所有 WP 頁面的 meta 中會說明 charset 是 utf-8;
所以瀏覽器會以 utf-8 方式顯示所有的 WP 頁面;這樣一來 Write 的所有 Post,和 Comment 都會以 UTF-8 格式從瀏覽器發(fā)送給 Apache,再由 Apache 交給 PHP;
所以 WP 從所有的表單中得到的數(shù)據(jù)都是 utf-8 編碼的;WP 不加轉(zhuǎn)換的直接把這些數(shù)據(jù)發(fā)送給 MySQL;
MySQL 默認設(shè)置的 character_set_client 和 character_set_connection 都是 latin1,此時怪異的事情發(fā)生了,實際上是 utf-8 格式的數(shù)據(jù),被“當作 latin1”轉(zhuǎn)換成……居然還是轉(zhuǎn)換成 latin1,然后再由這個 latin1 轉(zhuǎn)換成 utf-8,這么兩次轉(zhuǎn)換,有一部分 utf-8 的字符就丟失了,變成 ??,最后輸出的時候 character_set_results 默認是 latin1,也就輸出為奇怪的東西了。
最神奇的還不是這個,如果 WordPress 中設(shè)置以 GB2312 格式閱讀,那么 WP 發(fā)送給 MySQL 的 GB2312 編碼的數(shù)據(jù),被“當作 latin1”轉(zhuǎn)換后,存進數(shù)據(jù)庫的是一種奇怪的格式 (真的是奇怪的格式,mysqldump 出來就能發(fā)現(xiàn),無論當作 utf-8 還是當作 gb2312 來讀都是亂碼),但如果這種格式以 latin1 輸出出來,居然又能變回 GB2312!
這會導(dǎo)致什么現(xiàn)象呢?WP 如果使用 MySQL 4.1 數(shù)據(jù)庫,把編碼改用 GB2312 就正常了,可惜,這種正常只是貌似正常。
如何解決問題如果你已經(jīng)不耐煩了 (幾乎是肯定的),google 一下,會發(fā)現(xiàn)絕大部分的解答是,query 之前先執(zhí)行一下:SET NAMES 'utf8',沒錯,這是解決方案,但本文的目的是說明,這為什么是解決方案。
要保證結(jié)果正確,必須保證數(shù)據(jù)表采用的格式是正確的,也就是說,至少能夠存放所有的漢字,那么我們只有兩種選擇,gbk 或者 utf-8,下面討論 utf-8 的情況。
因為配置文件設(shè)置的 default_character_set 是 utf8,數(shù)據(jù)表默認采用的就是 utf-8 建立的。這也應(yīng)該是所有采用 MySQL 4.1 的主機提供商應(yīng)該采用的配置。所以我們要保證的只是客戶端與 MySQL 交互之間指定編碼的正確。
這只有兩種可能,客戶端以 gb2312 格式發(fā)送數(shù)據(jù),或者以 utf-8 格式發(fā)送數(shù)據(jù)。
如果以 gb2312 格式發(fā)送:
SET character_set_client='gb2312'
SET character_set_connection='utf8' 或者
SET character_set_connection='gb2312'
都是可以的,都能夠保證數(shù)據(jù)在編碼轉(zhuǎn)換中不出現(xiàn)丟失,也就是保證存儲入數(shù)據(jù)庫的是正確的內(nèi)容。
怎么保證取出的是正確的內(nèi)容呢?考慮到絕大部分客戶端 (包括 WP),發(fā)送數(shù)據(jù)的編碼也就是它所希望收到數(shù)據(jù)的編碼,所以:
SET character_set_results='gb2312'
可以保證取出給瀏覽器顯示的格式就是 gb2312。
如果是第二種情況,客戶端以 utf-8 格式發(fā)送 (WP 的默認情況),可以采用下述配置:
SET character_set_client='utf8'
SET character_set_connection='utf8'
SET character_set_results='utf8'
這個配置就等價于 SET NAMES 'utf8'。
WP 應(yīng)該作什么修改還是那句話,客戶端要發(fā)給數(shù)據(jù)庫什么編碼的數(shù)據(jù),數(shù)據(jù)庫是不可能確切知道的,只能讓客戶端自己說明白,所以,WP 是必須發(fā)送正確的 SET... 給 MySQL 的。怎么發(fā)送最合適呢?臺灣的 pLog 同仁給出了一些建議:
首先,測試服務(wù)器是否 >= 4.1,編譯時是否加入了 UTF-8 支持;是則繼續(xù)
然后測試數(shù)據(jù)庫以什么格式存儲 ($dbEncoding);
SET NAMES $dbEncoding
對于第二點,WP 的情況是不同的,按照上面的典型配置,只要用 WP,肯定數(shù)據(jù)庫是用 UTF-8 存儲的,所以要根據(jù)用戶設(shè)置的以 GB2312 還是 UTF-8 瀏覽來判斷 (bloginfo('charset')),但這個值是要連接數(shù)據(jù)庫以后才能得到的,所以效率最高的方式是連接數(shù)據(jù)庫之后,根據(jù)這個配置設(shè)置一次 SET NAMES,而不必每次查詢之前都設(shè)置一遍。
我的修改方式是這樣的,在 wp_includes/wp-db.php 中增加:
function set_charset($charset)
{
// check mysql version first.
$serverVersion = mysql_get_server_info($this->dbh);
$version = explode('.', $serverVersion);
if ($version[0] < 4) return;
// check if utf8 support was compiled in
$result = mysql_query("SHOW CHARACTER SET like 'utf8'",
$this->dbh);
if (mysql_num_rows($result) < = 0) return;
if ($charset == 'utf-8' || $charset == 'UTF-8')
$charset = 'utf8';
@mysql_query("SET NAMES '$charset'", $this->dbh);
}
在 wp-settings.php 的 require (ABSPATH . WPINC . '/vars.php'); 后增加:
$wpdb->set_charset(get_bloginfo('charset'));
1. MySQL 4.1 在文字上有很大改進,它有了 Character Set 與 Collation 的慨念。
2. 在 MySQL 4.0 ,一般的程式都會將文字以拉丁文 ( latin) 來儲存,就算我們輸入中文字,結(jié)果仍是放在以拉丁文設(shè)置的文字欄里頭,這對 MySQL 4.0 與以 MySQL 4.0 為基楚的程式來說,并不會有問題。
3. 可是 MySQL 4.1 的系統(tǒng)編碼是預(yù)設(shè)用 UTF-8 的,當要 restore MySQL 4.0 的 backup 檔到 MySQL 4.1 時,亂碼就出現(xiàn)了。原因在于 MySQL 4.1 將 latin 碼轉(zhuǎn)換過來,而后轉(zhuǎn)換是并不完全完美的,這導(dǎo)致了出現(xiàn)少量文字出現(xiàn)亂碼現(xiàn)象。
4. 要解決這亂碼問題并不難。首先,在 MySQL 4.0 備份時,先將所有文字欄變成 binary 類型,然后進行正常備份。第二步,可在 MySQL 4.1 里將剛才的備份 restore。最后,將較早前所變更到 binay 類型的文字欄,再次復(fù)原到文字類型。這樣中文編碼的問題就應(yīng)該可以完全解決。
5. 將文字欄變更到 binay 類型時,必需設(shè)定 binary 欄的長度大過或等于 (>=) 文字欄的長度,否則資料會失去。
6. 另外,經(jīng)這樣升級的 MySQL 數(shù)據(jù)庫,在 MySQL 4.1 里將會正常工作,就算是怎樣 backup 與 restore 都不會再有亂碼問題。
作者: MySQL 發(fā)布日期: 2005-12-14
mysql4.1是比較煩人,支持多語言的細化設(shè)置,再加上phpmyadmin2.6也比較笨,默認就是改不動的utf8,怎么弄都亂碼。
好了,廢話少說,我們來一步步解決這個問題:
1.修改/etc/my.cnf文件,改成這樣:
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
default-character-set=utf8
[mysql.server]
user=mysql
basedir=/var/lib
[mysqld_safe]
err-log=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
注意:就是加入了一句default-character-set=utf8。
2./etc/init.d/mysqld restart 重新啟動mysql;
3.打開phpmyadmin,選擇lang為"Chines simplifies(zh-utf-8)",選擇"MySQL 連接校對"為"utf8_general_ci "點“顯示 MySQL 的運行信息”--“變量”,可以看到:
character set client utf8 utf8
character set connection utf8 utf8
character set database utf8 utf8
character set results utf8 utf8
character set server utf8 utf8
character set system utf8 utf8
collation connection utf8_general_ci utf8_general_ci
collation database utf8_general_ci utf8_general_ci
collation server utf8_general_ci utf8_general_ci
從這里可以看到character全部變成utf8了。
有人要問,為什么都要改成utf8呢?改成GB2312不行嗎?
解釋如下:
我也不想改成utf8,只是phpmyadmin2.6在mysql4.1的時候只會用utf8,連其他頁面的charset也都是utf8,改成gb2312一定會亂碼,我們只能湊phpmyadmin了。
只有在mysql3.23的時候,phpmyadmin才會多一個gb2312的頁面charset,這時候是正常的。
3.將以前的mysql3的庫文件導(dǎo)入mysql4.1的庫
有兩種情況:
一是從phpmyadmin上導(dǎo)入,這時候你要注意的是在選擇庫文件的頁面左下腳有個“文件的字符集:”,默認是utf8,要改成gb2312,否則導(dǎo)進去亂碼;
二是在linux下導(dǎo)入,這時候你需要先在庫文件的頭部加一行:
SET NAMES 'gb2312'; 注意最后也是;號,別漏了。
然后執(zhí)行mysql -u用戶名 -p密碼 xxx.sql > 庫名
導(dǎo)入完成以后再用phpmyadmin打開看,里面的中文字就是正確的。
4.從mysql4.1里導(dǎo)出庫文件
一.用phpmyadmin導(dǎo)出
導(dǎo)出倒是問題不大,如果phpmyadmin的瀏覽頁面里顯示的中文是正常的,那么導(dǎo)出肯定也是正常的
二.在linux上導(dǎo)出
如果用mysqldump導(dǎo)出出現(xiàn)了亂碼也沒有關(guān)系,可以運行iconv來轉(zhuǎn)換一下
iconv -c -f UTF-8 -t GB2312 庫文件名 > 新的gb2312的庫文件名
綜上所述,你要注意:
1。盡量在需要導(dǎo)入的庫文件的開頭加入SET NAMES 'gb2312';告訴mysql你要導(dǎo)入的是一個gb2312的文件;
2??赡苣阈枰@個:
SET NAMES 'utf8';
在登陸到mysql后用,把character的一些默認參數(shù)改到utf8上,有時可以減少一些困擾,不過也不是必須的。
在mysql上使用:
SHOW VARIABLES LIKE 'character_set_%';
用來查看當前的狀態(tài)。
3.如果出現(xiàn)亂碼也不要怕,一是你要注意留存原有的備份,二是用iconv來進行轉(zhuǎn)化。
在正常使用之前注意做導(dǎo)入導(dǎo)出的測試,確保萬無一失。
我升級了MYSQL到4.1.2,phpmyadmin用的是2.6.2。數(shù)據(jù)表里面有中文的字段中文都變成了亂碼,導(dǎo)出數(shù)據(jù)也是亂碼。我用以前的2.5.7沒有問題,想問一下,應(yīng)該在phpmyadmin的那個文件里改哪個設(shè)置一下才能顯示出來的是正常的中文字?
和字符相關(guān)的變量中這幾個和sql很有關(guān)系:
character_set_client
character_set_connection
character_set_results
此外就是數(shù)據(jù)庫中對相應(yīng)字段設(shè)置的charact set,如果沒有對字段設(shè)置,缺省是table的charact set,table也沒有指定則缺省使用database的。
上面3個變量的作用是這樣的,client表示客戶端發(fā)送過來的字符集,results表示發(fā)送到客戶端的字符集(這兩個分開是因為發(fā)送過來和發(fā)送過去的不一定是同一個客戶端),connection則在客戶端和數(shù)據(jù)庫起一個連接作用。
具體是這樣:比如我在mysql命令行設(shè)置client為gbk,connection為utf8,results為gbk,數(shù)據(jù)庫為big5,
當我發(fā)送一個insert語句的時候,這個語句作為gbk代碼,先轉(zhuǎn)為utf8代碼(connection),再轉(zhuǎn)為big5(database)插入數(shù)據(jù)庫。
而運行一個select語句的時候,從數(shù)據(jù)庫得到的結(jié)果則相反的過程,由big5轉(zhuǎn)為utf8,再轉(zhuǎn)為gbk,你得到gbk的結(jié)果。
因此最主要的是讓client和results和你使用的客戶端一致。比如你的網(wǎng)頁是utf8編碼,你就要設(shè)置這兩個為utf8。
而在mysql命令行的時候,我用的是2000,需要設(shè)置為gbk
而我們用的set names XXX,實際上就是同時設(shè)置這3個變量為XXX。
在這樣的情況下,我們可以把一個數(shù)據(jù)庫中的不同表或不同字段設(shè)為不同的字符集,只要上面3個設(shè)置正確,就可以在數(shù)據(jù)庫中同時使用不同的字符集。
注意要保證你的數(shù)據(jù)庫中的字符已經(jīng)使用了正確的字符集,比如如果一開始你設(shè)置錯誤,插入數(shù)據(jù)后,本身數(shù)據(jù)的編碼就是不正確的,然后即使設(shè)置改回來,也不可能得到正確的顯示了。
還有一個是編碼互相之間的兼容性,如果一個字符在gbk中有,在utf8中沒有,那么在gbk-》utf8-》gbk的過程中,它就變成了“?”
再說一下具體解決的辦法。
首先要指定你的升級后的database及table及field的character set,一般來說我們用gb2312或者utf8的,如果不同時使用多種編碼,只要指定database就可以,可以在建庫的sql語句加上相應(yīng)的 character set,在phpMyAdmin里也可以修改。
然后是導(dǎo)入舊數(shù)據(jù)。首先要確定自己的數(shù)據(jù)文件的編碼。如果用phpMyAdmin導(dǎo)入,在界面上有文件編碼的選項,一定要和數(shù)據(jù)文件的編碼一致。
如果從mysql的命令行導(dǎo)入,就要自己設(shè)置上面說到的3個變量,set names xxx。
使用其它的客戶端程序一樣要注意。
這樣就可以讓舊數(shù)據(jù)轉(zhuǎn)入新數(shù)據(jù)庫后的編碼才是正確的,如果這一步錯了,后面不可能得到正確的顯示。
然后是自己的程序,在連接后就可以執(zhí)行一次set names xxx,根據(jù)你的網(wǎng)頁編碼而定。
這樣基本就可以保證編碼正確了。
你很有可能是導(dǎo)入的數(shù)據(jù)編碼已經(jīng)不對了。
MYSQL數(shù)據(jù)庫默認語言為瑞典語, 現(xiàn)有一GB2312字符的數(shù)據(jù)庫.
結(jié)構(gòu)OK. 為什么內(nèi)容是亂碼? 不重裝數(shù)據(jù)庫有辦法解決碼?
從MySQL 4.1開始引入的多語言支持確實很棒,而且一些特性已經(jīng)超過了其他的數(shù)據(jù)庫系統(tǒng)。不過我在測試過程中發(fā)現(xiàn)使用適用于MySQL 4.1之前的PHP語句操作MySQL數(shù)據(jù)庫會造成亂碼,即使是設(shè)置過了表字符集也是如此。我讀了一下新的MySQL在線手冊中第十章 "Character Set Support"后終于找到了解決方法并測試通過。
MySQL 4.1的字符集支持(Character Set Support)有兩個方面:字符集(Character set)和排序方式(Collation)。對于字符集的支持細化到四個層次: 服務(wù)器(server),數(shù)據(jù)庫(database),數(shù)據(jù)表(table)和連接(connection)。
查看系統(tǒng)的字符集和排序方式的設(shè)定可以通過下面的兩條命令:
mysql> SHOW VARIABLES LIKE 'character_set_%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
7 rows in set (0.00 sec)
mysql> SHOW VARIABLES LIKE 'collation_%';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
| collation_database | latin1_swedish_ci |
| collation_server | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.00 sec)
上面列出的值就是系統(tǒng)的默認值。(很奇怪系統(tǒng)怎么默認是latin1的瑞典語排序方式)...
當我們按照原來的方式通過PHP存取MySQL數(shù)據(jù)庫時,就算設(shè)置了表的默認字符集為utf8并且通過UTF-8編碼發(fā)送查詢,你會發(fā)現(xiàn)存入數(shù)據(jù)庫的仍然是亂碼。問題就出在這個connection連接層上。解決方法是在發(fā)送查詢前執(zhí)行一下下面這句:
SET NAMES 'utf8';
它相當于下面的三句指令:
SET character_set_client = utf8;
SET character_set_results = utf8;
SET character_set_connection = utf8;
再試試看,正常了吧?^_^ Enjoy!
具體講
在你的查詢前加一行:
mysql_query("SET NAMES 'gb2312';",$this->con);
真應(yīng)該把手冊仔細看一遍.
和字符相關(guān)的變量中這幾個和sql很有關(guān)系:
character_set_client
character_set_connection
character_set_results
此外就是數(shù)據(jù)庫中對相應(yīng)字段設(shè)置的charact set,如果沒有對字段設(shè)置,缺省是table的charact set,table也沒有指定則缺省使用database的。
上面3個變量的作用是這樣的,client表示客戶端發(fā)送過來的字符集,results表示發(fā)送到客戶端的字符集(這兩個分開是因為發(fā)送過來和發(fā)送過去的不一定是同一個客戶端),connection則在客戶端和數(shù)據(jù)庫起一個連接作用。
具體是這樣:比如我在mysql命令行設(shè)置client為gbk,connection為utf8,results為gbk,數(shù)據(jù)庫為big5,
當我發(fā)送一個insert語句的時候,這個語句作為gbk代碼,先轉(zhuǎn)為utf8代碼(connection),再轉(zhuǎn)為big5(database)插入數(shù)據(jù)庫。
而運行一個select語句的時候,從數(shù)據(jù)庫得到的結(jié)果則相反的過程,由big5轉(zhuǎn)為utf8,再轉(zhuǎn)為gbk,你得到gbk的結(jié)果。
因此最主要的是讓client和results和你使用的客戶端一致。比如你的網(wǎng)頁是utf8編碼,你就要設(shè)置這兩個為utf8。
而在mysql命令行的時候,我用的是2000,需要設(shè)置為gbk
而我們用的set names XXX,實際上就是同時設(shè)置這3個變量為XXX。
在這樣的情況下,我們可以把一個數(shù)據(jù)庫中的不同表或不同字段設(shè)為不同的字符集,只要上面3個設(shè)置正確,就可以在數(shù)據(jù)庫中同時使用不同的字符集。
注意要保證你的數(shù)據(jù)庫中的字符已經(jīng)使用了正確的字符集,比如如果一開始你設(shè)置錯誤,插入數(shù)據(jù)后,本身數(shù)據(jù)的編碼就是不正確的,然后即使設(shè)置改回來,也不可能得到正確的顯示了。
還有一個是編碼互相之間的兼容性,如果一個字符在gbk中有,在utf8中沒有,那么在gbk-》utf8-》gbk的過程中,它就變成了“?”
再說一下具體解決的辦法。
首先要指定你的升級后的database及table及field的character set,一般來說我們用gb2312或者utf8的,如果不同時使用多種編碼,只要指定database就可以,可以在建庫的sql語句加上相應(yīng)的 character set,在phpMyAdmin里也可以修改。
然后是導(dǎo)入舊數(shù)據(jù)。首先要確定自己的數(shù)據(jù)文件的編碼。如果用phpMyAdmin導(dǎo)入,在界面上有文件編碼的選項,一定要和數(shù)據(jù)文件的編碼一致。
如果從mysql的命令行導(dǎo)入,就要自己設(shè)置上面說到的3個變量,set names xxx。
使用其它的客戶端程序一樣要注意。
這樣就可以讓舊數(shù)據(jù)轉(zhuǎn)入新數(shù)據(jù)庫后的編碼才是正確的,如果這一步錯了,后面不可能得到正確的顯示。
然后是自己的程序,在連接后就可以執(zhí)行一次set names xxx,根據(jù)你的網(wǎng)頁編碼而定。
-----------------------------------------
mysql 導(dǎo)入亂碼問題- -
mysql從4.1使用mysqldump導(dǎo)出數(shù)據(jù)并在4.0導(dǎo)入的時候會出現(xiàn)sql語句錯誤,并且所有數(shù)據(jù)變成亂碼。使用下面的參數(shù)就可以解決
mysqldump -uxunai -p --compatible=mysql40 --default-character-set=latin1 xunai>xunai.sql
mysql -uroot -p fmx < fmx3.sql -f --default-character-set=latin1
相關(guān)文章
用Jena將本體文件存入MySQL數(shù)據(jù)庫的實現(xiàn)方法
以下的文章主要介紹的是使用Jena,將本體文件存入MySQL數(shù)據(jù)庫的實際操作步驟2010-06-06