數據庫零碎---mysql編碼設置,與亂碼分析 一般來說,亂碼的出現有2種原因,首先是由於編碼(charset)設置錯誤,導致浏覽器以錯誤的編碼來解析,從而出現了滿屏亂七八糟的“天書”, 其次是文件被以錯誤的編碼打開,然後保存,比如一個文本文件原先是GB2312編碼的,卻以UTF-8編碼打開再保存。要解決上述亂碼問題,首先需要知道 開發中哪些環節涉及到了編碼: 1、文件編碼:指的是頁面文件(.html,.php等)本身是以何種編碼來保 存的。記事本和Dreamweaver在打開頁面時候會自動識別文件編碼因而不太會出問題。而ZendStudio卻不會自動識別編碼,它只會根據首選項 的配置固定以某種編碼打開文件,如果工作時候一不注意,用錯誤編碼打開文件,做了修改之後一保存,亂碼就出現了。 2、 頁面申明編碼:在HTML代碼HEAD裡面,可以用<meta http-equiv="Content-Type" content="text/html; charset="XXX" />(這句一定要寫在<title>XXX</title>前面,否則會導致頁面一片空白(僅限IE+PHP))來告訴浏 覽器網頁采用了什麼編碼,目前中文網站開發中主要用的是GB2312和UTF-8兩種編碼。 3、數據庫連接編 碼:指的是進行數據庫操作時候以哪種編碼與數據庫傳輸數據,這裡需要注意的是不要與數據庫本身的編碼混淆,比如MySQL內部默認是latin1編碼,也 就是說Mysql是以latin1編碼來存儲數據,以其他編碼傳輸給Mysql的數據會被轉換成latin1編碼。(新版本的mysql 4.1以上應該以utf-8編碼存儲) 知道了WEB開發中哪些地方涉及到了編碼,也就知道了亂碼產生的原因:上述3項編碼設置不一致,由於各種編碼絕大部分是兼容ASCII的,所以英文符號不會出現,中文就倒霉了。下面是一些常見的錯誤情況與解決: 1、數據庫采用UTF8編碼,而頁面申明編碼是GB2312,這是最常見的產生亂碼的原因。這時候在PHP腳本裡面直接SELECT數據出來的就是亂碼,需要在查詢前先使用: mysql_query("SET NAMES GBK");或mysql_query("SET NAMES GB2312");來設定MYSQL連接編碼,保證頁面申明編碼與這裡設定的連接編碼一致(GBK是GB2312的擴展)。如果頁面是UTF-8編碼的 話,可以用: mysql_query("SET NAMES UTF8"); 注意是UTF8而不是一般用的UTF-8。假如頁面申明的編碼與數據庫內部編碼一致可以不設定連接編碼。 注:事實上MYSQL的數據輸入輸出比上面講的更復雜一些,MYSQL配置文件my.ini中定義了2個默認編碼,分別是[client]裡的 default-character-set和[mysqld]裡的default-character-set來分別設定默認時候客戶端連接和數據庫內 部所采用的編碼。我們上面指定的編碼其實是MYSQL客戶端連接服務器時候的命令行參數character_set_client,來告訴MYSQL服務 器接受到的客戶端數據是什麼編碼的,而不是采用默認編碼。 2、 頁面申明編碼與文件本身編碼不一致,這種情況很少發生,因為如果編碼不一致美工做頁面時候在浏覽器看到的就是亂碼了。更多時候是發布以後修改一些小 BUG,以錯誤編碼打開頁面然後保存導致的。或者是用某些FTP軟件直接在線修改文件,比如CuteFTP,由於軟件編碼配置錯誤而導致轉換錯了編碼。 3、 一些租用虛擬主機的朋友,明明上述3項編碼都設置正確了還是有亂碼。比方說網頁是GB2312編碼的,IE等浏覽器打開卻總是識別成UTF-8,網頁 HEAD裡面已經申明是GB2312了,手動修改浏覽器編碼為GB2312後頁面顯示正常。產生原因是服務器Apache設定了服務器全局的默認編碼,在 httpd.conf裡面加了AddDefaultCharset UTF-8。這時候服務器會首先發送HTTP頭給浏覽器,其優先級比頁面裡申明編碼高,自然浏覽器就識別錯了。解決辦法有2個,請管理員在配置文件自己的 虛機裡加上一條AddDefaultCharset GB2312來覆蓋全局配置,或者在自己目錄的.htaccess裡配置。 亂碼解決方法 要解決亂碼問題,首先必須弄清楚自己數據庫用什麼編碼。如果沒有指明,將是默認的latin1。 我們用得最多的應該是這3種字符集 gb2312,gbk,utf8。 那麼我們如何去指定數據庫的字符集呢?下面也gbk為例 【在MySQL Command Line Client創建數據庫】 mysql> CREATE TABLE `mysqlcode` ( -> `id` TINYINT( 255 ) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY , -> `content` VARCHAR( 255 ) NOT NULL -> ) TYPE = MYISAM CHARACTER SET gbk COLLATE gbk_chinese_ci; Query OK, 0 rows affected, 1 warning (0.03 sec) mysql> desc mysqlcode; +---------+-----------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------+-----------------------+------+-----+---------+----------------+ | id | tinyint(255) unsigned | NO | PRI | | auto_increment | | content | varchar(255) | NO | | | | +---------+-----------------------+------+-----+---------+----------------+ 2 rows in set (0.02 sec) 其中後面的TYPE = MYISAM CHARACTER SET gbk COLLATE gbk_chinese_ci; 就是指定數據庫的字符集,COLLATE (校勘),讓mysql同時支持多種編碼的數據庫。 當然我們也可以通過如下指令修改數據庫的字符集 alter database da_name default character set 'charset'. 客戶端以 gbk格式發送 ,可以采用下述配置: SET character_set_client='gbk' SET character_set_connection='gbk' SET character_set_results='gbk' 這個配置就等價於 SET NAMES 'gbk'。 現在對剛才創建的數據庫操作 mysql> use test; Database changed mysql> insert into mysqlcode values(null,'php愛好者'); ERROR 1406 (22001): Data too long for column 'content' at row 1 沒有指定字符集為gbk,插入時出錯 mysql> set names 'gbk'; Query OK, 0 rows affected (0.02 sec) 指定字符集為 gbk mysql> insert into mysqlcode values(null,'php愛好者'); Query OK, 1 row affected (0.00 sec) 插入成功 mysql> select * from mysqlcode; +----+-----------+ | id | content | +----+-----------+ | 1 | php愛好著 | +----+-----------+ 1 row in set (0.00 sec) 在沒有指定字符集gbk時讀取也會出現亂碼,如下 mysql> select * from mysqlcode; +----+---------+ | id | content | +----+---------+ | 1 | php??? | +----+---------+ 1 row in set (0.00 sec) 【在phpmyadmin創建數據庫,並指定字符集】 表類型根據自己需要選,這裡選MyISAM(支持全文檢索); 整理選擇 gbk_chinese_ci 也就是gbk字符集 gbk_bin 簡體中文, 二進制。gbk_chinese_ci 簡體中文, 不區分大小寫。 在剛才創建的數據庫插入數據庫 再浏覽時發現是亂碼 為什麼呢?是因為數據庫為gbk字符集,而我們操作時沒有指定為gbk 回到數據庫首頁 可以看到 mysql 連接校對默認的latin1_bin。我們將其改為gbk_chinese_ci 再插入一條數據。看,這條已經正常了 一句話 你數據庫用什麼編碼,在對數據庫操作之前就set names '你的編碼';