MySQL的字符集

         MySQL的字符集支持(Character Set Support)有兩個方面:字符集(Character set)和排序方式(Collation)。  html

        字符(Character)是指人類語言中最小的表義符號。給定一系列字符,對每一個字符賦予一個數值,用數值來表明對應的字符,這一數值就是字符的編碼(Encoding)。例如,咱們給字符'A'賦予數值0,給字符'B'賦予數值1,則0就是字符'A'的編碼; 給定一系列字符並賦予對應的編碼後,全部這些字符和編碼對組成的集合就是字符集(Character Set)。例如,給定字符列表爲{'A','B'}時,{'A'=>0, 'B'=>1}就是一個字符集;mysql

        字符序(Collation)是指在同一字符集內字符之間的比較規則;  肯定字符序後,才能在一個字符集上定義什麼是等價的字符,以及字符之間的大小關係;  每一個字符序惟一對應一種字符集,但一個字符集能夠對應多種字符序,其中有一個是默認字符序(Default Collation);sql

        MySQL中的字符序名稱聽從命名慣例:以字符序對應的字符集名稱開頭;以_ci(表示大小寫不敏感)、_cs(表示大小寫敏感)或_bin(表示按編碼值比較)結尾。例如:在字符序``utf8_general_ci''下,字符``a''和``A''是等價的;數據庫

         MySQL對於字符集的支持細化到四個層次:服務器(server),數據庫(database),數據表(table)和鏈接(connection)。服務器

 

 1、MySQL默認字符集函數

         MySQL對於字符集的指定能夠細化到一個數據庫,一張表,一列,應該用什麼字符集。性能

         可是,傳統的程序在建立數據庫和數據表時並無使用那麼複雜的配置,它們用的是默認的配置,那麼,默認的配置從何而來呢?測試

         (1) 編譯MySQL 時,指定了一個默認的字符集,這個字符集是 latin1;編碼

         (2) 安裝MySQL 時,能夠在配置文件 (my.ini) 中指定一個默認的的字符集,若是沒指定,這個值繼承自編譯時指定的;spa

         (3) 啓動mysqld 時,能夠在命令行參數中指定一個默認的的字符集,若是沒指定,這個值繼承自配置文件中的配置,此時 character_set_server 被設定爲這個默認的字符集;

         (4) 當建立一個新的數據庫時,除非明確指定,這個數據庫的字符集被缺省設定爲character_set_server;

         (5) 當選定了一個數據庫時,character_set_database 被設定爲這個數據庫默認的字符集;

         (6) 在這個數據庫裏建立一張表時,表默認的字符集被設定爲 character_set_database,也就是這個數據庫默認的字符集;

         (7) 當在表內設置一欄時,除非明確指定,不然此欄缺省的字符集就是表默認的字符集;

         簡單的總結一下,若是什麼地方都不修改,那麼全部的數據庫的全部表的全部欄位的都用latin1存儲,不過咱們若是安裝 MySQL,通常都會選擇多語言支持,也就是說,安裝程序會自動在配置文件中把default_character_set 設置爲 UTF-8,這保證了缺省狀況下,全部的數據庫的全部表的全部欄位的都用 UTF-8 存儲。

 

 2、查看字符集

 一、查看MySQL數據庫服務器字符集(服務器級)

         mysql> show variables like '%char%';

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

         | Variable_name            | Value                                    |

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

         | character_set_client     | latin1                                   |-- 客戶端字符集

         | character_set_connection | latin1                                   |

         | character_set_database   | latin1                                   |-- 數據庫字符集

         | character_set_filesystem | binary                                   |

         | character_set_results    | latin1                                   |

         | character_set_server     | latin1                                   |-- 服務器字符集

         | character_set_system     | utf8                                     |

         | character_sets_dir       | D:\MySQL\MySQL Server 5.1\share\charsets\ |

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

系統變量:

– character_set_server:默認的內部操做字符集

– character_set_client:客戶端來源數據使用的字符集

– character_set_connection:鏈接層字符集

– character_set_results:查詢結果字符集

– character_set_database:當前選中數據庫的默認字符集

– character_set_system:系統元數據(字段名等)字符集

– 還有以collation_開頭的同上面對應的變量,用來描述字符序。

設置保存在my.ini文件裏。

 

二、查看數據庫的字符集(數據庫級)

         select * from information_schema.schemata where schema_name = '庫名';

例:

mysql> select * from information_schema.schemata where schema_name='testdb' \G;

*************************** 1. row ***************************

              CATALOG_NAME: NULL

               SCHEMA_NAME: testdb

DEFAULT_CHARACTER_SET_NAME: gbk

    DEFAULT_COLLATION_NAME: gbk_chinese_ci

                  SQL_PATH: NULL

 

     1)若沒有顯式設置,則自動使用服務器級的配置 

     2.)顯式設置:在建立庫時指定 

       create database 庫名 DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci; 

 

三、查看MySQL數據表(table)的字符集(表級)

      語法:show create table 表名

mysql> show create table tb \G;

*************************** 1. row ***************************

       Table: tb

Create Table: CREATE TABLE `tb` (

  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,

  `Name` char(20) NOT NULL,

  `Age` tinyint(4) NOT NULL,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=gbk

1 row in set (0.00 sec)

 

查看Collation

      語法:show table status from 數據庫名 like  ‘數據表名’;

mysql> show table status from testdb like '%tb%' \G;

*************************** 1. row ***************************

           Name: tb

         Engine: InnoDB

        Version: 10

     Row_format: Compact

           Rows: 1

 Avg_row_length: 16384

    Data_length: 16384

Max_data_length: 0

   Index_length: 0

      Data_free: 621805568

 Auto_increment: 2

    Create_time: 2013-08-14 22:27:06

    Update_time: NULL

     Check_time: NULL

      Collation: gbk_chinese_ci

       Checksum: NULL

 Create_options:

        Comment:

*************************** 2. row ***************************

           Name: tb11

         Engine: InnoDB

        Version: 10

     Row_format: Compact

           Rows: 2

 Avg_row_length: 8192

    Data_length: 16384

Max_data_length: 0

   Index_length: 0

      Data_free: 621805568

 Auto_increment: NULL

    Create_time: 2013-08-14 22:44:09

    Update_time: NULL

     Check_time: NULL

      Collation: gbk_chinese_ci

       Checksum: NULL

 Create_options:

        Comment:

2 rows in set (0.00 sec)

 

Collation:用於指定數據集如何排序,以及字符串的比對規則。

每一個 character set 會對應必定數量的 collation. 查看方法是在 mysql 的 console 下輸入:

        mysql>show collation;

 

 

 mysql collation的命名規則:
        它們以其相關的字符集名開始,一般包括一個語言名,而且以_ci(大小寫不敏感)、_cs(大小寫敏感)或_bin(二元)結束。

        好比latin1字符集有如下幾種校訂規則:

        校對規則                           含義
    latin1_german1_ci             德國DIN-1
    latin1_swedish_ci              瑞典/芬蘭
    latin1_danish_ci                 丹麥/挪威
    latin1_german2_ci              德國 DIN-2
    latin1_bin                            符合latin1編碼的二進制
    latin1_general_ci                 多種語言(西歐)
    latin1_general_cs                 多種語言(西歐ISO),大小寫敏感
    latin1_spanish_ci                 現代西班牙

 

        同一個 character set 的不一樣 collation 的區別在於排序、字符串對比的準確度(相同兩個字符在不一樣國家的語言中的排序規則多是不一樣的)以及性能。

       例如:utf8_general_ci 在排序的準確度上要遜於 utf8_unicode_ci, 固然,對於英語用戶應該沒有什麼區別。但性能上(排序以及比對速度)要略優於 utf8_unicode_ci.

 

        MySQL按照下面的方式選擇表字符集和 校對規則:
        若是指定了CHARACTER SET X和COLLATE Y,那麼採用字符集X和校對規則Y。
        若是指定了CHARACTER SET X而沒有指定COLLATE Y,那麼採用CHARACTER SET X和CHARACTER SET X的默認校對規則。

·       不然,採用服務器字符集和服務器校對規則。

        轉換語法
                alter table 表名 convert to character set 字符集名 collate 值;

例:

mysql> show create table tmptable \G;

*************************** 1. row ***************************

       Table: tmptable

Create Table: CREATE TABLE `tmptable` (

  `id` int(10) unsigned NOT NULL DEFAULT '0',

  `Name` char(20) NOT NULL,

  `Age` tinyint(4) NOT NULL

) ENGINE=InnoDB DEFAULT CHARSET=gbk

 

mysql> alter table tmptable convert to character set utf8 collate utf8_bin;

 

mysql> show create table tmptable \G;

*************************** 1. row ***************************

       Table: tmptable

Create Table: CREATE TABLE `tmptable` (

  `id` int(10) unsigned NOT NULL DEFAULT '0',

  `Name` char(20) COLLATE utf8_bin NOT NULL,

  `Age` tinyint(4) NOT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

1 row in set (0.00 sec)

 

若沒有顯式設置,則自動使用數據庫級的配置 

顯式設置在建表時指定:
    create table 表名 (
            字段
    ) engine=引薦 default charset=utf8 collate=utf8_bin;

建議使用_bin,這樣能夠區分大小寫

 

在建表的時候指定了character set,因此它永遠是採用對應的默認的校對規則,建議collation都儘可能採用字符集相應的bin類型的校對規則。

 

四、查看MySQL數據列(column)的字符集

mysql> show create table tmptable\G;

*************************** 1. row ***************************

       Table: tmptable

Create Table: CREATE TABLE `tmptable` (

  `id` int(10) unsigned NOT NULL DEFAULT '0',

  `Name` char(20) COLLATE utf8_bin NOT NULL,

  `Age` tinyint(4) NOT NULL

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin

1 row in set (0.00 sec)

 

若沒有顯式設置,則自動使用表級的配置。

顯式設置在建表時指定:

     CREATE TABLE Table1(column1 VARCHAR(5) CHARACTER SET latin1 COLLATE latin1_german1_ci); 

 

 

mysql> show full columns from tb;

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

| Field | Type             | Collation      | Null | Key | Default | Extra    | Privileges                      | Comment |

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

| id    | int(10) unsigned | NULL           | NO   | PRI | NULL    | auto_increment | select,insert,update,references |

| Name  | char(20)         | gbk_chinese_ci | NO   |     | NUL      | select,insert,update,references |         |

| Age   | tinyint(4)       | NULL           | NO   |     | NULL        | select,insert,update,references |         |

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

3 rows in set (0.00 sec)

 

關於collation的影響:

mysql> select * from tb;

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

| id | Name       | Age |

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

|  1 | changename |  20 |

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

1 row in set (0.00 sec)

 

mysql> select * from tb where binary name='changename';

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

| id | Name       | Age |

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

|  1 | changename |  20 |

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

1 row in set (0.69 sec)

 

mysql> select * from tb where name= binary 'changename';

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

| id | Name       | Age |

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

|  1 | changename |  20 |

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

1 row in set (0.00 sec)

 

查看字符的編碼:

mysql> select hex('測試');

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

| hex('測試') |

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

| B2E2CAD4    |

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

1 row in set (0.06 sec)

 

五、鏈接級別 

     show variables like 'character_set_client';  #客戶端statements 中的編碼

     show variables like 'character_set_connection' ; #數據庫鏈接中的編碼 

     show variables like 'character_set_results'; # 服務端返回結果集和錯誤信息中的編碼

 

 3、設置及修改字符集

 一、建立數據庫指定數據庫的字符集

         mysql> create database mydb character set gbk;

         mysql> use mydb

         mysql> show variables like 'character_set_database';

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

         | Variable_name          | Value  |

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

         | character_set_database | gbk |

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

 

 二、修改數據庫的字符集

(1)、經過SQL修改

         mysql> alter database mydb character set utf8;

         mysql> show variables like 'character_set_database';

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

         | Variable_name          | Value |

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

         | character_set_database | utf8  |

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

 

(2)、經過配置文件修改

         修改文件$MYSQL_HOME\data\mydb\db.opt的內容

         default-character-set=utf8

         default-collation=utf8_general_ci

         爲

         default-character-set=latin1

         default-collation=latin1_swedish_ci

         重啓MYSQL後生效

 

或者修改mysql的my.ini文件中的字符集鍵值

                default-character-set = utf8

                character_set_server = utf8

   修改完後,重啓mysql的服務

 

三、經過Mysql命令修改字符集

         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;

         mysql> set character_set_system=utf8;

         mysql> set collation_connection=utf8;

         mysql> set collation_database=utf8;

         mysql> set collation_server=utf8;

 

 

 

 

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

 

 

常見問題解析

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

     – 插入時根據MySQL服務器的默認設置,character_set_client、character_set_connection和character_set_results均爲latin1;

     – 插入操做的數據將通過latin1=>latin1=>utf8的字符集轉換過程,這一過程當中每一個插入的漢字都會從原始的3個字節變成6個字節保存;

    – 查詢時的結果將通過utf8=>utf8的字符集轉換過程,將保存的6個字節原封不動返回,產生亂碼……

 

 

• 向默認字符集爲latin1的數據表插入utf8編碼的數據前設置了鏈接字符集爲utf8

     – 插入時根據鏈接字符集設置,character_set_client、character_set_connection和character_set_results均爲utf8;

     – 插入數據將通過utf8=>utf8=>latin1的字符集轉換,若原始數據中含有/u0000~/u00ff範圍之外的Unicode字符,會由於沒法在latin1字符集中表示而被轉換爲「?」(0x3F)符號,之後查詢時無論鏈接字符集設置如何都沒法恢復其內容了。

 

 

5、檢測字符集問題的一些手段

• SHOW CHARACTER SET;

• SHOW COLLATION;

• SHOW VARIABLES LIKE 'character%';

• SHOW VARIABLES LIKE 'collation%';

• SQL函數HEX、LENGTH、CHAR_LENGTH

• SQL函數CHARSET、COLLATION

 

使用MySQL字符集時的建議

    • 創建數據庫/表和進行數據庫操做時儘可能顯式指出使用的字符集,而不是依賴於MySQL的默認設置,不然MySQL升級時可能帶來很大困擾;

    • 數據庫和鏈接字符集都使用latin1時雖然大部分狀況下均可以解決亂碼問題,但缺點是沒法以字符爲單位來進行SQL操做,通常狀況下將數據庫和鏈接字符集都置爲utf8是較好的選擇;

    • 使用mysql C API時,初始化數據庫句柄後立刻用mysql_options設定MYSQL_SET_CHARSET_NAME屬性爲utf8,這樣就不用顯式地用SET NAMES語句指定鏈接字符集,且用mysql_ping重連斷開的長鏈接時也會把鏈接字符集重置爲utf8;

    • 對於mysql PHP API,通常頁面級的PHP程序總運行時間較短,在鏈接到數據庫之後顯式用SET NAMES語句設置一次鏈接字符集便可;但當使用長鏈接時,請注意保持鏈接通暢並在斷開重連後用SET NAMES語句顯式重置鏈接字符集。

 

其餘注意事項

    • my.cnf中的default_character_set設置隻影響mysql命令鏈接服務器時的鏈接字符集,不會對使用libmysqlclient庫的應用程序產生任何做用!

    • 對字段進行的SQL函數操做一般都是之內部操做字符集進行的,不受鏈接字符集設置的影響。

    • SQL語句中的裸字符串會受到鏈接字符集或introducer設置的影響,對於比較之類的操做可能產生徹底不一樣的結果,須要當心!

部份內容來源於深刻Myql字符集設置分析,官方文檔:http://dev.mysql.com/doc/refman/5.1/zh/charset.html#charset-collate

相關文章
相關標籤/搜索