mysql 亂碼產生探討

mysql 亂碼產生探討

實驗一 
1。首先,在下面情況下: 
mysql> show variables like 'character_set_%'; 
+--------------------------+---------------------------------------+
| Variable_name            | Value                                 |
+--------------------------+---------------------------------------+
| character_set_client     | latin1                                |
| character_set_connection | latin1                                |
| character_set_database   | latin1                                |
| character_set_filesystem | binary                                |
| character_set_results    | latin1                                |
| character_set_server     | latin1                                |
| character_set_system     | utf8                                  |
| character_sets_dir       | D:\Programs\mysql5045\share\charsets\ |
+--------------------------+---------------------------------------+ 
建表,並加入3個記錄:大,阿,愛 
 
2。set character_set_results=utf8; 
則顯示:(cmd窗口中,cmd窗口代碼頁936) 

大->麓貿 
阿->擄壟 
愛->擄廬 
 
分析編碼: 
 
大U:5927,GBK:B4F3
麓U:9E93,GBK:C2B4
貿U:8D38,GBK:C3B3


阿U:963F,GBK:B0A2
擄U:63B3,GBK:C2B0
壟U:5784,GBK:C2A2

愛U:7231,GBK:B0AE
擄U:63B3,GBK:C2B0
廬U:5E90,GBK:C2AE 
 
3。改成
set character_set_results=gb2312; 
一樣是亂碼 
 
4。結論: 
  • 亂碼的產生,是由於單字節向多字節擴展引起的。B0A2 如果作爲單字節存儲(雖然表示的是1個漢字,但是因爲是latin1單字節,所以認爲B0A2是不相關的兩個字符),此時如果把character_set_results變成utf8多字節,那麼數據庫mysql 會試圖把每個單字節擴展成近似的(不知道具體的算法)雙字節。所以亂碼 
  • 反之,多字節向單字節轉換時,不會有變動,僅僅是原來2各字節表示的一個字符‘B0A2’變成了表示兩個字符而已。---- 這個說法經驗證是錯誤的。 
  • 數據庫存儲的內容(磁盤上,內存裏)不會受character_set_的影響,只是提交,查詢的過程中,受到字符集轉換的影響。
 

實驗二 
1。 
create table y (id int, name char(4)) default charset gb2312; 
 
2。在不改變默認character_set_ 是 latin1的情況下,如果插入一個漢字,則顯示亂碼 
 
3。改成 set names gb2312,顯示沒問題(cmd窗口中,cmd窗口代碼頁936) 
 
4。我原以爲如上述實驗1種的結論2,“多字節向單字節轉換時,不會有變動”。所以我開始以爲,set names gb2312 後,把 character_set_results 改成latin1,顯示不會出問題。結果, 
一個漢字,則顯示一個問號;兩個漢字,則顯示兩個問號的亂碼(估計一個問號代表一個字符)。也就是說,改成character_set_results = latin1後,多字節的數據存儲,在向單字節表示轉換時,mysql把提出的信息“縮水了”,把兩個字節,換算成了一個字節。 
 
5。如何,不讓mysql縮水呢,我想到了character_set_results = binary;結果,果然顯示正常。 
 
PS 
  • 開發的使用mysql的應用程序,是對應作爲獨立的使用自己的character_set_client的字符集的
  • cmd 窗口登陸mysql,也是作爲一個獨立的,擁有自己character_set_client變量的應用
  • 同理,打開不同的cmd窗口,都擁有獨自的character_set_client變量
 

實驗三 07/16/2010 
 
1。建一個默認字符集utf8的表(用navicat ,在utf8的界面下 代碼頁65001),並且插入utf8編碼的漢字‘大學’ 
2。切換到mysql console(代碼頁936) 
3。set names gbk; 然後顯示剛纔所建立的表,能正確現實嗎? ---- 能!當然,只把character_set_results 成 gbk,也能正常顯示 
 

實驗四 
 
1。mysql console(代碼頁936)建立一個表x3 ( name char(32) ),默認字符集 default charset gbk; 
2。默認環境變量   
| character_set_client     | latin1
| character_set_connection | latin1
| character_set_database   | latin1
| character_set_filesystem | binary
| character_set_results    | latin1
| character_set_server     | latin1
| character_set_system     |utf8 //不知道對以下過程、分析是否有影響 
 
character_set_client   character_set_connection character_set_results 是latin1的情況下,插入數據:insert x3 values('大'); 
顯示:ERROR 1406 (22001): Data too long for column 'name' at row 1 
3。set character_set_client=gbk;然後 insert x3 values('大');插入沒有問題,但顯然,數據經過 (character_set_connection=latin1)的轉換,已經是有損了 
4。不管 character_set_results 設不設成 gbk,都不能正常顯示結果 
5。set names gbk;則插入現實都沒問題。並且此時,一個uf8字符集的表的顯示也沒問題(實驗三)。而且進行連接查詢,亦沒問題。 
6。當然,set names utf8,如果在一個utf8的軟件界面上,顯示輸出也沒問題(navicat 驗證了) 
7。如果設成 set names binary。在936代碼頁的顯示界面上,可以看到,x3依然可以正常現實;但像實驗三那樣建的表就不能正常顯示了。 
-------- 
分析第2點:Data too long for column 'name' at row 1 
  1. 我的char 夠長,插入數據夠短,所以不是數據太長了。也就是說這個提示是錯誤的。
  2. 我知道,如果表x3 默認字符集 是latin1的話,插入是沒問題的(一直以來都是這麼玩的);這是因爲,雖然輸入端mysql console 代碼頁是936,但因爲三個主環境變量character_set_c%都是latin1,所以,mysql 認爲insert x3 values('大') 輸入的是2個字符(當然,如果從utf8界面輸入,可能就認爲是輸入3個字符)。存儲的自然也是2個字符。顯示的時候也是顯示的2個字符,只不過936代碼頁把這兩個字符自然組合,顯示成漢字了(早期dos環境常見現象)。
  3. 當默認字符集變爲gbk的時候,發生了什麼?不知道。。。。。 
 

實驗五 
一個很狗屎的問題出現了:936 mysql console 
環境變量如 實驗一.1。 
 
mysql> set names latin1;
Query OK, 0 rows affected (0.00 sec)

mysql> create table x4 (
    -> name char(32) primary key);
Query OK, 0 rows affected (0.09 sec)

mysql> drop table x4;
Query OK, 0 rows affected (0.06 sec)

mysql> create table x4 (
    -> name char(32) primary key) default charset utf8;
Query OK, 0 rows affected (0.10 sec)

mysql> insert x4 values('乃');
Query OK, 1 row affected (0.04 sec)

mysql> create table x5 (
    -> name char(32) primary key) default charset gbk;
Query OK, 0 rows affected (0.09 sec)

mysql> insert x5 values('乃');
ERROR 1406 (22001): Data too long for column 'name' at row 1
mysql>
 
 
結論,我實在對實驗四中分析的第3點做出結論。character_set_system utf8 有關 ~~ 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章