show charcater set;
show variables like '%character%';
1.查看mysql所支持的字符集
指令:SHOW CHARACTER SET;
很多很多匣距,這里就不全部放上來了,這里的charset代表字符集,就是編碼對應(yīng)字符的集合,后面的collation代表了字符序,字符序就是每種不同的字符集在比較時采用的不同的方法溉仑。只要表上有的字符集,就可以被我們采用。
指令:SHOW VARIABLES LIKE ‘character%’;
character_set_client: 代表客戶端字符集狂秦,客戶端最簡單的來說灌侣,就是之這個命令行,或者其它操作數(shù)據(jù)庫的網(wǎng)頁裂问,應(yīng)用等等侧啼,客戶端字符集就代表了用戶輸入的字符,用什么字符集來編碼堪簿。
character_set_connection: 代表與服務(wù)器連接層的字符集痊乾,mysql是連接mysqld服務(wù)器的客戶端,兩者連接層椭更,采用的字符集哪审。
character_set_database: 數(shù)據(jù)庫采用的字符集。
character_set_filesystem: 文件采用的肯定是二進制最合適虑瀑,不用修改湿滓。
character_set_result: 結(jié)果字符集,返回結(jié)果時采用的字符集舌狗。
character_set_server: mysql服務(wù)器采用的字符集叽奥,也就是操作默認的字符集。
character_set_system: 系統(tǒng)字符集把夸,比如我們輸入的命令'insert ...'這些語句字符串采用的字符集而线。
有一點很重要:在創(chuàng)建時未設(shè)置字符集的情況下,當(dāng)前創(chuàng)建的東西會根據(jù)上一級的字符集來確定字符集恋日,比如創(chuàng)建數(shù)據(jù)庫未指定字符集膀篮,則會采用server的字符集來作為庫的字符集,創(chuàng)建數(shù)據(jù)表時為指定字符集岂膳,則會采用數(shù)據(jù)庫的字符集來作為庫的字符集誓竿。以此類推,從下到上為 記錄<表<庫<服務(wù)器谈截。
舉個例子:
創(chuàng)建一個為指定字符集的數(shù)據(jù)庫
default-character-set=utf8
[mysqld]
character_set_server=utf8
collation_server=utf8_bin
4.在創(chuàng)建時指定字符集
除了采用默認的字符集外筷屡,還可以在創(chuàng)建時設(shè)置字符集涧偷,但是要清楚是為哪個設(shè)置字符集。
如圖毙死,在創(chuàng)建數(shù)據(jù)表時指定字符集:
指令:CREATE DATABASE db2 character set gbk;
不管創(chuàng)建什么燎潮,后面加一句character set <字符集>; ?這樣就可以指定了。
當(dāng)然還可以更改一個數(shù)據(jù)表的字符集:alter table tbname convert to charset gbk;
一扼倘、字符集和校驗規(guī)則
字符集是一套符合和編碼确封,校驗規(guī)則(collation)是在字符集內(nèi)用于比較字符的一套規(guī)則,即字符集的排序規(guī)則再菊。MySQL可以使用對種字符集和檢驗規(guī)則來組織字符爪喘。
MySQL服務(wù)器可以支持多種字符集,在同一臺服務(wù)器纠拔,同一個數(shù)據(jù)庫秉剑,甚至同一個表的不同字段都可以指定使用不同的字符集,相比oracle等其他數(shù)據(jù)庫管理系統(tǒng)稠诲,在同一個數(shù)據(jù)庫只能使用相同的字符集侦鹏,MySQL明顯存在更大的靈活性。
每種字符集都可能有多種校對規(guī)則吕粹,并且都有一個默認的校對規(guī)則种柑,并且每個校對規(guī)則只是針對某個字符集,和其他的字符集么有關(guān)系匹耕。
在MySQL中聚请,字符集的概念和編碼方案被看做是同義詞,一個字符集是一個轉(zhuǎn)換表和一個編碼方案的組合稳其。
Unicode(Universal Code)是一種在計算機上使用的字符編碼驶赏。Unicode 是為了解決傳統(tǒng)的字符編碼方案的局限而產(chǎn)生的,它為每種語言中的每個字符設(shè)定了統(tǒng)一并且唯一的二進制編碼既鞠,以滿足跨語言煤傍、跨平臺進行文本轉(zhuǎn)換、處理的要求嘱蛋。Unicode存在不同的編碼方案蚯姆,包括Utf-8,Utf-16和Utf-32洒敏。Utf表示Unicode Transformation Format龄恋。
二、查看mysql字符集方法
1凶伙、查看mysql服務(wù)器支持的字符集
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郭毕、查看字符集的校對規(guī)則
mysql> show collation;
mysql> show collation like 'utf8';
mysql> select * from information_schema.collations where collation_name like 'utf8%';
3、查看當(dāng)前數(shù)據(jù)庫的字符集
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:客戶端請求數(shù)據(jù)的字符集
character_set_connection:客戶機/服務(wù)器連接的字符集
character_set_database:默認數(shù)據(jù)庫的字符集函荣,無論默認數(shù)據(jù)庫如何改變显押,都是這個字符集扳肛;如果沒有默認數(shù)據(jù)庫,那就使用 character_set_server指定的字符集乘碑,這個變量建議由系統(tǒng)自己管理挖息,不要人為定義。
character_set_filesystem:把os上文件名轉(zhuǎn)化成此字符集蝉仇,即把 character_set_client轉(zhuǎn)換character_set_filesystem旋讹, 默認binary是不做任何轉(zhuǎn)換的
character_set_results:結(jié)果集殖蚕,返回給客戶端的字符集
character_set_server:數(shù)據(jù)庫服務(wù)器的默認字符集
character_set_system:系統(tǒng)字符集轿衔,這個值總是utf8,不需要設(shè)置睦疫。這個字符集用于數(shù)據(jù)庫對象(如表和列)的名字害驹,也用于存儲在目錄表中的函數(shù)的名字。
4蛤育、查看當(dāng)前數(shù)據(jù)庫的校對規(guī)則
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 當(dāng)前連接的字符集宛官。
collation_database??? 當(dāng)前日期的默認校對。每次用USE語句來“跳轉(zhuǎn)”到另一個數(shù)據(jù)庫的時候瓦糕,這個變量的值就會改變底洗。如果沒有當(dāng)前數(shù)據(jù)庫,這個變量的值就是collation_server變量的值咕娄。
collation_server 服務(wù)器的默認校對亥揖。
排序方式的命名規(guī)則為:字符集名字_語言_后綴,其中各個典型后綴的含義如下:
1)_ci:不區(qū)分大小寫的排序方式
2)_cs:區(qū)分大小寫的排序方式
3)_bin:二進制排序方式圣勒,大小比較將根據(jù)字符編碼费变,不涉及人類語言,因此_bin的排序方式不包含人類語言
三圣贸、MySQL字符集的設(shè)置
1挚歧、概述
MySQL字符集設(shè)置分為兩類:
1)創(chuàng)建對象的默認值。
2)控制server和client端交互通信的配置吁峻。
1滑负、創(chuàng)建對象的默認值
字符集合校對規(guī)則有4個級別的默認設(shè)置:
1)服務(wù)器級別;
2)數(shù)據(jù)庫級別用含;
3)表級別矮慕、列級別;
4)連接級別耕餐。
更低級別的設(shè)置會集成高級別的設(shè)置凡傅。
這里有一個通用的規(guī)則:先為服務(wù)器或者數(shù)據(jù)庫選擇一個合理的字符集,然后根據(jù)不同的實際情況肠缔,讓某個列選擇自己的字符集夏跷。
2哼转、控制server和client端交互通信的配置
大部分MySQL客戶端都不具備同時支持多種字符集的能力,每次都只能使用一種字符集槽华。
客戶和服務(wù)器之間的字符集轉(zhuǎn)換工作是由如下幾個MySQL系統(tǒng)變量控制的壹蔓。
1)character_set_server:mysql server默認字符集。
2)character_set_database:數(shù)據(jù)庫默認字符集猫态。
3)character_set_client:MySQL server假定客戶端發(fā)送的查詢使用的字符集佣蓉。
4)character_set_connection:MySQL Server接收客戶端發(fā)布的查詢請求后,將其轉(zhuǎn)換為character_set_connection變量指定的字符集亲雪。
5)character_set_results:mysql server把結(jié)果集和錯誤信息轉(zhuǎn)換為character_set_results指定的字符集勇凭,并發(fā)送給客戶端。
6)character_set_system:系統(tǒng)元數(shù)據(jù)(字段名等)字符集
還有以collation_開頭的同上面對應(yīng)的變量义辕,用來描述字符序虾标。
注意事項:
? my.cnf中的default_character_set設(shè)置只影響mysql命令連接服務(wù)器時的連接字符集,不會對使用libmysqlclient庫的應(yīng)用程序產(chǎn)生任何作用灌砖!
? 對字段進行的SQL函數(shù)操作通常都是以內(nèi)部操作字符集進行的璧函,不受連接字符集設(shè)置的影響。
? SQL語句中的裸字符串會受到連接字符集或introducer設(shè)置的影響基显,對于比較之類的操作可能產(chǎn)生完全不同的結(jié)果蘸吓,需要小心!
3撩幽、默認情況下字符集選擇規(guī)則
(1)編譯MySQL 時库继,指定了一個默認的字符集,這個字符集是 latin1;
(2)安裝MySQL 時摸航,可以在配置文件 (my.cnf) 中指定一個默認的的字符集制跟,如果沒指定,這個值繼承自編譯時指定的;
(3)啟動mysqld 時酱虎,可以在命令行參數(shù)中指定一個默認的的字符集雨膨,如果沒指定,這個值繼承自配置文件中的配置,此時character_set_server被設(shè)定為這個默認的字符集;
(4)當(dāng)創(chuàng)建一個新的數(shù)據(jù)庫時读串,除非明確指定聊记,這個數(shù)據(jù)庫的字符集被缺省設(shè)定為character_set_server;
(5)當(dāng)選定了一個數(shù)據(jù)庫時,character_set_database被設(shè)定為這個數(shù)據(jù)庫默認的字符集;
(6)在這個數(shù)據(jù)庫里創(chuàng)建一張表時恢暖,表默認的字符集被設(shè)定為character_set_database排监,也就是這個數(shù)據(jù)庫默認的字符集;
(7)當(dāng)在表內(nèi)設(shè)置一欄時,除非明確指定杰捂,否則此欄缺省的字符集就是表默認的字符集;
2舆床、分述
2.1、為列分配字符集
屬于同一個表的不同列可以有不同的字符集,如果沒有為一個列顯示的定義字符集就使用默認字符集挨队。創(chuàng)建一個表的時候谷暮,若顯示的為列指定字符集,則字符集作為數(shù)據(jù)類型選項包含在其中盛垦,要放在數(shù)據(jù)類型后面及空指定和主鍵前面湿弦。
例如:
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
插入數(shù)據(jù),感受一下效果:
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;
*************************** 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.3颊埃、為數(shù)據(jù)庫指定字符集
創(chuàng)建的每個數(shù)據(jù)庫都有一個默認字符集,如果沒有指定蝶俱,就用latin1班利。
create database dbking charset=utf8;
注意:創(chuàng)建數(shù)據(jù)庫分配字符集可以采用以下幾種子句:
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;命令查看數(shù)據(jù)庫創(chuàng)建語句:
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.4、為列分配校對規(guī)則
每個列都應(yīng)該有一個校對跷乐,如果沒有顯示指定肥败,MySQL就使用屬于該字符集的默認校對。如果指定了一個字符集和一個校對愕提,字符集應(yīng)該放在前面。
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;
查看表的校驗規(guī)則信息:
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.5、為表指定校對規(guī)則
create table table_collate(
c1 varchar(10),
c2 varchar(10))engine=innodb default charset utf8 collate utf8_romanian_ci;
檢查表的校對規(guī)則:
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.6证膨、為數(shù)據(jù)庫指定校對規(guī)則
create database dbking102 default charset utf8 collate utf8_romanian_ci;
查看數(shù)據(jù)庫定義語句:
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.7如输、字符直接量字符集
如果沒有顯示指定,那么字符直接量的字符集就是數(shù)據(jù)庫的默認字符集央勒。如果要顯示分配另一個字符集不见,需要把字符集的名字放在直接量前面,并且要在字符集前面加上下劃線崔步。
mysql> select _utf8'語言 Language 言語 язык';
+---------------------------------+
| 語言 Language 言語 язык???? |
+---------------------------------+
| 語言 Language 言語 язык???? |
+---------------------------------+??
2.8稳吮、修改和設(shè)置MySQL服務(wù)器級別字符集
MySQL服務(wù)器支持眾多不同的字符集,這類字符集可在編譯時和運行時指定井濒。
??? 1) 編譯時指定
編譯時可指定默認字符集和默認校對規(guī)則灶似,要想同時更改默認字符集和校對規(guī)則,要同時使用--with-charset和--with-collation選項瑞你。校對規(guī)則必須是字符集的合法校對規(guī)則酪惭。
./configure -- with-charset=CHARSET --with-collation=COLLATION
通過configure選項--with-extra-charsets=LIST,可以定義在服務(wù)器中再定義增加字符集者甲。LIST 指下面任何一項:
a.空格間隔的一系列字符集名
b.complex -春感,以包括不能動態(tài)裝載的所有字符集
c.all –,以將所有字符集包括進二進制
./configure -- with-charset=CHARSET --with-collation=COLLATION --with-extra-charsets=all
??? 2) 在參數(shù)文件my.cnf中指定
[mysqld]
character_set_server=utf8
??? --影響參數(shù):character_set_server 和 character_set_database
??? --注意:修改后要重啟數(shù)據(jù)庫才能生效。
[client]
default-character-set=utf8
??? --影響參數(shù):character_set_client鲫懒,character_set_connection 和character_set_results纺铭。
--注意:修改后無需重啟數(shù)據(jù)庫。
3) 在啟動參數(shù)前指定
./mysqld --character-set-server=utf8 &
--影響參數(shù):character_set_server 和 character_set_database
4)在mysql客戶端登陸時通過--default-character-set指定
mysql -uroot -pmysql?--default-character-set=utf8
--影響參數(shù):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;
3谦秧、總結(jié)
下面介紹下幾個MYSQL命令:
1)show character set;或show char set;
查看數(shù)據(jù)庫支持的所有字符集
2)status;或\s;
查看當(dāng)前狀態(tài) 里面包括當(dāng)然的字符集設(shè)置
3)show variables like 'char%';
查看系統(tǒng)字符集設(shè)置竟纳,包括所有的字符集設(shè)置
4)show table status from sqlstudy like '%countries%';
查看sqlstudy數(shù)據(jù)庫中表的字符集設(shè)置
5)show full columns from countries;
查看表列的字符集設(shè)置,關(guān)鍵是在同一個表中疚鲤,每列可以設(shè)置成不同的字符集
知道怎么查看字符集了锥累,下面我來說下如何設(shè)置這些字符集
1.修改服務(wù)器級
a. 臨時更改:
mysql>SET GLOBAL character_set_server=utf8;
b. 永久更改:
修改my.cnf文件
[mysqld]
character-set-server=utf8
2.修改數(shù)據(jù)庫級
a. 臨時更改:
mysql>SET GLOBAL character_set_database=utf8;
b. 永久更改:
改了服務(wù)器級就可以了
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
執(zhí)行SQL語句時信息的路徑是這樣的
信息輸入路徑:client→connection→server;
信息輸出路徑:server→connection→results.
四、MySQL數(shù)據(jù)庫中字符集轉(zhuǎn)換流程
1集歇、MySQL Server收到請求時將請求數(shù)據(jù)從character_set_client轉(zhuǎn)換為character_set_connection桶略;
2、進行內(nèi)部操作前將請求數(shù)據(jù)從character_set_connection轉(zhuǎn)換為內(nèi)部操作字符集诲宇,其確定方法如下:
使用每個數(shù)據(jù)字段的CHARACTER SET設(shè)定值际歼;
若上述值不存在,則使用對應(yīng)數(shù)據(jù)表的DEFAULT CHARACTER SET設(shè)定值(MySQL擴展姑蓝,非SQL標(biāo)準(zhǔn))鹅心;
若上述值不存在,則使用對應(yīng)數(shù)據(jù)庫的DEFAULT CHARACTER SET設(shè)定值纺荧;
若上述值不存在旭愧,則使用character_set_server設(shè)定值。
3宙暇、將操作結(jié)果從內(nèi)部操作字符集轉(zhuǎn)換為character_set_results输枯。
下圖源自于《高性能MySQL》中關(guān)于字符集轉(zhuǎn)換的圖解:
五、MySQL數(shù)據(jù)庫亂碼原因解析及案例
1占贫、產(chǎn)生亂碼的根本原因
1)客戶機沒有正確地設(shè)置client字符集桃熄,導(dǎo)致原先的SQL語句被轉(zhuǎn)換成connection所指字符集,而這種轉(zhuǎn)換靶剑,是會丟失信息的蜻拨,如果client是utf8格式,那么如果轉(zhuǎn)換成gb2312格式桩引,這其中必定會丟失信息缎讼,反之則不會丟失。一定要保證connection的字符集大于client字符集才能保證轉(zhuǎn)換不丟失信息坑匠。
2)數(shù)據(jù)庫字體沒有設(shè)置正確血崭,如果數(shù)據(jù)庫字體設(shè)置不正確,那么connection字符集轉(zhuǎn)換成database字符集照樣丟失編碼,原因跟上面一樣夹纫。
2咽瓷、亂碼或數(shù)據(jù)丟失
character_set_client:我們要告訴服務(wù)器,我給你發(fā)送的數(shù)據(jù)是什么編碼舰讹?
character_set_connection:告訴字符集轉(zhuǎn)換器茅姜,轉(zhuǎn)換成什么編碼?
character_set_results:查詢的結(jié)果用什么編碼月匣?
如果以上三者都為字符集N,可簡寫為set names 'N';
2.1 亂碼問題
模擬情景1:
向默認字符集為utf8的數(shù)據(jù)表插入utf8編碼的數(shù)據(jù)前連接字符集設(shè)置為latin1钻洒,查詢時設(shè)置連接字符集為utf8。
插入時根據(jù)MySQL服務(wù)器的默認設(shè)置锄开,character_set_client素标、character_set_connection和character_set_results均為latin1;
插入操作的數(shù)據(jù)將經(jīng)過latin1=>latin1=>utf8的字符集轉(zhuǎn)換過程萍悴,這一過程中每個插入的漢字都會從原始的3個字節(jié)變成6個字節(jié)保存头遭;
查詢時的結(jié)果將經(jīng)過utf8=>utf8的字符集轉(zhuǎn)換過程,將保存的6個字節(jié)原封不動返回癣诱,產(chǎn)生亂碼……
例如:
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 |
+---------------+
| ??-??? |
+---------------+
注意:存儲字符集編碼比插入時字符集大時计维,如果原封不動返回數(shù)據(jù)會出現(xiàn)亂碼,不過可通過修改查詢字符集狡刘,避免亂碼享潜,即不會丟失數(shù)據(jù)。
2.2 數(shù)據(jù)丟失問題
模擬情景1:
向默認字符集為latin1的數(shù)據(jù)表插入utf8編碼的數(shù)據(jù)前設(shè)置了連接字符集為utf8
插入時根據(jù)連接字符集設(shè)置嗅蔬,character_set_client、character_set_connection和character_set_results均為utf8疾就;
插入數(shù)據(jù)將經(jīng)過utf8=>utf8=>latin1的字符集轉(zhuǎn)換澜术,若原始數(shù)據(jù)中含有\(zhòng)u0000~\u00ff范圍以外的Unicode字 符,會因為無法在latin1字符集中表示而被轉(zhuǎn)換為“?”(0×3F)符號猬腰,以后查詢時不管連接字符集設(shè)置如何都無法恢復(fù)其內(nèi)容了鸟废。
例如:
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 |
+------+
| ?? |
+------+
數(shù)據(jù)不完整了,且無法恢復(fù)姑荷。
3盒延、 亂碼終極解決方案
1)首先要明確你的客戶端時候何種編碼格式,這是最重要的(IE6一般用utf8鼠冕,命令行一般是gbk添寺,一般程序是gb2312)
2)確保你的數(shù)據(jù)庫使用utf8格式,很簡單懈费,所有編碼通吃计露。
3)一定要保證connection字符集大于等于client字符集,不然就會信息丟失,比如: latin1 < gb2312 < gbk < utf8票罐,若設(shè)置set character_set_client = gb2312叉趣,那么至少connection的字符集要大于等于gb2312,否則就會丟失信息
4)以上三步做正確的話该押,那么所有中文都被正確地轉(zhuǎn)換成utf8格式存儲進了數(shù)據(jù)庫疗杉,為了適應(yīng)不同的瀏覽器,不同的客戶端蚕礼,你可以修改character_set_results來以不同的編碼顯示中文字體烟具,由于utf8是大方向,因此web應(yīng)用是我還是傾向于使用utf8格式顯示中文的闻牡。