MySQL的字符集支持(Character Set Support)有兩個方面:字符集(Character set)和排序方式(Collation)。 html
字符(Character)是指人類語言中最小的表義符號。給定一系列字符,對每一個字符賦予一個數值,用數值來表明對應的字符,這一數值就是字符的編碼(Encoding)。例如,咱們給字符'A'賦予數值0,給字符'B'賦予數值1,則0就是字符'A'的編碼; 給定一系列字符並賦予對應的編碼後,全部這些字符和編碼對組成的集合就是字符集(Character Set)。例如,給定字符列表爲{'A','B'}時,{'A'=>0, 'B'=>1}就是一個字符集;mysql
字符序(Collation)是指在同一字符集內字符之間的比較規則; 肯定字符序後,才能在一個字符集上定義什麼是等價的字符,以及字符之間的大小關係; 每一個字符序惟一對應一種字符集,但一個字符集能夠對應多種字符序,其中有一個是默認字符序(Default Collation);sql
MySQL中的字符序名稱聽從命名慣例:以字符序對應的字符集名稱開頭;以_ci(表示大小寫不敏感)、_cs(表示大小寫敏感)或_bin(表示按編碼值比較)結尾。例如:在字符序``utf8_general_ci''下,字符``a''和``A''是等價的;數據庫
MySQL對於字符集的支持細化到四個層次:服務器(server),數據庫(database),數據表(table)和鏈接(connection)。服務器
1、MySQL默認字符集函數
MySQL對於字符集的指定能夠細化到一個數據庫,一張表,一列,應該用什麼字符集。性能
可是,傳統的程序在建立數據庫和數據表時並無使用那麼複雜的配置,它們用的是默認的配置,那麼,默認的配置從何而來呢?測試
(1) 編譯MySQL 時,指定了一個默認的字符集,這個字符集是 latin1;編碼
(2) 安裝MySQL 時,能夠在配置文件 (my.ini) 中指定一個默認的的字符集,若是沒指定,這個值繼承自編譯時指定的;spa
(3) 啓動mysqld 時,能夠在命令行參數中指定一個默認的的字符集,若是沒指定,這個值繼承自配置文件中的配置,此時 character_set_server 被設定爲這個默認的字符集;
(4) 當建立一個新的數據庫時,除非明確指定,這個數據庫的字符集被缺省設定爲character_set_server;
(5) 當選定了一個數據庫時,character_set_database 被設定爲這個數據庫默認的字符集;
(6) 在這個數據庫裏建立一張表時,表默認的字符集被設定爲 character_set_database,也就是這個數據庫默認的字符集;
(7) 當在表內設置一欄時,除非明確指定,不然此欄缺省的字符集就是表默認的字符集;
簡單的總結一下,若是什麼地方都不修改,那麼全部的數據庫的全部表的全部欄位的都用latin1存儲,不過咱們若是安裝 MySQL,通常都會選擇多語言支持,也就是說,安裝程序會自動在配置文件中把default_character_set 設置爲 UTF-8,這保證了缺省狀況下,全部的數據庫的全部表的全部欄位的都用 UTF-8 存儲。
2、查看字符集
一、查看MySQL數據庫服務器字符集(服務器級)
mysql> show variables like '%char%';
+--------------------------+------------------------------------------+
| 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:\MySQL\MySQL Server 5.1\share\charsets\ |
+--------------------------+------------------------------------------+
系統變量:
– character_set_server:默認的內部操做字符集
– character_set_client:客戶端來源數據使用的字符集
– character_set_connection:鏈接層字符集
– character_set_results:查詢結果字符集
– character_set_database:當前選中數據庫的默認字符集
– character_set_system:系統元數據(字段名等)字符集
– 還有以collation_開頭的同上面對應的變量,用來描述字符序。
設置保存在my.ini文件裏。
二、查看數據庫的字符集(數據庫級)
select * from information_schema.schemata where schema_name = '庫名';
例:
mysql> select * from information_schema.schemata where schema_name='testdb' \G;
*************************** 1. row ***************************
CATALOG_NAME: NULL
SCHEMA_NAME: testdb
DEFAULT_CHARACTER_SET_NAME: gbk
DEFAULT_COLLATION_NAME: gbk_chinese_ci
SQL_PATH: NULL
1)若沒有顯式設置,則自動使用服務器級的配置
2.)顯式設置:在建立庫時指定
create database 庫名 DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;
三、查看MySQL數據表(table)的字符集(表級)
語法:show create table 表名
mysql> show create table tb \G;
*************************** 1. row ***************************
Table: tb
Create Table: CREATE TABLE `tb` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`Name` char(20) NOT NULL,
`Age` tinyint(4) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=gbk
1 row in set (0.00 sec)
查看Collation
語法:show table status from 數據庫名 like ‘數據表名’;
mysql> show table status from testdb like '%tb%' \G;
*************************** 1. row ***************************
Name: tb
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 1
Avg_row_length: 16384
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 621805568
Auto_increment: 2
Create_time: 2013-08-14 22:27:06
Update_time: NULL
Check_time: NULL
Collation: gbk_chinese_ci
Checksum: NULL
Create_options:
Comment:
*************************** 2. row ***************************
Name: tb11
Engine: InnoDB
Version: 10
Row_format: Compact
Rows: 2
Avg_row_length: 8192
Data_length: 16384
Max_data_length: 0
Index_length: 0
Data_free: 621805568
Auto_increment: NULL
Create_time: 2013-08-14 22:44:09
Update_time: NULL
Check_time: NULL
Collation: gbk_chinese_ci
Checksum: NULL
Create_options:
Comment:
2 rows in set (0.00 sec)
Collation:用於指定數據集如何排序,以及字符串的比對規則。
每一個 character set 會對應必定數量的 collation. 查看方法是在 mysql 的 console 下輸入:
mysql>show collation;
mysql collation的命名規則:
它們以其相關的字符集名開始,一般包括一個語言名,而且以_ci(大小寫不敏感)、_cs(大小寫敏感)或_bin(二元)結束。
好比latin1字符集有如下幾種校訂規則:
校對規則 含義
latin1_german1_ci 德國DIN-1
latin1_swedish_ci 瑞典/芬蘭
latin1_danish_ci 丹麥/挪威
latin1_german2_ci 德國 DIN-2
latin1_bin 符合latin1編碼的二進制
latin1_general_ci 多種語言(西歐)
latin1_general_cs 多種語言(西歐ISO),大小寫敏感
latin1_spanish_ci 現代西班牙
同一個 character set 的不一樣 collation 的區別在於排序、字符串對比的準確度(相同兩個字符在不一樣國家的語言中的排序規則多是不一樣的)以及性能。
例如:utf8_general_ci 在排序的準確度上要遜於 utf8_unicode_ci, 固然,對於英語用戶應該沒有什麼區別。但性能上(排序以及比對速度)要略優於 utf8_unicode_ci.
MySQL按照下面的方式選擇表字符集和 校對規則:
若是指定了CHARACTER SET X和COLLATE Y,那麼採用字符集X和校對規則Y。
若是指定了CHARACTER SET X而沒有指定COLLATE Y,那麼採用CHARACTER SET X和CHARACTER SET X的默認校對規則。
· 不然,採用服務器字符集和服務器校對規則。
轉換語法
alter table 表名 convert to character set 字符集名 collate 值;
例:
mysql> show create table tmptable \G;
*************************** 1. row ***************************
Table: tmptable
Create Table: CREATE TABLE `tmptable` (
`id` int(10) unsigned NOT NULL DEFAULT '0',
`Name` char(20) NOT NULL,
`Age` tinyint(4) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=gbk
mysql> alter table tmptable convert to character set utf8 collate utf8_bin;
mysql> show create table tmptable \G;
*************************** 1. row ***************************
Table: tmptable
Create Table: CREATE TABLE `tmptable` (
`id` int(10) unsigned NOT NULL DEFAULT '0',
`Name` char(20) COLLATE utf8_bin NOT NULL,
`Age` tinyint(4) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
1 row in set (0.00 sec)
若沒有顯式設置,則自動使用數據庫級的配置
顯式設置在建表時指定:
create table 表名 (
字段
) engine=引薦 default charset=utf8 collate=utf8_bin;
建議使用_bin,這樣能夠區分大小寫
在建表的時候指定了character set,因此它永遠是採用對應的默認的校對規則,建議collation都儘可能採用字符集相應的bin類型的校對規則。
四、查看MySQL數據列(column)的字符集
mysql> show create table tmptable\G;
*************************** 1. row ***************************
Table: tmptable
Create Table: CREATE TABLE `tmptable` (
`id` int(10) unsigned NOT NULL DEFAULT '0',
`Name` char(20) COLLATE utf8_bin NOT NULL,
`Age` tinyint(4) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin
1 row in set (0.00 sec)
若沒有顯式設置,則自動使用表級的配置。
顯式設置在建表時指定:
CREATE TABLE Table1(column1 VARCHAR(5) CHARACTER SET latin1 COLLATE latin1_german1_ci);
mysql> show full columns from tb;
+-------+------------------+----------------+------+-----+---------+----------------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+-------+------------------+----------------+------+-----+---------+----------------+---------------------------------+---------+
| id | int(10) unsigned | NULL | NO | PRI | NULL | auto_increment | select,insert,update,references |
| Name | char(20) | gbk_chinese_ci | NO | | NUL | select,insert,update,references | |
| Age | tinyint(4) | NULL | NO | | NULL | select,insert,update,references | |
+-------+------------------+----------------+------+-----+---------+----------------+---------------------------------+---------+
3 rows in set (0.00 sec)
關於collation的影響:
mysql> select * from tb;
+----+------------+-----+
| id | Name | Age |
+----+------------+-----+
| 1 | changename | 20 |
+----+------------+-----+
1 row in set (0.00 sec)
mysql> select * from tb where binary name='changename';
+----+------------+-----+
| id | Name | Age |
+----+------------+-----+
| 1 | changename | 20 |
+----+------------+-----+
1 row in set (0.69 sec)
mysql> select * from tb where name= binary 'changename';
+----+------------+-----+
| id | Name | Age |
+----+------------+-----+
| 1 | changename | 20 |
+----+------------+-----+
1 row in set (0.00 sec)
查看字符的編碼:
mysql> select hex('測試');
+-------------+
| hex('測試') |
+-------------+
| B2E2CAD4 |
+-------------+
1 row in set (0.06 sec)
五、鏈接級別
show variables like 'character_set_client'; #客戶端statements 中的編碼
show variables like 'character_set_connection' ; #數據庫鏈接中的編碼
show variables like 'character_set_results'; # 服務端返回結果集和錯誤信息中的編碼
3、設置及修改字符集
一、建立數據庫指定數據庫的字符集
mysql> create database mydb character set gbk;
mysql> use mydb
mysql> show variables like 'character_set_database';
+------------------------+--------+
| Variable_name | Value |
+------------------------+--------+
| character_set_database | gbk |
+------------------------+--------+
二、修改數據庫的字符集
(1)、經過SQL修改
mysql> alter database mydb character set utf8;
mysql> show variables like 'character_set_database';
+------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| character_set_database | utf8 |
+------------------------+-------+
(2)、經過配置文件修改
修改文件$MYSQL_HOME\data\mydb\db.opt的內容
default-character-set=utf8
default-collation=utf8_general_ci
爲
default-character-set=latin1
default-collation=latin1_swedish_ci
重啓MYSQL後生效
或者修改mysql的my.ini文件中的字符集鍵值
default-character-set = utf8
character_set_server = utf8
修改完後,重啓mysql的服務
三、經過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 character_set_system=utf8;
mysql> set collation_connection=utf8;
mysql> set collation_database=utf8;
mysql> set collation_server=utf8;
4、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。
常見問題解析
• 向默認字符集爲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字符集中表示而被轉換爲「?」(0x3F)符號,之後查詢時無論鏈接字符集設置如何都沒法恢復其內容了。
5、檢測字符集問題的一些手段
• 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 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設置的影響,對於比較之類的操做可能產生徹底不一樣的結果,須要當心!
部份內容來源於深刻Myql字符集設置分析,官方文檔:http://dev.mysql.com/doc/refman/5.1/zh/charset.html#charset-collate