MySQL字符集

字符集mysql

從本質上來講,計算機只能識別二進制代碼,所以,不管是計算機程序仍是其處理的數據,最終都必須轉換成二進制碼,計算機才能認識a爲了使計算機不只能作科學計算,也能處理文字信息,人們想出了給每一個文字符號編碼以便於計算機識別處理的辦法,這就是計算機字符集的由來。本章將詳細介紹字符集的發展歷程以及MySQL中字符集的使用。程序員

字符集概述sql

簡單地說字符集就是一套文字符號及其編碼、比較規則的集合。20世紀60年代初期,美國標準化組織ANSI發佈了第一個計算機字符集 ASCII (American Standard Code for Informationnterchange),後來進一步變成了國際標準ISO-646。這個字符集採用7位編碼,定義了包括大小寫英文字母、阿拉伯數字和標點符號,以及33個控制符號等。雖然如今看來,這個美式的字符集很簡單,包括的符號也不多,但直到今天它依然是計算機世界裏奠定性的標準,其後制定的各類字符集基本都兼容ASCII字符集數據庫

ASCII以後,爲了處理不一樣的文字,各大計算機公司、各國政府、標準化組織等前後發明了幾百種字符集,如你們熟悉的ISO-8859系列GB 2312-80、GBK、BIG 5等。這些五花八門的字符集,從收錄的字符到編碼規則各不相同,給計算機軟件開發和移植帶來了很大困難。一個軟件要在使用不一樣文字的國家或地區發佈,必須進行本地化開發!基於這個緣由,統一字符編碼,成了 20世紀80年代計算機業的迫切須要和廣泛共識。緩存

9.2 Unicode 簡述服務器

爲了統一字符編碼,國際標準化組織 ISO (International Organization for Standardization)的一些成員國於1984年發起制定新的國際字符集標準,以容納全世界各類語言文字和符號。這個標準最後叫作「Universal Multiple-Octet Coded Character Set」,簡稱UCS,標準編號則定爲ISCM0646。ISO-10646標準採用4字節(32bit)編碼,所以簡稱UCS4。具體編碼規則是:網絡

.將代碼空間劃分爲組(group)、面(plane)、行(raw)和格(ceil);第1個字節表明組(group),第2個字節表明面(plane),第3個字節表明行(row),第4個字節表明格(ceil),並規定
字符編碼的第32位必須爲0,且每一個面(plane)的最後兩個碼位FFFEhFFFFh保留不用;所以,丨SO-1064共有128個羣組(0〜0x7F),每一個羣組有256個字面(00〜OjcFF),每一個字函數

深刻戌出性能

面有256行(00〜OxFF),每行包括256格(0〜OxFF),共有256* 128 = 32,768個字面,每一個字面有 256x256-2=65,534 個碼位,合計 65,534x32,768=2,147,418,丨丨2 個碼位。ui

SO-10646發佈之後,遭到了部分美國計算機公司的反對。1988年Xerox公司提議制定新的以16位編碼的統一字符集Unicode,並聯合Apple、丨BMDECSunMicrosoft
Novell等公司成立Unicode協會(The Unicode Consortium),併成立Unicode技術委員會(Unicode Technical Committee〉,專門負責Unicode文字的蒐集、整理和編碼,並於1991年推出了 Unicode 1.0。

 

都是爲了解決字符編碼統一問題,ISOUnicode協會卻推出了兩個不一樣的編碼標準,這顯然是不利的。後來f你們都認識到了這一點,通過雙方談判,1991年10月達成協議,ISOUnicode編碼併入ISO-10646的0組0字面,叫做基本多語言文字面(Basic Multi-丨ingualPlane.BMP),共有65,534個碼位,並根椐不一樣用途分爲若干區域。除BMP夕卜的32,767個字面又分爲輔助字面(supplementary planes)和專用字面(private use panes)兩部分,輔助字面用以收錄丨SCM0646後續蒐集的各國文字,專用字面供使用者自定義收錄ISO-10646未收錄的文字符號。其實,大部分用戶只使用BMP字面就足夠了,早期的丨SO-10646-1標準也只要求實現BMP字面,這樣只須要2字節來編碼就足夠了,Unicode也正是這麼作的,這叫做ISO-10646編碼的基本面形式,簡稱爲UCS-2編碼,UCS-2編碼轉換成UCS-4編碼也很容易,只要在前面加兩個取值爲0的字節便可。

ISO-10646的編碼空間足以容納人類從古至今使用過的全部文字和符號,但其實許多文字符號都已經不多使用了,超過99%的在用文字符號都編入了 BMP,所以,絕大部分狀況下,Unicode的雙字節編碼方式都能知足需求,而這種雙字節編碼方式比起ISO-10646的4字節原始編碼來講,在節省內存和處理時間上都具備優點,這也是Unicode編碼方式更流行的原
因。但若是萬一要使用ISO-10646 BMP字面之外的文字怎麼辦呢? Unicode提出了名爲UTF-16 或代理法(surrogates)的解決方案UTF 是 CS/Unicode Transformation Format 的縮寫s UTF-16的解決辦法是:對BMP字面的編碼保持二字節不變,對其餘字面的文字按必定規則將其32位編碼轉換爲兩個16位的Unicode編碼,其兩個字節的取值範圍分別限定爲0xD800OxDBFF 和 OxDCOOOxDFFF,所以,UTF-16 共有(4x256) x (4x256) =1,048,576個碼位。.

雖然UTF-16解決了 ISO-10646除BMP外第1〜15字面的編碼問題,但當時的計算機和網絡世界仍是ASCII的天下,只能處理單字節數據流,UTF-16在離開Unicode環境後,在傳輸和處理中.都存在問題。因而Unicode又提出了名爲UTF-8的解決方案,UTF-8按必定規則將一個ISO-10646或Unicode字元碼轉換成1〜4個字節的編碼,其中將ASCII碼(0〜0x7F)轉換成單字節編碼,也就是嚴格兼容ASCII字符集;UTF-8的2字節編碼,用以轉換ISO-10646標準0x0080〜0x07FFUCS-4原始碼:UTF-8的3字節編碼,用以轉換ISO-10646標準0x0800〜OxFFFFUCS-4原始碼:UTF-8的4字節編碼,用以轉換丨SO-10646標準0x00010000〜0001FFFF 的 UCS-4 原始碼。

上述各類編碼方式,看起來有點讓人迷惑。其實,ISO-10646只是給每個文字符號分配了一個4字節無符號整數編號(UCS-4),並未規定在計算機中如何去表示這個無符號整數編號。UTF-16和UTF-8就是其兩種變通表示方式。

ISCM0646與Unicode統一之後,兩個組織雖然都繼續發佈各自的標準,但兩者之間是—致的。因爲Unicode最先投入應用,其編碼方式更加普及,所以,許多人都知道Unicode,

但對ISO-10646卻瞭解很少。但因爲兩者是一致的,所以,區分ISO-10646和Unicode的意義也就不大了。如今,你們說UnicodeISO-10646, —般指的是同一個東西,只是Unicode
更直接、更普及罷了。兩者不一樣版本的對應關係以下。

 Unicode 2.0 等同於 ISO/丨EC 10646-1:1993。

 Unicode 3.0 等同於 ISO/IEC 10646- 1:2Q00。

» Unicode 4.0 等同於 ISO/IEC 10646:2003。

最後要說的是,UTF-16和UTF-32因字節序的不一樣,又有了 UTF-16BE(BigEndian)、UTF-16LE (Little Endian)和 UTF-32BE (Big Endian)、UTF-32LE (Little Endian)等,在此

不作進一步介紹。

3 漢字及一些常見字符集

 

在計算機發展的不一樣階段,我國也參照當時的國際標準和實際須要,制定了一些漢字字符集編碼標準,主要內容以下所示。

® GB 2312-80:全稱《信息交換用漢字編碼字符集基本集》,於1980年發佈。根據1SO/IEC 2022提供的字符編碼擴充規範,造成雙字節編碼的字符集。收錄了 6,763個經常使用漢字和682個非漢字圖形符號。

^ GB 13000:全稱《信息技術通用多八位編碼字符集(UCS)第一部分:體系結構與基本多文種平面》,於1993年發佈3根據丨SO/IEC 10646-1:1993,在CJK (中、曰、韓簡稱)統一漢字區和CJK統一漢字擴充區A,除收錄GB 2312-80外,還收錄了第一、三、五、7輔助集的所有漢字,共27,484個,以及一些偏旁部首等〇但013 13000推出後,幾乎沒有獲得業界的支持,也就成了一個形式上的標準。

^ GBK:全稱《漢字內碼擴展規範》1.0版,發佈於1995年。GBKGB2312內碼系統的基礎上進行了擴充,收錄了 GB 13000.1-1993的所有20902個CJK統一漢字,包括GB 2312的所有6,763個漢字。此外,它增補編碼了 52個漢字,13個漢字結構符(在ISO/IEC 10646.1: 2000中稱爲表意文字描述符)和一些經常使用部首與漢字部件。
GBK的內碼系統中GB 2312漢字所在碼位保持不便,這樣,保證了 GBKGB 2312的徹底兼容。同時,GBK內碼與GB 13000.1代碼 對應,爲GBKGB 13000,1

的轉換提供瞭解決辦法。有意思的是GBK並非一個強制性的國家標準,只是一個行業指導規範,並無強制力,但因爲獲得了 Microsoft Windows 95的支持而大爲流行。

^ GB 18030:全稱《信息技術信息交換用漢字編碼字符集、基本集的擴充》,發佈於2000 年3 根據丨SO/1EC 10646-1:2000,收錄了 1SO/IEC 10646.1: 2000 所有 27,484個CJK統一漢字,13個表意文字描述符、部分漢字部首和部件、歐元符號等GB 18030採用2字節或4字節編碼,其二字節編碼部分與GBK保持一致,所以GB 18030是GBK的超集,也徹底與GB 13000向上兼容,制定GB 18030也是爲了解決GBK強制力不夠的問題。

以上簡要介紹了幾種漢字字符集,下面將一些經常使用字符集的特色概括如表9-1所示。


9-1經常使用字符集比較

字符集

是否認長

編碼方式

其餘說明

ACSII

單字節7位編碼

最先的奠定字符

TSO-8859-l/latinl

單字節8位編碼

西歐字符集.常常被一些程序員用來轉碼

GB 2312-80

雙字節編碼

早期標準.不推薦再

GBK

雙字節編碼

雖然不是國標,但支持的系統很多

GB 18030

2字節或4字節編碼

開始有一些支持,但數據庫支持的還少見

UTF-32

4字節編碼

UCS4原始編碼,目前不多采用

UCS-2

2字節編碼

Windows 2000 內部用 UCS-2

UTF-36

2字節或4字節編碼

Java 和 Windows XP/NT 等內部使用 UTF-16

UTF-8

1〜4字節編碼

互聯網和UMX/Linux普遍支持的Unicode ^
符集;MySQLServer 也使用 UTF-8

 

4 怎樣選擇合適的字符集

對數據庫來講,字符集更加劇要,由於數據庫存儲的數據大部分都是各類文字,字符集對數據庫的存儲、處理性能,以及往後系統的移植、推廣都會有影響。

MySQL 5.0目前支持幾十種字符集,UTF-8是MySQL 5.0支持的惟一Unicode字符集,但版本是3.0,不支持4字節的擴展部分。面對衆多的字符集,咱們該如何選擇呢?

雖然沒有必定之規,但在選擇數據庫字符集時,能夠根據應用的需求,結合上面介紹的一些字符集的特色來權衡,主要考慮因素包括:

(1) 知足應用支持語言的需求,若是應用要處理各類各樣的文字,或者將發佈到使用不一樣語言的國家或地區,就應該選擇Unicode字符集。對MySQL來講,目前就是UTF-8。

(2) 若是應用中涉及已有數據的導入,就要充分考慮數據庫字符集對己有數據的兼容性》假如己有數據是GBK文字,若是選擇GB 2312-80爲數據庫字符集,就極可能出現某些文字
沒法正確導入的問題。

(3) 若是數據庫只須要支持-•般中文,數據量很大,性能要求也很高,那就應該選擇雙字節定長編碼的中文字符集,好比GBK。由於,相對於UTF-8而言,GBK比較「小」,每一個漢字只佔2個字節,而UTF-8漢字編碼須要3個字節,這樣能夠減小磁盤1/0、數據庫cache,以及網絡傳輸的時間,從而提升性能。相反,若是應用主要處理英文字符,僅有少許漢字數據,那麼選擇UTF-8更好,由於GBKUCS-二、UTF-I6的西文字符編碼都是2個字節,會形成很大沒必要要的開銷。

(4) 若是數據庫須要作大量的字符運算,如比較、排序等,選擇定長字符集可能更好,由於定長字符集的處理速度要比變長字符集的處理速度快。

(5) 若是全部客戶端程序都支持相同的字符集,應該優先選擇該字符集做爲數據庫字符集。這樣能夠避免因字符集轉換帶來的性能開銷和數據損失.

MySQL支持的字符集簡介

MySQL服務器能夠支持多神字符集,在同一臺服務器、同一個數據庫甚至同一個表的不一樣字段均可以指定使用不一樣的字符集,相比Oracle等其餘數據庫管理系統,在同一個數據庫只能使用相同的字符集,MySQL明顯存在更大的靈活性。

査看全部可用的字符集的命令是show character set:

或者査看informati〇n_schemaxharacter_set,能夠顯示全部的字符集和該字符集默認的校對規則。

對規則。

MySQL的字符集包括字符集(CHARACTER)和校對規則(COLLATION)兩個概念.
字符集是用來定義MySQL存儲字符串的方式,校對規則則是定義了比較字符串的方式。字
符集和校對規則是一對多的關係,MySQL支持30多種字符集的70多種校對規則》

每一個字符集至少對應一個校對規則^能夠用「SHOW COLLATION LIKE •***';」命令或
者査看information_schema.COLLATIONS。査看相關字符集的校對規則。校對規則命名約定:它們以其相關的字符集名開始,一般包括一個語言名,而且以(大小寫不敏感)、_cs (大小寫敏感)或_bin (二元,即比較是基F字符編碼的值而與language無關)結束。

例如,上面例子中GBK的校對規則,其中gbk_ChineSe_Ci是默認的校對規則,大小寫不敏感的,gbk_bin按照編碼的值進行比較,是大小寫敏感的,

K面的這個例子中,若是指定_A’和_a'按照gbk_ChineSe_d校對規則進行比較,則認爲兩個字符是相同的,若是按照gbk_bin校對規則進行比較,則認^兩個字符是不一樣的。咱們事先須要確
認應用的需求,是須要按照什麼樣的排序方式,是否須要區分大小寫,以肯定校對規則的選擇.


MySQL字符集的設置

MySQL的字符集和校對規則有4個級別的默認設置:服務器級、數據庫級、表級和字段級,它們分別在不一樣的地方設置,做用也不相同。

6.1服務器字符集和校對規則

服務器字符集和校對,在MySQL服務啓動的時候肯定

能夠在my.cnf中設置:

[mysqld]

default-character-set=gbk

或者在啓動選項中指定:

mysqld --default-character-set-gbk

或者在編譯的時候指定:

./configure --with-charset=gbk

 

若是沒有特別的指定服務器字符集,默認使用丨atinl做爲服務器字符集。上面3種設置的方式都只指定了字符集,沒有指定校對規則,這樣是使用該字符集默認的校對規則,若是要使用該字符集的非默認校對規則,則須要在指定字符集的N時指定校對規則。

司以用「show variables like 'character_set_server’;」命令査詢當前服務器的字符集和校對

mysql> show variables like 'character_set_server';

+ * + +

I Variable_name | Value |

+ — + +

I character_set_server 卜 gbk |

 

1 row in set (0.00 sec)

mysql> show variables like 1collation_server1;

+ +- +

I Variable_name | Value |

+ + +

I collation_server 1 gbk_chinese_ci |

+ + +

1 row in set (0.00 sec)

6.2數據庫字符集和校對規則。

數據庫的字符集和校對規則在建立數據庫的時候指定,也能夠在建立完數據庫後經過「alter database」命令進行修改。須要注意的是,若是數據庫裏已經存在數據,由於修改字符集並不能將已有的數據按照新的字符集進行存放,因此不能經過修改數據庫的字符集直接修改數據的內容,在9.7小節中經過一個具體的例子介紹了字符集的修改方法。

設置數據庫字符集的規則是:

9 若是指定了字符集和校對規則,則使用指定的字符集和校對規則;

« 若是指定了字符集沒有指定校對規則,則使用指定字符集的默認校對規則;

^ 若是沒有指定字符集和校對規則,則使用服務器字符集和校對規則做爲數據庫的字
符集和校對規則^

推薦在建立數據庫的時候明確指定字符集和校對規則,避免受到默認值的影響。

要顯示當前數據庫的字符集和校對規則,可使用「show variables like’ character_set_
database •」和 「showvariables like* collation_database_」 命令査看:9.6.3表字符集和校對規則

表的字符集和校對規則在建立表的時候指定,能夠經過alter table命令進行修改,一樣,
若是表中已有記錄,修改字符集對原有的記錄並無影響f不會按照新的字符集進行存放。
表的字段仍然使用原來的字符集。

 

設置表的字符集的規則和上面基本相似:

若是指定了字符集和校對規則,使用指定的字符集和校對規則;

9 若是指定了字符集沒有指定校對規則,使用指定字符集的默認校對規則;

^ 若是沒有指定字符集和校對規則,使用數據庫字符集和校對規則做爲表的字符集和
校對規則。

推薦在建立表的時候明確指定字符集和校對規則,避免受到默認值的影響。要顯示錶的
字符集和校對規則,可使用show create table命令査看:

 

9.6.4列字符集和校對規則

MySQL能夠定義列級別的字符集和校對規則,主要是針對相同的表不一樣字段須要使用
不一樣的字符集的狀況,應該說通常遇到這種狀況的概率比較小,這只是MySQL提供給咱們
一個靈活設置的手段。

列字符集和校對規則的定義能夠在建立表時指定,或者在修改表時調整,若是在建立表
的時候沒有特別指定字符集和校對規則,則默認使用表的字符集和校對規則。

9.6.5鏈接字符集和校對規則

上面4種設置方式,肯定的是數據保存的字符集和校對規則,對於實際的應用訪問來講,還存在客戶端和服務器之間交互的字符集和校對規則的設置。

對於客戶端和服務器的交互操做,MySQL提供了 3個不一樣的參數:characteiLsetjlieiitcharacter_set_connectioncharaeter_set_results,分別表明客戶端、鏈接和返回結果的字符集,一般狀況下,這3個字符集應該是相同的,才能夠確保用戶寫入的數據能夠正確地讀出,特別是對於中文字符,不一樣的寫入字符集和返回結果字符集將致使寫入的記錄不能正確讀出。
一般狀況下,不會單個地設置這3個參數,能夠經過如下命令:

SET NAMES ***;

來設置鏈接的字符集和校對規則,這個命令能夠同時修改這3個參數的值。使用這個方法修改鏈接的字符集和校對規則,須要應用每次鏈接數據庫後都執行這個命令。

另一個更簡便的辦法,是在my.cnf中設置如下語句:

[mysql]

default-character-set=gbk

 

這樣服務器啓動後,全部鏈接默認就是使用GBK字符集進行鏈接的,而不須要在程序中再執行set names命令。

另外,字符串常量的字符集也是由character_set_connection參數來指定的。

能夠經過「Lcharset nameystring' [COLLATE collation name]」命令強制字符串的字符集和校對規則。例如

selectgbk 1字符集丨;
select 1 字符集’;

一般狀況下,基本不須要用戶強制指定字符串字符集。

9.7 字符集的修改步驟

若是在應用開始階段沒有正確的設置字符集,在運行一段時間之後才發現存在不能知足
要求須要調整,又不想丟棄這段時間的數據,那麼就須要進行字符集的修改。字符集的修改
不能直接經過 「alter database character set ***」 或者 「alter table tablename character set ***」

命令進行,這兩個命令都沒有更新已有記錄的字符集,而只是對新建立的表或者記錄生效。
已有記錄的字符集調整,須要先將數據導出,通過適當的調整從新導入後纔可完成。

如下模擬的是將latinl字符集的數據庫修改爲GBK字符集的數據庫的過程。

導出表結構:

mysqldump -uroot -p --default-character-set=gbk -d databasename>createtab.sql

其中-default-character-set=gbk表示設置以什麼字符集鏈接,-d表示只導出表結構,不導

出數據。

手工修改createtab.sql中表結構定義中的字符集爲新的字符集。

確保記錄再也不更新,導出全部記錄。

mysqldump -uroot 一p --quick ——no-create-info --extended-insert --default-char ac ter- set-lat ini databasename> data.sql

v* -quick:該選項用於轉儲大的表。它強制mysqldump從m務器一次一行地檢索表中的行而不是檢索全部行,並在輸出前將它緩存到內存中。

9 -extended-insert:使用包括幾個VALUES列表的多行INSERT語法。這樣使轉儲文件更小,重栽文件時能夠加速插入。

-no-create^info:不寫從新建立每一個轉儲表的CREATE TABLE語句。

 --de&uk-character-set=latinl:按照原有的字符集導出全部數據,這樣導出的文件中,全部中文都是可見的,不會保存成孔碼。

(4)打開 data.sql,將 SET NAMES latinl 修改爲 SETNAMES gbk。

(5>使用新的字符集建立新的數據庫。

create database databasename default charset gbk;

建立表,執行 createtab.sql。

mysql -uroot -p databasename < createtab•sql

導入數據,執行data.sql

mysql -uroot -p databasename < data.sql

注意:選擇目標字符集的時候,要注意最好是源字符集的超級,或者肯定比源字符集的字庫更大,不然若是目標字符集的字庫小於源字符集的字庫,那麼目標字符集中不支持的字符倒入後會變成亂碼,丟失一部分數據。例如,GBK字符集的字庫大於GB 2312字符集,那麼GBIC字符集的數據,若是導入GB2312數據庫中,就會丟失GB 2312中不支持的那部分漢字的數據。

 小結

基本概念

• 字符(Character)是指人類語言中最小的表義符號。例如’A'、’B'等;
• 給定一系列字符,對每一個字符賦予一個數值,用數值來表明對應的字符,這一數值就是字符的編碼(Encoding)。例如,咱們給字符’A'賦
予數值0,給字符’B'賦予數值1,則0就是字符’A'的編碼;
• 給定一系列字符並賦予對應的編碼後,全部這些字符和編碼對組成的集合就是字符集(Character Set)。例如,給定字符列表爲
{’A',’B'}時,{’A'=>0, ‘B’=>1}就是一個字符集;
• 字符序(Collation)是指在同一字符集內字符之間的比較規則;
• 肯定字符序後,才能在一個字符集上定義什麼是等價的字符,以及字符之間的大小關係;
• 每一個字符序惟一對應一種字符集,但一個字符集能夠對應多種字符序,其中有一個是默認字符序(Default Collation);
• MySQL中的字符序名稱聽從命名慣例:以字符序對應的字符集名稱開頭;以_ci(表示大小寫不敏感)、_cs(表示大小寫敏感)或_bin(表示按
編碼值比較)結尾。例如:在字符序「utf8_general_ci」下,字符「a」和「A」是等價的;

MySQL字符集設置

• 系統變量:
– character_set_server:默認的內部操做字符集
– character_set_client:客戶端來源數據使用的字符集
– character_set_connection:鏈接層字符集
– character_set_results:查詢結果字符集
– character_set_database:當前選中數據庫的默認字符集
– character_set_system:系統元數據(字段名等)字符集
– 還有以collation_開頭的同上面對應的變量,用來描述字符序。

• 用introducer指定文本字符串的字符集:
– 格式爲:[_charset] ’string’ [COLLATE collation]
– 例如:
SELECT _latin1 ’string’;
SELECT _utf8 ‘你好’ COLLATE utf8_general_ci;
– 由introducer修飾的文本字符串在請求過程當中不通過多餘的轉碼,直接轉換爲內部字符集處理。

MySQL中的字符集轉換過程

1. MySQL Server收到請求時將請求數據從character_set_client轉換爲character_set_connection;
2. 進行內部操做前將請求數據從character_set_connection轉換爲內部操做字符集,其肯定方法以下:
- 使用每一個數據字段的CHARACTER SET設定值;
- 若上述值不存在,則使用對應數據表的DEFAULT CHARACTER SET設定值(MySQL擴展,非SQL標準);
- 若上述值不存在,則使用對應數據庫的DEFAULT CHARACTER SET設定值;
- 若上述值不存在,則使用character_set_server設定值。

 

3. 將操做結果從內部操做字符集轉換爲character_set_results。


咱們如今回過頭來分析下咱們產生的亂碼問題:
a 咱們的字段沒有設置字符集,所以使用表的數據集
b 咱們的表沒有指定字符集,默認使用數據庫存的字符集
c 咱們的數據庫在建立的時候沒有指定字符集,所以使用character_set_server設定值
d 咱們沒有特地去修改character_set_server的指定字符集,所以使用mysql默認
e mysql默認的字符集是latin1,所以,咱們使用了latin1字符集,而咱們character_set_connection的字符集是UTF-8,插入中
文亂碼也再所不免了。

常見問題解析
• FAQ-1 向默認字符集爲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)符號,之後查詢時無論鏈接字符集設置如何都沒法恢復其內容了。轉換過程以下圖:

檢測字符集問題的一些手段 • SHOW CHARACTER SET; • SHOW COLLATION; • SHOW VARIABLES LIKE ‘character%’; • SHOW VARIABLES LIKE ‘collation%’; • SQL函數HEX、LENGTH、CHAR_LENGTH • SQL函數CHARSET、COLLATION 使用MySQL字符集時的建議 • 創建數據庫/表和進行數據庫操做時儘可能顯式指出使用的字符集,而不是依賴於MySQL的默認設置,不然MySQL升級時可能帶來很大困 擾; • 數據庫和鏈接字符集都使用latin1時,雖然大部分狀況下均可以解決亂碼問題,但缺點是沒法以字符爲單位來進行SQL操做,通常情 況下將數據庫和鏈接字符集都置爲utf8是較好的選擇; • 使用mysql CAPI(mysql提供C語言操做的API)時,初始化數據庫句柄後立刻用mysql_options設定MYSQL_SET_CHARSET_NAME屬性爲 utf8,這樣就不用顯式地用SET NAMES語句指定鏈接字符集,且用mysql_ping重連斷開的長鏈接時也會把鏈接字符集重置爲utf8; • 對於mysql PHP API,通常頁面級的PHP程序總運行時間較短,在鏈接到數據庫之後顯式用SET NAMES語句設置一次鏈接字符集便可; 但當使用長鏈接時,請注意保持鏈接通暢並在斷開重連後用SET NAMES語句顯式重置鏈接字符集。 其餘注意事項 • my.cnf中的default_character_set設置隻影響mysql命令鏈接服務器時的鏈接字符集,不會對使用libmysqlclient庫的應用程序產生 任何做用! • 對字段進行的SQL函數操做一般都是之內部操做字符集進行的,不受鏈接字符集設置的影響。 • SQL語句中的裸字符串會受到鏈接字符集或introducer設置的影響,對於比較之類的操做可能產生徹底不一樣的結果,須要當心! 總結 根據上面的分析和建議,咱們解決咱們遇到問題應該使用什麼方法你們內心應該比較清楚了。對,就是在建立database的時候指定字符 集,不要去經過修改默認配置來達到目的,固然你也能夠採用指定表的字符集的形式,但很容易出現遺漏,特別是在不少人都參與設計的時 候,更容易紕漏。 雖然不提倡經過修改mysql的默認字符集來解決,但對於如何去修改默認字符集,我這裏仍是給出一些方法,僅供你們參考。 MySQL默認字符集MySQL對於字符集的指定能夠細化到一個數據庫,一張表,一列.傳統的程序在建立數據庫和數據表時並無使用那麼複雜的配置,它們用的 是默認的配置. (1)編譯MySQL 時,指定了一個默認的字符集,這個字符集是 latin1; (2)安裝MySQL 時,能夠在配置文件 (my.ini) 中指定一個默認的的字符集,若是沒指定,這個值繼承自編譯時指定的; (3)啓動mysqld 時,能夠在命令行參數中指定一個默認的的字符集,若是沒指定,這個值繼承自配置文件中的配置,此時 character_set_server 被設定爲這個默認的字符集; (4)安裝 MySQL選擇多語言支持,安裝程序會自動在配置文件中把default_character_set 設置爲 UTF-8,保證缺省狀況下全部的數據 庫全部表的全部列的都用 UTF-8 存儲。查看默認字符集 (默認狀況下,mysql的字符集是latin1(ISO_8859_1),如何查看在上面咱們已經給出了相關命令修改默認字符集(1) 最簡單的修改方法,就是修改mysql的my.ini文件中的字符集鍵值, 如 default-character-set = utf8 character_set_server = utf8 修改完後,重啓mysql的服務(2) 還有一種修改字符集的方法,就是使用mysql的命令 mysql> SET character_set_client = utf8 ; mysql> SET character_set_connection = utf8 ; mysql> SET character_set_database = utf8 ; mysql> SET character_set_results = utf8 ; mysql> SET character_set_server = utf8 ; mysql> SET collation_connection = utf8 ; mysql> SET collation_database = utf8 ; mysql> SET collation_server = utf8 ; 設置了表的默認字符集爲utf8而且經過UTF-8編碼發送查詢,存入數據庫的仍然是亂碼。那connection鏈接層上可能出了問題。解決方 法是在發送查詢前執行一下下面這句: SET NAMES 'utf8';它至關於下面的三句指令:SET character_set_client = utf8;SET character_set_results = utf8;SET character_set_connection = utf8;

相關文章
相關標籤/搜索