天天看點

Mysql 字元集(學習筆記十)

show charcater set;

show variables like '%character%';

1.檢視mysql所支援的字元集

指令:SHOW CHARACTER SET; 很多很多,這裡就不全部放上來了,這裡的charset代表字元集,就是編碼對應字元的集合,後面的collation代表了字元序,字元序就是每種不同的字元集在比較時采用的不同的方法。隻要表上有的字元集,就可以被我們采用。 2.目前關于mysql的各種字元集 指令:SHOW VARIABLES LIKE ‘character%’; 這張圖是經過我更改my.ini配置後的各個項目的字元集,我都改成了utf8,因為utf8支援漢字,幾乎成了目前Web開發界的标準字元集。下面我來解釋下各個項代表的含義。 character_set_client: 代表用戶端字元集,用戶端最簡單的來說,就是之這個指令行,或者其它操作資料庫的網頁,應用等等,用戶端字元集就代表了使用者輸入的字元,用什麼字元集來編碼。 character_set_connection: 代表與伺服器連接配接層的字元集,mysql是連接配接mysqld伺服器的用戶端,兩者連接配接層,采用的字元集。 character_set_database: 資料庫采用的字元集。 character_set_filesystem: 檔案采用的肯定是二進制最合适,不用修改。 character_set_result: 結果字元集,傳回結果時采用的字元集。 character_set_server: mysql伺服器采用的字元集,也就是操作預設的字元集。 character_set_system: 系統字元集,比如我們輸入的指令'insert ...'這些語句字元串采用的字元集。 有一點很重要:在建立時未設定字元集的情況下,目前建立的東西會根據上一級的字元集來确定字元集,比如建立資料庫未指定字元集,則會采用server的字元集來作為庫的字元集,建立資料表時為指定字元集,則會采用資料庫的字元集來作為庫的字元集。以此類推,從下到上為 記錄<表<庫<伺服器。 舉個例子: 建立一個為指定字元集的資料庫 3.更改my.ini配置檔案來更改預設字元集 [mysql]

default-character-set=utf8

[mysqld]

character_set_client=utf8

character_set_server=utf8

collation_server=utf8_bin

4.在建立時指定字元集

除了采用預設的字元集外,還可以在建立時設定字元集,但是要清楚是為哪個設定字元集。 如圖,在建立資料表時指定字元集: 指令:CREATE DATABASE db2 character set gbk; 不管建立什麼,後面加一句character set <字元集>;  這樣就可以指定了。 當然還可以更改一個資料表的字元集:alter table tbname convert to charset gbk; MySQL字元集詳解

一、字元集和校驗規則

字元集是一套符合和編碼,校驗規則(collation)是在字元集内用于比較字元的一套規則,即字元集的排序規則。MySQL可以使用對種字元集和檢驗規則來組織字元。

MySQL伺服器可以支援多種字元集,在同一台伺服器,同一個資料庫,甚至同一個表的不同字段都可以指定使用不同的字元集,相比oracle等其他資料庫管理系統,在同一個資料庫隻能使用相同的字元集,MySQL明顯存在更大的靈活性。

每種字元集都可能有多種校對規則,并且都有一個預設的校對規則,并且每個校對規則隻是針對某個字元集,和其他的字元集麼有關系。

在MySQL中,字元集的概念和編碼方案被看做是同義詞,一個字元集是一個轉換表和一個編碼方案的組合。

Unicode(Universal Code)是一種在計算機上使用的字元編碼。Unicode 是為了解決傳統的字元編碼方案的局限而産生的,它為每種語言中的每個字元設定了統一并且唯一的二進制編碼,以滿足跨語言、跨平台進行文本轉換、處理的要求。Unicode存在不同的編碼方案,包括Utf-8,Utf-16和Utf-32。Utf表示Unicode Transformation Format。

二、檢視mysql字元集方法

1、檢視mysql伺服器支援的字元集

mysql> show character set;

mysql> select * from information_schema.character_sets;

mysql> select character_set_name, default_collate_name, description, maxlen from

information_schema.character_sets;

2、檢視字元集的校對規則

mysql> show collation;

mysql> show collation like 'utf8';

mysql> select * from information_schema.collations where collation_name like 'utf8%';

3、檢視目前資料庫的字元集

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,不需要設定。這個字元集用于資料庫對象(如表和列)的名字,也用于存儲在目錄表中的函數的名字。

4、檢視目前資料庫的校對規則

mysql> show variables like 'collation%';

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

| 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、概述

MySQL字元集設定分為兩類:

1)建立對象的預設值。

2)控制server和client端互動通信的配置。

1、建立對象的預設值

字元集合校對規則有4個級别的預設設定:

1)伺服器級别;

2)資料庫級别;

3)表級别、列級别;

4)連接配接級别。

更低級别的設定會內建進階别的設定。

這裡有一個通用的規則:先為伺服器或者資料庫選擇一個合理的字元集,然後根據不同的實際情況,讓某個列選擇自己的字元集。

2、控制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設定的影響,對于比較之類的操作可能産生完全不同的結果,需要小心!

3、預設情況下字元集選擇規則

(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、分述

2.1、為列配置設定字元集

屬于同一個表的不同列可以有不同的字元集,如果沒有為一個列顯示的定義字元集就使用預設字元集。建立一個表的時候,若顯示的為列指定字元集,則字元集作為資料類型選項包含在其中,要放在資料類型後面及空指定和主鍵前面。

例如:

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)

2.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;

Table: table_charset

Create Table: CREATE TABLE `table_charset` (

`c1` varchar(10) DEFAULT NULL,

`c2` varchar(10) DEFAULT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8

測試:

mysql> insert into table_charset(c1,c2) values('圖靈','圖靈');

mysql> select * from table_charset;

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

| c1 | c2 |

| 圖靈 | 圖靈 |

2.3、為資料庫指定字元集

建立的每個資料庫都有一個預設字元集,如果沒有指定,就用latin1。

create database dbking charset=utf8;

注意:建立資料庫配置設定字元集可以采用以下幾種子句: charset utf8; default charset utf8; char set utf8; default char 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 */ |

2.4、為列配置設定校對規則

每個列都應該有一個校對,如果沒有顯示指定,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;

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

| A | A |

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.5、為表指定校對規則

create table table_collate(

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_collate | c1 | utf8_romanian_ci |

| table_collate | c2 | utf8_romanian_ci |

2 rows in set (0.00 sec)

2.6、為資料庫指定校對規則

create database dbking102 default charset utf8 collate utf8_romanian_ci;

檢視資料庫定義語句:

mysql> show create database dbking102\G;

Database: dbking102

Create Database: CREATE DATABASE `dbking102` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_romanian_ci */

2.7、字元直接量字元集

如果沒有顯示指定,那麼字元直接量的字元集就是資料庫的預設字元集。如果要顯示配置設定另一個字元集,需要把字元集的名字放在直接量前面,并且要在字元集前面加上下劃線。

mysql> select _utf8'語言 Language 言語 язык';

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

| 語言 Language 言語 язык     |

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

2.8、修改和設定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中指定

    --影響參數:character_set_server 和 character_set_database

    --注意:修改後要重新開機資料庫才能生效。

[client]

    --影響參數: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 collation_connection=@@collation_database;

3、總結

下面介紹下幾個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檔案

character-set-server=utf8

2.修改資料庫級

mysql>SET GLOBAL character_set_database=utf8;

改了伺服器級就可以了

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.更改連接配接字元集

mysql> set names utf8;

在[client]中增加:

執行SQL語句時資訊的路徑是這樣的

資訊輸入路徑:client→connection→server;

資訊輸出路徑:server→connection→results.

四、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。

下圖源自于《高性能MySQL》中關于字元集轉換的圖解:

Mysql 字元集(學習筆記十)

五、MySQL資料庫亂碼原因解析及案例

1、産生亂碼的根本原因

1)客戶機沒有正确地設定client字元集,導緻原先的SQL語句被轉換成connection所指字元集,而這種轉換,是會丢失資訊的,如果client是utf8格式,那麼如果轉換成gb2312格式,這其中必定會丢失資訊,反之則不會丢失。一定要保證connection的字元集大于client字元集才能保證轉換不丢失資訊。

2)資料庫字型沒有設定正确,如果資料庫字型設定不正确,那麼connection字元集轉換成database字元集照樣丢失編碼,原因跟上面一樣。

2、亂碼或資料丢失

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個位元組原封不動傳回,産生亂碼……

mysql> set names latin1;

mysql> create table temp(name varchar(10)) charset utf8;

mysql> insert into temp values('中國');

mysql> select * from temp;

+--------+

| name |

| 中國 |

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

| 中国 |

注意:存儲字元集編碼比插入時字元集大時,如果原封不動傳回資料會出現亂碼,不過可通過修改查詢字元集,避免亂碼,即不會丢失資料。

2.2 資料丢失問題

向預設字元集為latin1的資料表插入utf8編碼的資料前設定了連接配接字元集為utf8

插入時根據連接配接字元集設定,character_set_client、character_set_connection和character_set_results均為utf8;

插入資料将經過utf8=>utf8=>latin1的字元集轉換,若原始資料中含有\u0000~\u00ff範圍以外的Unicode字 符,會因為無法在latin1字元集中表示而被轉換為“?”(0×3F)符号,以後查詢時不管連接配接字元集設定如何都無法恢複其内容了。

Mysql 字元集(學習筆記十)

mysql> create table temp(name varchar(10)) charset latin1;

+------+

| ?? |

資料不完整了,且無法恢複。

3、 亂碼終極解決方案

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