MySQL字元集亂碼

來源:互聯網
上載者:User

標籤:character   伺服器   資料庫   mysql   字串   

什麼是字元集?

    字元集是一套符號和編碼的規則,可以想象為二進位位和符號的轉換表。


MySQL支援的字元集

    MySQL資料庫可以支援多種字元集。

    MySQL字元集包括字元集(character set)和校對規則(collation)兩個概念。字元集是用來定義MySQL儲存字串的方式,校對規則則是用來定義了比較字串的方式。字元集和校對規則是一對多的關係。

    每個字元集至少對應一個校對規則。

# 查看支援的字元集mysql> SHOW CHARACTER SET;# 查看支援的校對規則mysql> SHOW COLLATION;


    MySQL字元集設定非常靈活,分別可以在伺服器級、資料庫級、表級、欄位級設定。

資料庫物件的字元集的指定有如下繼承關係:

Server -> Database -> Table -> Column

也就是說,如果某一級沒有顯示指定字元集,那麼將繼承上一級的字元集。

# 查看伺服器字元集相關的系統變數mysql> SHOW VARIABLES LIKE ‘%char%‘;

650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/57/0F/wKioL1SQVebgKuIHAANaVutXzkI147.jpg" title="34.png" alt="wKioL1SQVebgKuIHAANaVutXzkI147.jpg" />


亂碼問題?

MySQL處理串連時,外部串連發送過來的SQL請求會根據以下順序進行轉換:
character_set_client           //客戶串連所採用的字元集
|
character_set_connection  //MySQL串連字元集
|
character_set_database    //資料庫所採用的字元集(表,列)
|
character_set_results        //返回的結果所採用的字元集

  1. 我們告訴伺服器,我發送給你的資料是什麼編碼? character_set_client

  2. 如果發現和連接器指定的編碼不一致,要轉換為什麼編碼? character_set_connection

  3. 查詢的結果用什麼編碼? character_set_results

如果以上三者都為字元集N,可簡寫為: set names N;

下面通過執行個體來示範為什麼會亂碼?

# 建立一個表mysql> CREATE TABLE person (    -> id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,    -> name VARCHAR(30)    -> ) DEFAULT CHARSET utf8;# 然後執行下面3條命令, 可以簡寫為 set names utf8;set character_set_client=utf8;set character_set_connection=utf8;set_character_set_results=utf8;# 查看當前字元集設定mysql> show variables like ‘%char%‘;+--------------------------+----------------------------+| Variable_name            | Value                      |+--------------------------+----------------------------+| character_set_client     | utf8                       || character_set_connection | utf8                       || character_set_database   | latin1                     || character_set_filesystem | binary                     || character_set_results    | utf8                       || character_set_server     | latin1                     || character_set_system     | utf8                       || character_sets_dir       | /usr/share/mysql/charsets/ |+--------------------------+----------------------------+# 然後插入一條資料mysql> INSERT INTO person(name) VALUES(‘中文‘);# 查詢mysql> SELECT * FROM person;+----+--------+| id | name   |+----+--------+|  1 | 中文   |+----+--------+# 顯示結果是正常的。# 好,接下來,我們改變character_set_results 為 gbkmysql> set character_set_results=gbk;Query OK, 0 rows affected (0.04 sec)mysql> SELECT * FROM person;+----+------+| id | name |+----+------+|  1 |      |+----+------+

產生亂碼的根本原因就是:

各字元集系統變數不一致,導致進行字元集轉換。


    比如說:客戶機沒有正確地設定client字元集,導致原先的SQL語句被轉換成connection所指字元集,而這種轉換,可能是會丟失資訊的,如果client是utf8格式,那麼如果轉換成gb2312格式,這其中必定會丟失資訊,反之則不會丟失。一定要保證connection的字元集大於client字元集才能保證轉換不丟失資訊。同理,connection與results也是這樣。就像程式設計語言中的資料類型相互轉換時一樣,比如把double類型強制轉換成int類型,就會造成精度的丟失一樣。

    我們來仔細說明一下轉換的過程:

  • 向預設字元集為utf8的資料表插入utf8編碼的資料前沒有設定串連字元集,查詢時設定串連字元集為utf8
         – 插入時根據MySQL伺服器的預設設定,character_set_client、character_set_connection和character_set_results均為latin1;
         – 插入操作的資料將經過latin1=>latin1=>utf8的字元集轉換過程,這一過程中每個插入的漢字都會從原始的3個位元組變成6個位元組儲存;
         – 查詢時的結果將經過utf8=>utf8的字元集轉換過程,將儲存的6個位元組原封不動返回,產生亂碼。

  • 向預設字元集為latin1的資料表插入utf8編碼的資料前設定了串連字元集為utf8
         – 插入時根據串連字元集設定,character_set_client、character_set_connection和character_set_results均為utf8;
         --插入資料將經過utf8=>utf8=>latin1的字元集轉換,若未經處理資料中含有\u0000~\u00ff範圍以外的Unicode字元,會因為無法在latin1字元集中表示而被轉換為“?”(0×3F)符號,以後查詢時不管串連字元集設定如何都無法恢複其內容了。

綜上,終極解決方案如下:
1.首先要明確你的用戶端時候何種編碼格式,這是最重要的(IE6一般用utf8,命令列一般是gbk,一般程式是gb2312)
2.確保你的資料庫使用utf8格式,很簡單,所有編碼通吃。
3.一定要保證connection字元集大於等於client字元集,不然就會資訊丟失,比如: latin1 < gb2312 < gbk < utf8,若設定set character_set_client = gb2312,那麼至少connection的字元集要大於等於gb2312,否則就會丟失資訊
4.以上三步做正確的話,那麼所有中文都被正確地轉換成utf8格式儲存進了資料庫,為了適應不同的瀏覽器,不同的用戶端,你可以修改character_set_results來以不同的編碼顯示中文字型,由於utf8是大方向,因此web應用是我還是傾向於使用utf8格式顯示中文的。


總結
    根據上面的分析和建議,我們解決我們遇到問題應該使用什麼方法大家心裡應該比較清楚了。對,就是在建立database的時候指定字元集,不要去通過修改預設配置來達到目的,當然你也可以採用指定表的字元集的形式,但很容易出現遺漏,特別是在很多人都參與設計的時候,更容易紕漏。



http://www.cnblogs.com/zzwlovegfj/archive/2012/06/25/2560649.html

http://www.cnblogs.com/discuss/articles/1862248.html


本文出自 “Share your knowledge” 部落格,請務必保留此出處http://skypegnu1.blog.51cto.com/8991766/1591215

MySQL字元集亂碼

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.