標籤:
http://blog.csdn.net/martinkro/article/details/5352474
1 MYSQL中的字元集概念
Mysql的字元集裡有兩個概念,一個是"Character set(字元集)",另一個是"Collations"。
1.1 Collations
Collations翻成中文是"校正",在網頁開發的過程中,這個詞彙,只在Mysql裡使用,主要作用是指導Mysql對字元的比較,比如, ASCII字元集裡,Collations規定了a小於b,a等於a,以及a是否等於A之類的。通常,大家基本可以忽略Collations的存在,因為每個字元集都有一個預設的Collations,通常,使用預設的Collations就可以了。
1.2 Character set
與這對比的是,字元集是個更廣的概念,即使是Windows下普通的文字檔,也滲及到字元集的問題。不同的字元集,規定了不同的字元的編碼方式。一個 character set (字元集)是一組符號和編碼,比如,ASCII字元集,包括的字元有:數字,大小寫字母,分號、換行之類的符號,編碼方式是用一個7bit表示一個字元(A的編碼是65,b的編碼是98)。ASCII只規定了英文字母的編碼,非英文語言不能用ASCII編碼錶示,為此,不同的國家,都為自己的語言做了編碼,比如,我們國家,就有GB2312編碼。但每個國家之間的編碼不同,也存在著一些跨平台的問題,為此,一些國際化標準組織,就制定了一些國際通用的編碼,最常用的就是UTF8了。ASCII只對英文符號和英文字母做了編碼,GB2312對英文符號,英文字母,漢字做了編碼,UTF8對世界上所有的語言文字做了編碼,所以,GB1212的字元包含了ASCII字元,UTF8包含了GB2312字元。由此可見,UTF8是所含最廣字元的字元集,所以,在一些多語言的WEB系統中,一般用UTF8字元集(PHPMyAdmin使用UTF8編碼)。
任何文本的儲存,都滲及到字元集的概念。包括資料庫,也包括普通的文字檔。
編碼和字元集兩個概念極易混淆,因為一般情況下,編碼的名字和字元集的名字相同,如:GB2312既是一種字元集的名字,也是一種編碼格式的名字。
字元:漢字,英文字母,標點符號,拉丁文等等。
編碼:將字元轉換成電腦儲存的格式,比如,A用65表示。
字元集:一組字元以及對應的編碼方式。
可見字元集和編碼是兩個不同的概念。一個字元集可以有多種編碼方式,如Unicode字元集就有UTF-8、UTF-16、UTF-32等編碼方式。 charset=utf-8,在網頁中的意思是該頁面時採用Unicode字元集,並採用UTF-8編碼方式。
1.3 Mysql的字元集
Mysql目前支援多字元集,並且,支援在不同的字元集之間轉換(便於移植和支援多語言)。
Mysql可以設定伺服器級字元集、資料庫級字元集、資料表級字元集、表列的字元集,實際上,最終使用字元集的地方是儲存字元的列,比如,你設定 table1中col1列是字元類型,col1才用到了字元集,如果table1表的col2列是int類型,col2不使用字元集的概念。
伺服器級字元集、資料庫級字元集、資料表級字元集都是為列的字元集做預設選項的。
Mysql 一定有一個字元集,可以通過啟動時加參數指定,也可以編譯時間指定,也可以在設定檔裡指定。Mysql伺服器字元集,只是做為資料庫級的預設值。建立資料庫時,你可以指定字元集,如果沒指定,就使用伺服器的字元集。同理,建立表時,你可以指定表級的字元集,如果沒指定,使用資料庫的字元集做為表的字元集。建立列時,你可以指定某列的字元集,如果沒指定,就使用表的字元集。
通常情況下,您只需設定伺服器級的字元集,其它的資料庫級,表級,以及列級的字元集,都繼承自伺服器級字元集。
由於UTF8是最廣的字元集,所以,一般情況下,我們設定Mysql伺服器級的字元集為UTF8。
MYSQL中字元集的繼承關係
伺服器字元集(在設定檔中設定字元集的方式:my.ini [mysqld] default-character-set=utf8)
|
|
|
資料庫級字元集(如果建立資料庫是指定了字元集,則使用指定的字元集。如果沒有,則使用伺服器級的字元集)
|
|
|
表級字元集(建立表時指定了字元集,則使用指定的字元集。如果沒有,則使用資料庫級的字元集)
|
|
|
列級字元集(建立表時指定了列的字元集,則使用指定的字元集。如果沒有,則使用表級的字元集)
可見最終使用字元集的地方是儲存文本的列。
2 普通文本的字元集問題
任何文本的儲存,都存在著字元集的問題,普通文字檔也不例外。
Windows2000+的系統中,開啟記事本,"儲存為..."對話方塊,就有一個選項,可以讓你選擇儲存文本的編碼方式。
通常情況下,大家都使用Windows2000+的系統,都使用預設的編碼,所以,不會碰到字元集的問題。
Windows下,儲存文字檔時,可以選擇編碼方式,但開啟文字檔時,都是自動判斷編碼方式的。網上有一個用Windows2000+的記事本玩移動,聯通的笑話,大家可以搜搜,就是因為Windows在開啟文字檔時,編碼判斷錯誤引起的問題。
因為自動判斷編碼有時會錯誤,所以,有的文字檔,規定了如何識別自身所使用的編碼。HTML檔案就是一個這樣的例子。
HTML是文字檔。儲存HTML檔案的時候,需要使用一個編碼,並且,在HTML檔案裡,也使用HTML文法,指定了該檔案所使用的編碼(比如)。如果HTML檔案沒有指定編碼,則瀏覽器自動識別檔案的編碼。如果HTML指定了編碼,則瀏覽器使用HTML指定的編碼。
通常情況下,HTML檔案指定的charset和HTML檔案自身的編碼是一致的,但也有不一致的情況,如果不一致,就會導致網頁亂碼(此處亂碼,只和文字檔有關,和資料庫無關。)使用專門的網頁編輯工具(比如Dreamwave),會自動根據網頁中的charset值來編碼檔案。
例如:test.html
內容如下:
<h1>123地方活動家恢複搭街坊456</h1>
不管上述檔案儲存時使用什麼編碼方式,用瀏覽器開啟都會正常,不會出現亂碼。這是因為瀏覽器能自動識別編碼格式。
將上述檔案內容該為:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<h1>123地方活動家恢複搭街坊456</h1>
這時test.html不使用UTF-8編碼格式儲存,瀏覽器開啟一定會出現亂碼。因為瀏覽器將使用UTF-8編碼來解析收到的資料。
3 php+mysql的字元集問題
PHP最終產生的是文字檔,但他要取資料庫裡的文本,或將文本存進資料庫。
由於Mysql支援多字元集,預設情況下,Mysql不知道PHP發給他的是什麼編碼的字元,所以,Mysql要求用戶端(PHP)告訴他存取的字元集是什麼。
PHP通過設定character_set_client,告訴Mysql,PHP存進資料庫的是什麼編碼方式。
PHP通過設定character_set_results,告訴Mysql,PHP需要取什麼樣編碼的資料。
PHP通過設定character_set_connection,告訴Mysql,PHP查詢中的文本,使用什麼編碼。
MYSQL使用設定的編碼方式儲存文本。
假設Mysql使用setserver來儲存文本,PHP的character_set_client是setclient,PHP的 character_set_results是setresult。那麼,Mysql將PHP發來的文本,從setclient編碼方式,轉換成 setserver編碼方式,再存入資料庫,如果PHP取文本,Mysql將文本從setserver轉換成setresult,再發送給PHP。
PHP檔案(最終產生的HTML檔案)本身有個編碼,如果Mysql傳過來的編碼,與PHP檔案自身的編碼不同,那麼,整個網頁,必然亂碼。所以,PHP一般將自己的編碼方式,告訴Mysql。
要保證不亂碼,就必須將三個編碼統一:一是網頁自身的編碼,二是HTML裡指定的編碼,三是PHP告訴Mysql的編碼(包括character_set_client和character_set_results)。
第一和第二個編碼,如果使用DW之類的編輯器寫的網頁,通常是一致的,但用記事本寫的網頁,有可能不一致。
第三個編碼,需要手工通知Mysql。這步可以通過在PHP裡使用mysql_query("set names characterX")來實現。
//---------------------------------------------------------------------------------------------------------
MySQL會出現中文亂碼的原因不外乎下列幾點:
1.server本身設定問題,例如還停留在latin1
2.table的語系設定問題(包含character與collation)
3.用戶端程式(例如php)的連線語系設定問題
強烈建議使用utf8!!!!
utf8可以相容世界上所有字元!!!!
一、避免建立資料庫及表出現中文亂碼和查看編碼方法
1、建立資料庫的時候:CREATE DATABASE `test`
CHARACTER SET ‘utf8‘
COLLATE ‘utf8_general_ci‘;
2、建表的時候 CREATE TABLE `database_user` (
`ID` varchar(40) NOT NULL default ‘‘,
`UserID` varchar(40) NOT NULL default ‘‘,
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
這3個設定好了,基本就不會出問題了,即建庫和建表時都使用相同的編碼格式。
但是如果你已經建了庫和表可以通過以下方式進行查詢。
1.查看預設的編碼格式:
mysql> show variables like "%char%";
+--------------------------+---------------+
| Variable_name | Value |
+--------------------------+---------------+
| character_set_client | gbk |
| character_set_connection | gbk |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | gbk |
| character_set_server | utf8 |
| character_set_system | utf8 |
+--------------------------+-------------+
註:以前2個來確定,可以使用set names utf8,set names gbk設定預設的編碼格式;
執行SET NAMES utf8的效果等同於同時設定如下:
SET character_set_client=‘utf8‘;
SET character_set_connection=‘utf8‘;
SET character_set_results=‘utf8‘;
2.查看test資料庫的編碼格式:
mysql> show create database test;
+------------+------------------------------------------------------------------------------------------------+
| Database | Create Database |
+------------+------------------------------------------------------------------------------------------------+
| test | CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET gbk */ |
+------------+------------------------------------------------------------------------------------------------+
3.查看yjdb資料庫的編碼格式:
mysql> show create table yjdb;
| yjdb | CREATE TABLE `yjdb` (
`sn` int(5) NOT NULL AUTO_INCREMENT,
`type` varchar(10) NOT NULL,
`brc` varchar(6) NOT NULL,
`teller` int(6) NOT NULL,
`telname` varchar(10) NOT NULL,
`date` int(10) NOT NULL,
`count` int(6) NOT NULL,
`back` int(10) NOT NULL,
PRIMARY KEY (`sn`),
UNIQUE KEY `sn` (`sn`),
UNIQUE KEY `sn_2` (`sn`)
) ENGINE=MyISAM AUTO_INCREMENT=1826 DEFAULT CHARSET=gbk ROW_FORMAT=DYNAMIC |
二、避免匯入資料有中文亂碼的問題
1:將資料編碼格式儲存為utf-8
設定預設編碼為utf8:
set names utf8;
設定資料庫db_name預設為utf8:
ALTER DATABASE `db_name` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
設定表tb_name預設編碼為utf8:
ALTER TABLE `tb_name` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
匯入:
LOAD DATA LOCAL INFILE ‘C:\\utf8.txt‘ INTO TABLE yjdb;
2:將資料編碼格式儲存為ansi(即GBK或GB2312)
設定預設編碼為gbk:
set names gbk;
設定資料庫db_name預設編碼為gbk:
ALTER DATABASE `db_name` DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;
設定表tb_name預設編碼為gbk:
ALTER TABLE `tb_name` DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;
匯入:
LOAD DATA LOCAL INFILE ‘C:\\gbk.txt‘ INTO TABLE yjdb;
註:1.UTF8不要匯入gbk,gbk不要匯入UTF8;
2.dos下不支援UTF8的顯示;
三、解決網頁中亂碼的問題
將網站編碼設為 utf-8,這樣可以相容世界上所有字元。
如果網站已經運作了好久,已有很多舊資料,不能再更改簡體中文的設定,那麼建議將頁面的編碼設為 GBK, GBK與GB2312的區別就在於:GBK能比GB2312顯示更多的字元,要顯示簡體碼的繁體字,就只能用GBK。
1.編輯/etc/my.cnf ,在[mysql]段加入default_character_set=utf8;
2.在編寫Connection URL時,加上?useUnicode=true&characterEncoding=utf-8參;
3.在網頁代碼中加上一個"set names utf8"或者"set names gbk"的指令,告訴MySQL連線內容都要使用
utf8或者gbk;
//-----------------------------------------------------------------------------------
在my.ini裡面改成utf8
php串連資料庫後設定mysql_query(‘SET NAMES UTF8‘);
PHP和MYSQL的編碼問題