1、字符集和校驗規則mysql
字符集是一套符合和編碼,校驗規則(collation)是在字符集內用於比較字符的一套規則,即字符集的排序規則。MySQL可使用對種字符集和檢驗規則來組織字符。web
MySQL服務器能夠支持多種字符集,在同一臺服務器,同一個數據庫,甚至同一個表的不一樣字段均可以指定使用不一樣的字符集,相比oracle等其餘數據庫管理系統,在同一個數據庫只能使用相同的字符集,MySQL明顯存在更大的靈活性。sql
每種字符集均可能有多種校對規則,而且都有一個默認的校對規則,而且每一個校對規則只是針對某個字符集,和其餘的字符集麼有關係。數據庫
在MySQL中,字符集的概念和編碼方案被看作是同義詞,一個字符集是一個轉換表和一個編碼方案的組合。瀏覽器
Unicode(Universal Code)是一種在計算機上使用的字符編碼。Unicode 是爲了解決傳統的字符編碼方案的侷限而產生的,它爲每種語言中的每一個字符設定了統一而且惟一的二進制編碼,以知足跨語言、跨平臺進行文本轉換、處理的要求。Unicode存在不一樣的編碼方案,包括Utf-8,Utf-16和Utf-32。Utf表示Unicode Transformation Format。服務器
mysql> show character set;併發
mysql> select * from information_schema.character_sets;oracle
mysql> select character_set_name, default_collate_name, description, maxlen from函數
information_schema.character_sets;性能
mysql> show collation;
mysql> show collation like 'utf8';
mysql> select * from information_schema.collations where collation_name like 'utf8%';
mysql> show variables like 'character%';
+--------------------------+----------------------------------+
| Variable_name | Value |
+--------------------------+----------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | latin1 |
| character_set_filesystem | utf8 |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | /usr/local/mysql/share/charsets/ |
+--------------------------+----------------------------------+
8 rows in set (0.00 sec)
名詞解釋:
character_set_client:客戶端請求數據的字符集
character_set_connection:客戶機/服務器鏈接的字符集
character_set_database:默認數據庫的字符集,不管默認數據庫如何改變,都是這個字符集;若是沒有默認數據庫,那就使用 character_set_server指定的字符集,這個變量建議由系統本身管理,不要人爲定義。
character_set_filesystem:把os上文件名轉化成此字符集,即把 character_set_client轉換character_set_filesystem, 默認binary是不作任何轉換的
character_set_results:結果集,返回給客戶端的字符集
character_set_server:數據庫服務器的默認字符集
character_set_system:系統字符集,這個值老是utf8,不須要設置。這個字符集用於數據庫對象(如表和列)的名字,也用於存儲在目錄表中的函數的名字。
mysql> show variables like 'collation%';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | utf8_general_ci |
| collation_database | latin1_swedish_ci |
| collation_server | utf8_general_ci |
+----------------------+-------------------+
3 rows in set (0.01 sec)
名詞解釋:
collation_connection 當前鏈接的字符集。
collation_database 當前日期的默認校對。每次用USE語句來「跳轉」到另外一個數據庫的時候,這個變量的值就會改變。若是沒有當前數據庫,這個變量的值就是collation_server變量的值。
collation_server 服務器的默認校對。
排序方式的命名規則爲:字符集名字_語言_後綴,其中各個典型後綴的含義以下:
1)_ci:不區分大小寫的排序方式
2)_cs:區分大小寫的排序方式
3)_bin:二進制排序方式,大小比較將根據字符編碼,不涉及人類語言,所以_bin的排序方式不包含人類語言
MySQL字符集設置分爲兩類:
1)建立對象的默認值。
2)控制server和client端交互通訊的配置。
字符集合校對規則有4個級別的默認設置:
1)服務器級別;
2)數據庫級別;
3)表級別、列級別;
4)鏈接級別。
更低級別的設置會集成高級別的設置。
這裏有一個通用的規則:先爲服務器或者數據庫選擇一個合理的字符集,而後根據不一樣的實際狀況,讓某個列選擇本身的字符集。
大部分MySQL客戶端都不具有同時支持多種字符集的能力,每次都只能使用一種字符集。
客戶和服務器之間的字符集轉換工做是由以下幾個MySQL系統變量控制的。
1)character_set_server:mysql server默認字符集。
2)character_set_database:數據庫默認字符集。
3)character_set_client:MySQL server假定客戶端發送的查詢使用的字符集。
4)character_set_connection:MySQL Server接收客戶端發佈的查詢請求後,將其轉換爲character_set_connection變量指定的字符集。
5)character_set_results:mysql server把結果集和錯誤信息轉換爲character_set_results指定的字符集,併發送給客戶端。
6)character_set_system:系統元數據(字段名等)字符集
還有以collation_開頭的同上面對應的變量,用來描述字符序。
注意事項:
• my.cnf中的default_character_set設置隻影響mysql命令鏈接服務器時的鏈接字符集,不會對使用libmysqlclient庫的應用程序產生任何做用!
• 對字段進行的SQL函數操做一般都是之內部操做字符集進行的,不受鏈接字符集設置的影響。
• SQL語句中的裸字符串會受到鏈接字符集或introducer設置的影響,對於比較之類的操做可能產生徹底不一樣的結果,須要當心!
(1)編譯MySQL 時,指定了一個默認的字符集,這個字符集是 latin1;
(2)安裝MySQL 時,能夠在配置文件 (my.cnf) 中指定一個默認的的字符集,若是沒指定,這個值繼承自編譯時指定的;
(3)啓動mysqld 時,能夠在命令行參數中指定一個默認的的字符集,若是沒指定,這個值繼承自配置文件中的配置,此時character_set_server被設定爲這個默認的字符集;
(4)當建立一個新的數據庫時,除非明確指定,這個數據庫的字符集被缺省設定爲character_set_server;
(5)當選定了一個數據庫時,character_set_database被設定爲這個數據庫默認的字符集;
(6)在這個數據庫裏建立一張表時,表默認的字符集被設定爲character_set_database,也就是這個數據庫默認的字符集;
(7)當在表內設置一欄時,除非明確指定,不然此欄缺省的字符集就是表默認的字符集;
屬於同一個表的不一樣列能夠有不一樣的字符集,若是沒有爲一個列顯示的定義字符集就使用默認字符集。建立一個表的時候,若顯示的爲列指定字符集,則字符集做爲數據類型選項包含在其中,要放在數據類型後面及空指定和主鍵前面。
例如:
create table column_charset(
c1 char(10) character set utf8 not null,
c2 char(10) char set utf8,
c3 varchar(10) charset utf8,
c4 varchar(10)) engine=innodb;
注意:character set能夠簡寫爲char set和charset
使用show create table table_name;命令查看column_charset建表語句:
mysql> show create table column_charset\G;
*************************** 1. row ***************************
Table: column_charset
Create Table: CREATE TABLE `column_charset` (
`c1` char(10) CHARACTER SET utf8 NOT NULL,
`c2` char(10) CHARACTER SET utf8 DEFAULT NULL,
`c3` varchar(10) CHARACTER SET utf8 DEFAULT NULL,
`c4` varchar(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.01 sec)
ERROR:
No query specified
插入數據,感覺一下效果:
mysql> insert into column_charset(c1,c2,c3,c4) value("圖靈","圖靈","圖靈","chavin");
Query OK, 1 row affected (0.01 sec)
mysql> select * from column_charset;
+--------+--------+--------+--------+
| c1 | c2 | c3 | c4 |
+--------+--------+--------+--------+
| 圖靈 | 圖靈 | 圖靈 | chavin |
+--------+--------+--------+--------+
1 row in set (0.00 sec)
create table table_charset(
c1 varchar(10),
c2 varchar(10))engine=innodb default charset=utf8;
注意:爲表指定字符集可使用如下幾種方式:
default charset=utf8;
charset=utf8;
default character set=utf8;
character set=utf8;
default char set=utf8;
char set=utf8;
檢查建表語句:
mysql> show create table table_charset\G;
*************************** 1. row ***************************
Table: table_charset
Create Table: CREATE TABLE `table_charset` (
`c1` varchar(10) DEFAULT NULL,
`c2` varchar(10) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)
測試:
mysql> insert into table_charset(c1,c2) values('圖靈','圖靈');
Query OK, 1 row affected (0.01 sec)
mysql> select * from table_charset;
+--------+--------+
| c1 | c2 |
+--------+--------+
| 圖靈 | 圖靈 |
+--------+--------+
1 row in set (0.00 sec)
建立的每一個數據庫都有一個默認字符集,若是沒有指定,就用latin1。
create database dbking charset=utf8;
注意:建立數據庫分配字符集能夠採用如下幾種子句:
charset=utf8;
default charset=utf8;
charset utf8;
default charset utf8;
char set=utf8;
default char set=utf8;
char set utf8;
default char set utf8;
character set=utf8;
default character set=utf8;
character set utf8;
default character set utf8;
使用show create database db_name;命令查看數據庫建立語句:
mysql> show create database dbking;
+----------+-----------------------------------------------------------------+
| Database | Create Database |
+----------+-----------------------------------------------------------------+
| dbking | CREATE DATABASE `dbking` /*!40100 DEFAULT CHARACTER SET utf8 */ |
+----------+-----------------------------------------------------------------+
1 row in set (0.00 sec)
每一個列都應該有一個校對,若是沒有顯示指定,MySQL就使用屬於該字符集的默認校對。若是指定了一個字符集和一個校對,字符集應該放在前面。
create table column_collate(
c1 varchar(10) charset utf8 collate utf8_romanian_ci not null,
c2 varchar(10) charset utf8 collate utf8_spanish_ci)engine=innodb;
查看錶的校驗規則信息:
mysql> select table_name,column_name,collation_name
from information_schema.columns
where table_name='column_collate';
+----------------+-------------+------------------+
| table_name | column_name | collation_name |
+----------------+-------------+------------------+
| column_collate | c1 | utf8_romanian_ci |
| column_collate | c2 | utf8_spanish_ci |
+----------------+-------------+------------------+
2 rows in set (0.04 sec)
注意:字符集和校對在處理字符表達式的過程當中扮演着重要角色。咱們不能比較兩個屬於不一樣校對的不一樣字符值。例如:
mysql> insert into column_collate(c1,c2) values('A','A');
Query OK, 1 row affected (0.22 sec)
mysql> select * from column_collate;
+----+------+
| c1 | c2 |
+----+------+
| A | A |
+----+------+
1 row in set (0.00 sec)
mysql> select * from column_collate where c1=c2;
ERROR 1267 (HY000): Illegal mix of collations (utf8_romanian_ci,IMPLICIT) and (utf8_spanish_ci,IMPLICIT) for operation '='
create table table_collate(
c1 varchar(10),
c2 varchar(10))engine=innodb default charset utf8 collate utf8_romanian_ci;
檢查表的校對規則:
mysql> select table_name,column_name,collation_name from information_schema.columns where table_name='table_collate';
+---------------+-------------+------------------+
| table_name | column_name | collation_name |
+---------------+-------------+------------------+
| table_collate | c1 | utf8_romanian_ci |
| table_collate | c2 | utf8_romanian_ci |
+---------------+-------------+------------------+
2 rows in set (0.00 sec)
create database dbking102 default charset utf8 collate utf8_romanian_ci;
查看數據庫定義語句:
mysql> show create database dbking102\G;
*************************** 1. row ***************************
Database: dbking102
Create Database: CREATE DATABASE `dbking102` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_romanian_ci */
1 row in set (0.00 sec)
若是沒有顯示指定,那麼字符直接量的字符集就是數據庫的默認字符集。若是要顯示分配另外一個字符集,須要把字符集的名字放在直接量前面,而且要在字符集前面加上下劃線。
mysql> select _utf8'語言 Language 言語 язык';
+---------------------------------+
| 語言 Language 言語 язык |
+---------------------------------+
| 語言 Language 言語 язык |
+---------------------------------+
MySQL服務器支持衆多不一樣的字符集,這類字符集可在編譯時和運行時指定。
編譯時可指定默認字符集和默認校對規則,要想同時更改默認字符集和校對規則,要同時使用--with-charset和--with-collation選項。校對規則必須是字符集的合法校對規則。
./configure -- with-charset=CHARSET --with-collation=COLLATION
經過configure選項--with-extra-charsets=LIST,能夠定義在服務器中再定義增長字符集。LIST 指下面任何一項:
a.空格間隔的一系列字符集名
b.complex -,以包括不能動態裝載的全部字符集
c.all –,以將全部字符集包括進二進制
./configure -- with-charset=CHARSET --with-collation=COLLATION --with-extra-charsets=all
[mysqld]
character_set_server=utf8
--影響參數:character_set_server 和 character_set_database
--注意:修改後要重啓數據庫才能生效。
[client]
default-character-set=utf8
--影響參數:character_set_client,character_set_connection 和character_set_results。
--注意:修改後無需重啓數據庫。
3) 在啓動參數前指定
./mysqld --character-set-server=utf8 &
--影響參數:character_set_server 和 character_set_database
4)在mysql客戶端登錄時經過--default-character-set指定
mysql -uroot -pmysql --default-character-set=utf8
--影響參數:set character_set_client,set character_set_connection,set character_set_results。
a)分別指定
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;
b)mysql客戶端使用:set names utf8;
等同於
set character_set_client=utf8;
set character_set_connection=utf8;
set character_set_results=utf8;
c)set character set utf8;
等同於
set character_set_client=utf8;
set character_set_results=utf8;
set collation_connection=@@collation_database;
下面介紹下幾個MYSQL命令:
1)show character set;或show char set;
查看數據庫支持的全部字符集
2)status;或\s;
查看當前狀態 裏面包括固然的字符集設置
3)show variables like 'char%';
查看系統字符集設置,包括全部的字符集設置
4)show table status from sqlstudy like '%countries%';
查看sqlstudy數據庫中表的字符集設置
5)show full columns from countries;
查看錶列的字符集設置,關鍵是在同一個表中,每列能夠設置成不一樣的字符集
知道怎麼查看字符集了,下面我來講下如何設置這些字符集
1.修改服務器級
a. 臨時更改:
mysql>SET GLOBAL character_set_server=utf8;
b. 永久更改:
修改my.cnf文件
[mysqld]
character-set-server=utf8
2.修改數據庫級
a. 臨時更改:
mysql>SET GLOBAL character_set_database=utf8;
b. 永久更改:
改了服務器級就能夠了
3.修改表級
mysql>ALTER TABLE table_name DEFAULT CHARSET utf8;
更改了後永久生效
4.修改列級
修改示例:
mysql>alter table `products` change `products_model` `products_model` varchar( 20 )
character set utf8 collate utf8_general_ci null default null;
更改了後永久生效
5.更改鏈接字符集
a. 臨時更改:
mysql> set names utf8;
b. 永久更改:
修改my.cnf文件
在[client]中增長:
default-character-set=utf8
執行SQL語句時信息的路徑是這樣的
信息輸入路徑:client→connection→server;
信息輸出路徑:server→connection→results.
一、MySQL Server收到請求時將請求數據從character_set_client轉換爲character_set_connection;
二、進行內部操做前將請求數據從character_set_connection轉換爲內部操做字符集,其肯定方法以下:
使用每一個數據字段的CHARACTER SET設定值;
若上述值不存在,則使用對應數據表的DEFAULT CHARACTER SET設定值(MySQL擴展,非SQL標準);
若上述值不存在,則使用對應數據庫的DEFAULT CHARACTER SET設定值;
若上述值不存在,則使用character_set_server設定值。
三、將操做結果從內部操做字符集轉換爲character_set_results。
下圖源自於《高性能MySQL》中關於字符集轉換的圖解:
一、產生亂碼的根本緣由
1)客戶機沒有正確地設置client字符集,致使原先的SQL語句被轉換成connection所指字符集,而這種轉換,是會丟失信息的,若是client是utf8格式,那麼若是轉換成gb2312格式,這其中一定會丟失信息,反之則不會丟失。必定要保證connection的字符集大於client字符集才能保證轉換不丟失信息。
2)數據庫字體沒有設置正確,若是數據庫字體設置不正確,那麼connection字符集轉換成database字符集照樣丟失編碼,緣由跟上面同樣。
character_set_client:咱們要告訴服務器,我給你發送的數據是什麼編碼?
character_set_connection:告訴字符集轉換器,轉換成什麼編碼?
character_set_results:查詢的結果用什麼編碼?
若是以上三者都爲字符集N,可簡寫爲set names 'N';
模擬情景1:
向默認字符集爲utf8的數據表插入utf8編碼的數據前鏈接字符集設置爲latin1,查詢時設置鏈接字符集爲utf8。
插入時根據MySQL服務器的默認設置,character_set_client、character_set_connection和character_set_results均爲latin1;
插入操做的數據將通過latin1=>latin1=>utf8的字符集轉換過程,這一過程當中每一個插入的漢字都會從原始的3個字節變成6個字節保存;
查詢時的結果將通過utf8=>utf8的字符集轉換過程,將保存的6個字節原封不動返回,產生亂碼……
例如:
mysql> set names latin1;
mysql> create table temp(name varchar(10)) charset utf8;
mysql> insert into temp values('中國');
mysql> select * from temp;
+--------+
| name |
+--------+
| 中國 |
+--------+
mysql> set names utf8;
mysql> select * from temp;
+---------------+
| name |
+---------------+
| ä¸å›½ |
+---------------+
注意:存儲字符集編碼比插入時字符集大時,若是原封不動返回數據會出現亂碼,不過可經過修改查詢字符集,避免亂碼,即不會丟失數據。
模擬情景1:
向默認字符集爲latin1的數據表插入utf8編碼的數據前設置了鏈接字符集爲utf8
插入時根據鏈接字符集設置,character_set_client、character_set_connection和character_set_results均爲utf8;
插入數據將通過utf8=>utf8=>latin1的字符集轉換,若原始數據中含有\u0000~\u00ff範圍之外的Unicode字 符,會由於沒法在latin1字符集中表示而被轉換爲「?」(0×3F)符號,之後查詢時無論鏈接字符集設置如何都沒法恢復其內容了。
例如:
mysql> set names utf8;
mysql> create table temp(name varchar(10)) charset latin1;
mysql> insert into temp values('中國');
mysql> select * from temp;
+------+
| name |
+------+
| ?? |
+------+
mysql> set names latin1;
mysql> select * from temp;
+------+
| name |
+------+
| ?? |
+------+
數據不完整了,且沒法恢復。
1)首先要明確你的客戶端時候何種編碼格式,這是最重要的(IE6通常用utf8,命令行通常是gbk,通常程序是gb2312) 2)確保你的數據庫使用utf8格式,很簡單,全部編碼通吃。 3)必定要保證connection字符集大於等於client字符集,否則就會信息丟失,好比: latin1 < gb2312 < gbk < utf8,若設置set character_set_client = gb2312,那麼至少connection的字符集要大於等於gb2312,不然就會丟失信息 4)以上三步作正確的話,那麼全部中文都被正確地轉換成utf8格式存儲進了數據庫,爲了適應不一樣的瀏覽器,不一樣的客戶端,你能夠修改character_set_results來以不一樣的編碼顯示中文字體,因爲utf8是大方向,所以web應用是我仍是傾向於使用utf8格式顯示中文的。