MySQL字符集詳解

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。服務器

2、查看mysql字符集方法

一、查看mysql服務器支持的字符集

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的排序方式不包含人類語言

3、MySQL字符集的設置

一、概述

MySQL字符集設置分爲兩類:

1)建立對象的默認值。

2)控制server和client端交互通訊的配置。

一、建立對象的默認值

字符集合校對規則有4個級別的默認設置:

1)服務器級別;

2)數據庫級別;

3)表級別、列級別;

4)鏈接級別。

更低級別的設置會集成高級別的設置。

這裏有一個通用的規則:先爲服務器或者數據庫選擇一個合理的字符集,而後根據不一樣的實際狀況,讓某個列選擇本身的字符集。

二、控制server和client端交互通訊的配置

大部分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)當在表內設置一欄時,除非明確指定,不然此欄缺省的字符集就是表默認的字符集;

二、分述

2.一、爲列分配字符集

屬於同一個表的不一樣列能夠有不一樣的字符集,若是沒有爲一個列顯示的定義字符集就使用默認字符集。建立一個表的時候,若顯示的爲列指定字符集,則字符集做爲數據類型選項包含在其中,要放在數據類型後面及空指定和主鍵前面。

例如:

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 setcharset

使用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)

2.二、爲表分配字符集

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)

2.三、爲數據庫指定字符集

建立的每一個數據庫都有一個默認字符集,若是沒有指定,就用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)

2.四、爲列分配校對規則

每一個列都應該有一個校對,若是沒有顯示指定,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 '='

2.五、爲表指定校對規則

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)

2.六、爲數據庫指定校對規則

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)

2.七、字符直接量字符集

若是沒有顯示指定,那麼字符直接量的字符集就是數據庫的默認字符集。若是要顯示分配另外一個字符集,須要把字符集的名字放在直接量前面,而且要在字符集前面加上下劃線。

mysql> select _utf8'語言 Language 言語 язык';
+---------------------------------+
| 語言 Language 言語 язык     |
+---------------------------------+
| 語言 Language 言語 язык     |
+---------------------------------+   
2.八、修改和設置MySQL服務器級別字符集

MySQL服務器支持衆多不一樣的字符集,這類字符集可在編譯時和運行時指定。

    1) 編譯時指定

編譯時可指定默認字符集和默認校對規則,要想同時更改默認字符集和校對規則,要同時使用--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

    2) 在參數文件my.cnf中指定

[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。

    5)臨時指定

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.

4、MySQL數據庫中字符集轉換流程

一、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》中關於字符集轉換的圖解:

clip_image002

5、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';

2.1 亂碼問題

模擬情景1:

向默認字符集爲utf8的數據表插入utf8編碼的數據前鏈接字符集設置爲latin1,查詢時設置鏈接字符集爲utf8。

插入時根據MySQL服務器的默認設置,character_set_client、character_set_connection和character_set_results均爲latin1;
插入操做的數據將通過latin1=>latin1=>utf8的字符集轉換過程,這一過程當中每一個插入的漢字都會從原始的3個字節變成6個字節保存;
查詢時的結果將通過utf8=>utf8的字符集轉換過程,將保存的6個字節原封不動返回,產生亂碼……

clip_image004

例如:

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 |

+---------------+

| 中国 |

+---------------+

注意:存儲字符集編碼比插入時字符集大時,若是原封不動返回數據會出現亂碼,不過可經過修改查詢字符集,避免亂碼,即不會丟失數據。

2.2 數據丟失問題

模擬情景1:

向默認字符集爲latin1的數據表插入utf8編碼的數據前設置了鏈接字符集爲utf8
插入時根據鏈接字符集設置,character_set_client、character_set_connection和character_set_results均爲utf8;
插入數據將通過utf8=>utf8=>latin1的字符集轉換,若原始數據中含有\u0000~\u00ff範圍之外的Unicode字 符,會由於沒法在latin1字符集中表示而被轉換爲「?」(0×3F)符號,之後查詢時無論鏈接字符集設置如何都沒法恢復其內容了。

clip_image006

例如:

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格式顯示中文的。

相關文章
相關標籤/搜索