1、mysql字符集
(1)mysql字符集
字符集就是一套文字符號及編碼,比較規則的集合。mysql的字符及包括字符集(CHARACTER)和校對規則(COLLATION)
MySQL字符集支持在基於InnoDB, MyISAM, Memory三個存儲引擎的MySQL實例、數據庫、表、列四個級別上設置,同時MySQL提供了多種字符集和排序規則,其中字符集設置、數據存儲以及客戶端與MySQL實例的交互相關,排序規則和字符串的對比規則相關。查看當前MySQL支持的字符集的方式有兩種,一種是通過查看information_schema.character_set系統表,一種是通過命令show character set查看。
(2)mysql常用字符集
1)Latin字符集
又稱Latin-1或“西歐語言”,是國際標準化組織內ISO/IEC 8859的第一個8位字符集。它以ASCII爲基礎,此字符集支持部分於歐洲使用的語言。也是mysql5.7中默認字符集。
# 創建基於latin字符集的表並插入中文
mysql> CREATE TABLE test01(name varchar(100) DEFAULT NULL,name2 varchar(100) DEFAULT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1;
# 將客戶端的字符集也設置爲latin1,否則不能插入中文
mysql> set names 'latin1';
mysql> insert into test01 values('china','中國');
mysql> select * from test01;
+-------+-------+
| name | name2 |
+-------+-------+
| china | 中國 |
+-------+-------+
Latin1是一種很常見的字符集,這種字符集是單字節編碼,向下兼容ASCII,Latin1覆蓋了所有的單字節,因此,可以將任意字符串保存在latin1字符集中,而不用擔心有內容不符合latin1的編碼規範而被拋棄。
mysql使用者經常利用Latin1的這種全覆蓋特性,將其它類型的字符串,gbk,utf8,big5等,保存在latin1列中。保存的過程中沒有數據丟失,只要原樣取出來,便又是合法的gbk/utf8/big字符串。如果將gbk字符串保存在utf8列中,則gbk字符串中那些不符合utf8編碼格式的內容,會被拋棄,保存的內容無法原樣取出,數據實際上遭到了破壞。
# 將客戶端的字符串該爲utf8時新插入的數據爲utf8則會遭到破壞
mysql> insert ignore into test01(name,name2) values('china1','中國一');
mysql> select * from test01;
+--------+---------------+
| name | name2 |
+--------+---------------+
| china | ä¸å›½ |
| china1 | ??? |
+--------+---------------+
2)Unicode字符集
Unicode(Universal Code)是一種在計算機上使用的字符編碼。Unicode 是爲了解決傳統的字符編碼方案的侷限而產生的,它爲每種語言中的每個字符設定了統一併且唯一的二進制編碼,以滿足跨語言、跨平臺進行文本轉換、處理的要求。Unicode存在不同的編碼方案,包括Utf-8,Utf-16和Utf-32。Mysql支持的unicode的字符集主要有以下幾種:
character set |
Supported characters |
Required storage per character |
Utf8 |
BMP only |
1、2、3 bytes |
Ucs2 |
BMP only |
2bytes |
Utf8mb4 |
BMP and supplementary |
1、2、3、4bytes |
Utf18 |
BMP and supplementary |
2、4bytes |
Utf16le |
BMP and supplementary |
2、4bytes |
Utf32 |
BMP and supplementary |
4bytes |
BMP(BMP-Basic Multilingual Plane):基本多語言範圍。如果將BMP之外的擴展字符轉換成utf8等僅支持BMP的字符集時,不識別的字符會轉化成?號;除UTF8外,客戶端字符集不支持設置爲其他的Unicode字符集。
UTF8字符集:UTF8(Unicode Transformation Format with 8-bit units)是一種存放Unicode數據的編碼規則。各類字符佔用的大小如下:
基礎拉丁字母,數字,標點符號會佔用一個字節
擴展的拉丁字符,希臘語,斯拉夫語,阿拉伯語等會佔用兩個字節
韓語,中文,日語字符會佔用3個或4個字節
在MySQL中,UTF8字符集不支持擴展字符,且僅佔用最多3個字節
3)國家字符集
標準SQL中會有兩種預定義的字符集數據類型,分別是nchar和nvarchar。 在MySQL中這種預定義的字符集就是UTF8。對字符串來說,可以使用N'字符串'的方式表明使用國家字符集。
mysql> create table test03(name nchar(10),name2 nvarchar(10),name3 varchar(10));
mysql> show create table test03;
+--------+----------------------------------------------------------+
| Table | Create Table
+--------+----------------------------------------------------------+
| test03 | CREATE TABLE `test03` (
`name` char(10) CHARACTER SET utf8 DEFAULT NULL,
`name2` varchar(10) CHARACTER SET utf8 DEFAULT NULL,
`name3` varchar(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+--------+-----------------------------------------------------------+
4)中文字符集和排序規則
字符集 |
描述 |
排序規則 |
big5 |
Big5 繁體中文 |
big5_bin、big5_chinese_ci (default) |
gb2312 |
GB2312 簡體中文 |
gb2312_bin、gb2312_chinese_ci (default) |
gbk |
GBK簡體中文 |
gbk_bin、gbk_chinese_ci (default) |
gb18030 |
中國國家標準GB18030) |
gb18030_bin:二進制排序規則 gb18030_chinese_ci (default):若是字母就按照字母排序,如果是漢字則按照拼音排序 gb18030_unicode_520_c:Unicode排序規則 |
mysql> create table test04(name01 varchar(10) character set utf8 not null,name02 varchar(10) character set gbk,name03 varchar(10) character set gb2312,name04 varchar(10)) engine=InnoDB charset=latin1;
mysql> insert ignore into test04 values('中國','中國','中國','中國');
# 由於連接字符集和客戶端字符集都爲utf8導致latin字符集插入中文時數據遭到破壞
mysql> select * from test04;
+--------+--------+--------+--------+
| name01 | name02 | name03 | name04 |
+--------+--------+--------+--------+
| 中國 | 中國 | 中國 | ?? |
+--------+--------+--------+--------+
(3)查看mysql中字符集及排序規則
# 查看當前數據庫字符集
mysql> show variables like '%charac%';
+--------------------------+-----------------------------------------+
| Variable_name | Value |
+--------------------------+-----------------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/local/mysql-5.7.32/share/charsets/ |
+--------------------------+-----------------------------------------+
各字符集的含義如下:
character_set_client:連接客戶端發送的語句的字符集
character_set_connection:客戶端與服務交互時的字符集
character_set_database:當前所在庫的字符集
character_set_results:參數決定了語句的執行結果以什麼字符集返回給客戶端
character_set_server:當前登錄的數據庫實例的字符集
character_set_system:數據庫所在系統的字符集
# 查看當前數據庫排序規則
mysql> show variables like '%collation%';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | utf8_general_ci |
| collation_database | latin1_swedish_ci |
| collation_server | latin1_swedish_ci |
+----------------------+-------------------+
2、mysql字符集排序規則
(1)mysql字符集排序規則
每個指定的字符集都會有一個或多個支持的排序規則,可以通過兩種方式查看,一種是查看information_schema.collations表,另一種是通過show collation命令查看;不同的字符集不可能有相同的排序規則,每個字符集都會有一個默認的排序規則。
(2)排序規則的命名規則
排序規則的命令通常是以對應的字符集的名字爲開頭,並以自己的特定屬性結尾,當排序規則特指某種語言時,則中間的部分就爲這種語言的名字,如” utf8_turkish_ci”代表UTF8字符集中的土耳其語排序中對大小寫不敏感
結尾符 |
代表含義 |
_ai |
口音不敏感 |
_as |
口音敏感 |
_ci |
大小寫不敏感 |
_cs |
大小寫敏感 |
_bin |
二進制 |
當排序規則名字中沒有指定_as或者_ai時,則是否口音敏感是由_ci或者_cs決定。對Unicode的字符集來說,對應的排序規則也可能會包含unicode排序算法的版本號,如果沒有這個版本號顯示則表示是基於4.0.0這個版本。
3、字符集及排序規則的設置
(1)實例級別字符集和排序規則的設置
實例級別的字符集可以在實例啓動的時候指定或在默認的配置文件中指定,默認的字符集是latin1,當僅指定了字符集沒有指定排序規則時,則默認的排序規則是該字符集的默認排序規則。
設置參數:
character-set-server:指定字符集
collation-server:指定排序規則
# 啓動mysql實例時設置字符集
]# /etc/init.d/mysqld start --character-set-server=latin1 --collation-server=latin1_swedish_ci
# 在mysql配置文件中設置字符集,在老版本中使用” Default-character-set”參數
[mysqld]
character-set-server=utf8
# 修改實例級別的默認字符集,對root用戶無效
mysql> show variables like '%character_set%';
(2)庫級別字符集和排序規則的設置
數據庫級別的字符集和排序規則,可以通過create database和alter database語句來指定和修改。
# 創建一個數據庫並指定排序規則
mysql> create database test01 character set utf8;
# 修改創建的庫的排序規則
mysql> alter database test01 character set latin1;
mysql> show create database test01;
+----------+-------------------------------------------------+
| Database | Create Database
+----------+-------------------------------------------------------+
| test01 | CREATE DATABASE `test01` /*!40100 DEFAULT CHARACTER SET latin1 */ |
+----------+--------------------------------------------------------+
(3)表級別字符集和排序規則的設置
每個表都有自己的字符集和排序規則,可以通過create table和alter table語句指定或修改表的字符集和排序規則;如果沒有指定排序規則時會使用字符集默認的排序規則,如果沒有指定字符集時則使用排序規則對應的字符集。當兩個屬性都沒有指定時,會使用數據庫級別的字符集和排序規則。
# 創建表時指定排序規則和字符集
mysql> create table test01(id int,name varchar(100)) character set utf8 collate utf8_general_ci;
# 修改表的字符集,表的字符集不會改變已經存在的字段的字符集和字段裏的數據
mysql> alter table test01 character set latin1;
mysql> show create table test01;
+--------+--------------------------------------------------+
| Table | Create Table
+--------+---------------------------------------------------+
| test01 | CREATE TABLE `test01` (
`id` int(11) DEFAULT NULL,
`name` varchar(100) CHARACTER SET utf8 DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |
+--------+---------------------------------------------------------+
(4)列級別字符集和排序規則的設置
每個字符串字段都有自己的字符集和排序規則,可以在create table和alter table指定和修改字段的字符集和排序規則。如果通過alter table語句修改某一列的字符集時,MySQL會試圖轉換其中已有的數據,這樣的轉換有可能會導致數據丟失。
# 創建一張表並指定某些字段的排序規則
mysql> CREATE TABLE test02 (id int,name VARCHAR(5) CHARACTER SET latin1 COLLATE latin1_german1_ci);
# 修改列級別字符集
mysql> alter table test02 modify name varchar(12) character set utf8;
# 當修改爲範圍更小的級別的字符集時會報錯
mysql> alter table test02 modify name varchar(12) character set greek;
ERROR 1366 (HY000): Incorrect string value: '\xC3\xA4\xC2\xB8\xC2\xAD...' for column 'name' at row 1
(5)連接級字符集和排序規則
每個數據庫客戶端連接都有自己的字符集和排序規則屬性,客戶端發送的語句的字符集是由character_set_client決定,而與服務端交互時會根據character_set_connection和collation_connection兩個參數將接收到的語句轉化。當涉及到顯示字符串的比較時,由collation_connection參數決定,而當比較的是字段裏的字符串時則根據字段本身的排序規則決定。
客戶端可以很方便的調整字符集和排序規則,當使用”set names”語句設置字符集時相當於同時設置了character_set_client、character_set_connection、character_set_results的值。
# 設置客戶端的字符集的排序規則
mysql> set names latin1;
也可以通過參數 --init_connect="SET NAMES 'utf8'" 來讓每個客戶端連接都自動設置字符集,但缺點是對擁有super權限的用戶不生效;init_connect表示服務器爲每個連接的客戶端執行的字符串,要想指定多個語句,用分號間隔開。
# 通過命令設置客戶端的排序規則的字符集
mysql> SET GLOBAL init_connect='SET AUTOCOMMIT=0;set names utf8';
#通過配置文件設置默認的客戶端的字符集和排序規則
[mysqld]
init_connect='SET AUTOCOMMIT=0;set names utf8’
(6)排序規則在sql語句中使用
在SQL語句中指定排序規則可以覆蓋之前定義的默認排序規則
mysql> select sname,gender from student order by gender collate latin1_german2_ci;
+--------+--------+
| sname | gender |
+--------+--------+
| Andy | 0 |
| Bob | 0 |
# 使用函數時定義排序規則
mysql> select max(score collate latin1_german2_ci) from score;
+--------------------------------------+
| max(score collate latin1_german2_ci) |
+--------------------------------------+
| 95 |
+--------------------------------------+
(7)字符集和排序規則使用注意事項
當應用程序使用MySQL默認的字符集和排序規則時,則應用程序端不需要特別的設置,而當不是使用默認屬性時則需要特別設置。
4、mysql數據庫字符集的轉化
1)MySQL Server收到請求時將請求數據從character_set_client轉換爲character_set_connection;
2)進行內部操作前將請求數據從character_set_connection轉換爲內部操作字符集
3)將操作結果從內部操作字符集轉換爲character_set_results
5、mysql數據庫字符集的亂碼及解決方法
(1)字符集亂碼原因
1)客戶機沒有正確地設置client字符集,導致原先的SQL語句被轉換成connection所指字符集,而這種轉換,是會丟失信息的
2)數據庫字體沒有設置正確,那麼connection字符集轉換成database字符集照樣丟失編碼
(2)解決字符亂碼方案
1)首先要明確你的客戶端時候何種編碼格式,這是最重要的(IE6一般用utf8,命令行一般是gbk,一般程序是gb2312)
2)確保數據庫使用utf8格式,很簡單,所有編碼通吃。
3)要保證connection字符集大於等於client字符集,不然就會信息丟失