1. Collations
Collations翻成中文是“校驗(yàn)”,在網(wǎng)頁(yè)開(kāi)發(fā)的過(guò)程中,這個(gè)詞匯,只在 Mysql里使用,主要作用是指導(dǎo)Mysql對(duì)字符的比較,比如, ASCII字符集里,Collations規(guī)定了a小于b,a等于a,以及a是否等于A之類(lèi)的。通常,大家基本可以忽略Collations的存在,因?yàn)槊總(gè)字符集都有一個(gè)默認(rèn)的Collations,通常,使用默認(rèn)的Collations就可以了。以字節(jié)為編碼單元,沒(méi)有字節(jié)序的問(wèn)題。UTF-16以?xún)蓚(gè)字節(jié)為編碼單元,在解釋一個(gè)UTF-16文本前,首先要弄清楚每個(gè)編碼單元的字節(jié)序。例如收到一個(gè)“奎”的Unicode編碼是594E,“乙”的Unicode編碼是4E59。如果我們收到UTF-16字節(jié)流“594E”,那么這是“奎”還是“乙”?<o:p></o:p>
2.字符集
與這對(duì)比的是,字符集是個(gè)更廣的概念,即使是Windows下普通的文本文件,也滲及到字符集的問(wèn)題。不同的字符集,規(guī)定了不同的字符的編碼方式。一個(gè) character set (字符集)是一組符號(hào)和編碼,比如,ASCII字符集,包括的字符有:數(shù)字,大小寫(xiě)字母,分號(hào)、換行之類(lèi)的符號(hào),編碼方式是用一個(gè)7bit表示一個(gè)字符(A的編碼是65,b的編碼是98)。ASCII只規(guī)定了英文字母的編碼,非英文語(yǔ)言不能用ASCII編碼表示,為此,不同的國(guó)家,都為自己的語(yǔ)言做了編碼,比如,我們國(guó)家,就有GB2312編碼。但每個(gè)國(guó)家之間的編碼不同,也存在著一些跨平臺(tái)的問(wèn)題,為此,一些國(guó)際化標(biāo)準(zhǔn)組織,就制定了一些國(guó)際通用的編碼,最常用的就是UTF8了。ASCII只對(duì)英文符號(hào)和英文字母做了編碼,GB2312對(duì)英文符號(hào),英文字母,漢字做了編碼,UTF8對(duì)世界上所有的語(yǔ)言文字做了編碼,所以,GB1212的字符包含了ASCII字符,UTF8包含了GB2312字符。由此可見(jiàn),UTF8是所含最廣字符的字符集,所以,在一些多語(yǔ)言的WEB系統(tǒng)中,一般用UTF8字符集(PHPMyAdmin使用UTF8編碼)。
任何文本的存儲(chǔ),都滲及到字符集的概念。包括數(shù)據(jù)庫(kù),也包括普通的文本文件。
主要術(shù)語(yǔ):
字符:漢字,英文字母,標(biāo)點(diǎn)符號(hào),拉丁文等等。
編碼:將字符轉(zhuǎn)換成計(jì)算機(jī)存儲(chǔ)的格式,比如,A用65表示
字符集:一組字符以及對(duì)應(yīng)的編碼方式。
a. Mysql的字符集
Mysql目前支持多字符集,并且,支持在不同的字符集之間轉(zhuǎn)換(便于移植和支持多語(yǔ)言)。
Mysql可以設(shè)置服務(wù)器級(jí)字符集、數(shù)據(jù)庫(kù)級(jí)字符集、數(shù)據(jù)表級(jí)字符集、表列的字符集,實(shí)際上,最終使用字符集的地方是存儲(chǔ)字符的列,比如,你設(shè)置 table1中col1列是字符類(lèi)型,col1才用到了字符集,如果table1表的col2列是int類(lèi)型,col2不使用字符集的概念。
服務(wù)器級(jí)字符集、數(shù)據(jù)庫(kù)級(jí)字符集、數(shù)據(jù)表級(jí)字符集都是為列的字符集做默認(rèn)選項(xiàng)的。
Mysql一定有一個(gè)字符集,可以通過(guò)啟動(dòng)時(shí)加參數(shù)指定,也可以編譯時(shí)指定,也可以在配置文件里指定。Mysql服務(wù)器字符集,只是做為數(shù)據(jù)庫(kù)級(jí)的默認(rèn)值。創(chuàng)建數(shù)據(jù)庫(kù)時(shí),你可以指定字符集,如果沒(méi)指定,就使用服務(wù)器的字符集。同理,創(chuàng)建表時(shí),你可以指定表級(jí)的字符集,如果沒(méi)指定,使用數(shù)據(jù)庫(kù)的字符集做為表的字符集。創(chuàng)建列時(shí),你可以指定某列的字符集,如果沒(méi)指定,就使用表的字符集。
通常情況下,您只需設(shè)置服務(wù)器級(jí)的字符集,其它的數(shù)據(jù)庫(kù)級(jí),表級(jí),以及列級(jí)的字符集,都繼承自服務(wù)器級(jí)字符集。
由于UTF8是最廣的字符集,所以,一般情況下,我們?cè)O(shè)置Mysql服務(wù)器級(jí)的字符集為UTF8!
b. 普通文本的字符集問(wèn)題
任何文本的存儲(chǔ),都存在著字符集的問(wèn)題,普通文本文件也不例外。
Windows2000+的系統(tǒng)中,打開(kāi)記事本,“保存為…”對(duì)話框,就有一個(gè)選項(xiàng),可以讓你選擇存儲(chǔ)文本的編碼方式。
通常情況下,大家都使用Windows2000+的系統(tǒng),都使用默認(rèn)的編碼,所以,不會(huì)碰到字符集的問(wèn)題。
Windows下,保存文本文件時(shí),可以選擇編碼方式,但打開(kāi)文本文件時(shí),都是自動(dòng)判斷編碼方式的。網(wǎng)上有一個(gè)用Windows2000+的記事本玩移動(dòng),聯(lián)通的笑話,大家可以搜搜,就是因?yàn)閃indows在打開(kāi)文本文件時(shí),編碼判斷錯(cuò)誤引起的問(wèn)題。
因?yàn)樽詣?dòng)判斷編碼有時(shí)會(huì)錯(cuò)誤,所以,有的文本文件,規(guī)定了如何識(shí)別自身所使用的編碼。HTML文件就是一個(gè)這樣的例子。>
HTML是文本文件。存儲(chǔ)HTML文件的時(shí)候,需要使用一個(gè)編碼,并且,在HTML文件里,也使用HTML語(yǔ)法,指定了該文件所使用的編碼(比如< meta http-equiv="content-type" content="text/html; charset=UTF-8">)。如果HTML文件沒(méi)有指定編碼,則瀏覽器自動(dòng)識(shí)別文件的編碼。如果HTML指定了編碼,則瀏覽器使用HTML指定的編碼。
通常情況下,HTML文件指定的charset和HTML文件自身的編碼是一致的,但也有不一致的情況,如果不一致,就會(huì)導(dǎo)致網(wǎng)頁(yè)亂碼(此處亂碼,只和文本文件有關(guān),和數(shù)據(jù)庫(kù)無(wú)關(guān)。)使用專(zhuān)門(mén)的網(wǎng)頁(yè)編輯工具(比如Dreamwave),會(huì)自動(dòng)根據(jù)網(wǎng)頁(yè)中的charset值來(lái)編碼文件。
c. php+mysql的字符集問(wèn)題
PHP最終生成的是文本文件,但他要取數(shù)據(jù)庫(kù)里的文本,或?qū)⑽谋敬孢M(jìn)數(shù)據(jù)庫(kù)
由于Mysql支持多字符集,默認(rèn)情況下,Mysql不知道PHP發(fā)給他的是什么編碼的字符,所以,Mysql要求客戶(hù)端(PHP)告訴他存取的字符集是什么。
PHP通過(guò)設(shè)置character_set_client,告訴Mysql,PHP存進(jìn)數(shù)據(jù)庫(kù)的是什么編碼方式。
PHP通過(guò)設(shè)置character_set_results,告訴Mysql,PHP需要取什么樣編碼的數(shù)據(jù)。
PHP通過(guò)設(shè)置character_set_connection,告訴Mysql,PHP查詢(xún)中的文本,使用什么編碼。
MYSQL使用設(shè)置的編碼方式存儲(chǔ)文本。
假設(shè)Mysql使用setserver來(lái)存儲(chǔ)文本,PHP的character_set_client是setclient,PHP的 character_set_results是setresult。那么,Mysql將PHP發(fā)來(lái)的文本,從setclient編碼方式,轉(zhuǎn)換成 setserver編碼方式,再存入數(shù)據(jù)庫(kù),如果PHP取文本,Mysql將文本從setserver轉(zhuǎn)換成setresult,再發(fā)送給PHP。
PHP文件(最終生成的HTML文件)本身有個(gè)編碼,如果Mysql傳過(guò)來(lái)的編碼,與PHP文件自身的編碼不同,那么,整個(gè)網(wǎng)頁(yè),必然亂碼。所以,PHP一般將自己的編碼方式,告訴Mysql。
要保證不亂碼,就必須將三個(gè)編碼統(tǒng)一:一是網(wǎng)頁(yè)自身的編碼,二是HTML里指定的編碼,三是PHP告訴Mysql的編碼(包括character_set_client和character_set_results)。
第一和第二個(gè)編碼,如果使用DW之類(lèi)的編輯器寫(xiě)的網(wǎng)頁(yè),通常是一致的,但用記事本寫(xiě)的網(wǎng)頁(yè),有可能不一致。(這里我感覺(jué)不太準(zhǔn)確,需要討論一下)
第三個(gè)編碼,需要手工通知Mysql。這步可以通過(guò)在PHP里使用mysql_query(“set names characterX”)來(lái)實(shí)現(xiàn)。
d.字符集的轉(zhuǎn)換問(wèn)題
如果小字集轉(zhuǎn)換成大字符集,不會(huì)丟失數(shù)據(jù),但大字集,轉(zhuǎn)換成小字集,可能會(huì)丟失數(shù)據(jù)。
比如,UTF8里有的字符,GB2312不一定有,所以,從UTF8轉(zhuǎn)換到GB2312可能會(huì)丟失一些字符。
但有種情況例外,先從GB2312轉(zhuǎn)成UTF8,再?gòu)腢TF8轉(zhuǎn)成GB2312,這種情況是不會(huì)丟數(shù)據(jù)的,因?yàn)椋瑒傞_(kāi)始轉(zhuǎn)換的文本,都是GB2312里的字符,所以,整個(gè)過(guò)程都是GB2312的字符在轉(zhuǎn)換,不會(huì)丟失。
正因?yàn)閁TF8能容納世界上的所有字符,所以,數(shù)據(jù)庫(kù)一般使用UTF8編碼。這使得,任何字符都可以存進(jìn)UTF8編碼的數(shù)據(jù)庫(kù)。
e. PHPMyAdmin亂碼的問(wèn)題
PHPMyAdmin支持多國(guó)語(yǔ)言,這就必定要求HTML頁(yè)面使用UTF8編碼。
HTML頁(yè)面使用UTF8編碼,這就必定要求PHPMyAdmin連接Mysql時(shí),character_set_client和character_set_results使用UTF8編碼。
當(dāng)前情況下,PHP連接Mysql只能是使用set names(或其它幾個(gè)語(yǔ)句)來(lái)通知Mysql的編碼方式,如果沒(méi)有顯式的聲明編碼方式,都將使用latin1編碼。一般的程序,都沒(méi)有顯式聲明 character_set_client變量,所以,都是將gb2312文本,按latin1編碼方式存在數(shù)據(jù)庫(kù),PHPMyAdmin再用utf8格式讀取,肯定是亂碼的。
如果PHP程序按正確的編碼存入數(shù)據(jù)庫(kù),肯定是沒(méi)有問(wèn)題的。所以,需要修改的不是PHPMyAdmin.(雖然有時(shí)修改PHPMyAdmin可以解決亂碼問(wèn)題,但這不是問(wèn)題的根本)