1. 程式人生 > >MySQL(六)------ 字符集

MySQL(六)------ 字符集

       計算機只能識別二進位制程式碼,而人只能看懂文字元號,這兩者之間必須要定義一個轉換規則來使人和計算機識別的是同一個東西,這個規則就是人們制定的字符集。

一、字符集概述

       字符集的基礎是ASCII碼,基本上後來所有的字符集都相容ASCII字符集,但是,由於各公司、各政府、各機構等建立的字符集編碼規則各不相同,這就給軟體移植及協同開發帶來困難,因此有必要統一字元編碼。

       Unicode字符集就是後來經過發展得到公認的一個標準,也是現在基本上通行的一個標準,它基本上概括了從古至今人類所使用過的所有文字和符號。

       中國結合國際標準及漢字的特性制定了GBK、GB18030等字符集,下表將一些常用字符集的特點進行了歸納:

二、怎樣選擇合適的字符集

      對資料庫來說,字符集至關重要,存入資料庫的內容都需要通過字符集進行轉換,它對資料庫的儲存效能、處理效能,以及日後系統的移植、推廣都會有影響。

      MySQL支援包括UTF-8、utf8mb4等幾十種字符集,如何進行選擇呢?一般需要根據需求及各字符集本身的特點進行權衡,主要考慮以下幾點:

  • 滿足應用支援語言的需要,一般Unicode型別就行,對MySQL來說基本上就是UTF-8。
  • 如果涉及已有資料的匯入,就需要考慮當前字符集是否對匯入的有相容性,否則可能有些會無法正確匯入。
  • 如果資料庫只需支援一般中文,且資料量很大,效能要求也高,那就應該選雙位元組定長編碼中文字符集,如GBK。相反,如果主要處理英文字元那UTF-8更好。
  • 如果資料庫需要做大量的字元運算,如比較排序等,那麼選擇定長字符集更好,因為它的處理速度快。
  • 如果所有客戶端程式都支援相同的字符集,那麼應優先選擇該字符集作為資料庫字符集,這樣可以避免字符集轉化帶來的開銷和資料損失。

三、MySQL支援的字符集簡介

       MySQL支援很多字符集,在同一臺伺服器、同一個資料庫甚至同一個表的不同欄位都可以指定不同的字符集,這與Oracle等資料庫相比靈活性更高,Oracle的同一個資料庫只能使用同一種字符集。

       使用 show character set 命令檢視所有可用字符集:

mysql> show character set;
+----------+---------------------------------+---------------------+--------+
| Charset  | Description                     | Default collation   | Maxlen |
+----------+---------------------------------+---------------------+--------+
| big5     | Big5 Traditional Chinese        | big5_chinese_ci     |      2 |
| dec8     | DEC West European               | dec8_swedish_ci     |      1 |
| cp850    | DOS West European               | cp850_general_ci    |      1 |
| hp8      | HP West European                | hp8_english_ci      |      1 |
| koi8r    | KOI8-R Relcom Russian           | koi8r_general_ci    |      1 |
| latin1   | cp1252 West European            | latin1_swedish_ci   |      1 |
| latin2   | ISO 8859-2 Central European     | latin2_general_ci   |      1 |
| swe7     | 7bit Swedish                    | swe7_swedish_ci     |      1 |
| ascii    | US ASCII                        | ascii_general_ci    |      1 |
| ujis     | EUC-JP Japanese                 | ujis_japanese_ci    |      3 |
| sjis     | Shift-JIS Japanese              | sjis_japanese_ci    |      2 |
| hebrew   | ISO 8859-8 Hebrew               | hebrew_general_ci   |      1 |
| tis620   | TIS620 Thai                     | tis620_thai_ci      |      1 |
| euckr    | EUC-KR Korean                   | euckr_korean_ci     |      2 |
| koi8u    | KOI8-U Ukrainian                | koi8u_general_ci    |      1 |
| gb2312   | GB2312 Simplified Chinese       | gb2312_chinese_ci   |      2 |
| greek    | ISO 8859-7 Greek                | greek_general_ci    |      1 |
| cp1250   | Windows Central European        | cp1250_general_ci   |      1 |
| gbk      | GBK Simplified Chinese          | gbk_chinese_ci      |      2 |
| latin5   | ISO 8859-9 Turkish              | latin5_turkish_ci   |      1 |
| armscii8 | ARMSCII-8 Armenian              | armscii8_general_ci |      1 |
| utf8     | UTF-8 Unicode                   | utf8_general_ci     |      3 |
| ucs2     | UCS-2 Unicode                   | ucs2_general_ci     |      2 |
| cp866    | DOS Russian                     | cp866_general_ci    |      1 |
| keybcs2  | DOS Kamenicky Czech-Slovak      | keybcs2_general_ci  |      1 |
| macce    | Mac Central European            | macce_general_ci    |      1 |
| macroman | Mac West European               | macroman_general_ci |      1 |
| cp852    | DOS Central European            | cp852_general_ci    |      1 |
| latin7   | ISO 8859-13 Baltic              | latin7_general_ci   |      1 |
| utf8mb4  | UTF-8 Unicode                   | utf8mb4_general_ci  |      4 |
| cp1251   | Windows Cyrillic                | cp1251_general_ci   |      1 |
| utf16    | UTF-16 Unicode                  | utf16_general_ci    |      4 |
| utf16le  | UTF-16LE Unicode                | utf16le_general_ci  |      4 |
| cp1256   | Windows Arabic                  | cp1256_general_ci   |      1 |
| cp1257   | Windows Baltic                  | cp1257_general_ci   |      1 |
| utf32    | UTF-32 Unicode                  | utf32_general_ci    |      4 |
| binary   | Binary pseudo charset           | binary              |      1 |
| geostd8  | GEOSTD8 Georgian                | geostd8_general_ci  |      1 |
| cp932    | SJIS for Windows Japanese       | cp932_japanese_ci   |      2 |
| eucjpms  | UJIS for Windows Japanese       | eucjpms_japanese_ci |      3 |
| gb18030  | China National Standard GB18030 | gb18030_chinese_ci  |      4 |
+----------+---------------------------------+---------------------+--------+
41 rows in set (0.00 sec)

          MySQL的字符集包括字符集校對規則兩個概念。字符集用來定義儲存字串的方式,校對規則用來定義比較字串的方式,一個字符集可以對於多種校對規則。

          使用 show collation like ’ *** ‘ 命令來檢視相應字符集的校對規則:

mysql> show collation like 'gbk%';
+----------------+---------+----+---------+----------+---------+
| Collation      | Charset | Id | Default | Compiled | Sortlen |
+----------------+---------+----+---------+----------+---------+
| gbk_chinese_ci | gbk     | 28 | Yes     | Yes      |       1 |
| gbk_bin        | gbk     | 87 |         | Yes      |       1 |
+----------------+---------+----+---------+----------+---------+
2 rows in set (0.00 sec)

          校對規則的命名約定:以字符集名開始,包含語言名,以_ci(大小寫不敏感)、_cs(大小寫敏感)、_bin(二元,基於字元編碼的值而與語言無關)結束。

下面的例子就介紹了字母根據校對規則是否對大小寫的敏感:

mysql> select case when 'A' collate gbk_chinese_ci = ('a' collate gbk_chinese_ci) then 1 else 0 end;
+---------------------------------------------------------------------------------------+
| case when 'A' collate gbk_chinese_ci = ('a' collate gbk_chinese_ci) then 1 else 0 end |
+---------------------------------------------------------------------------------------+
|                                                                                     1 |
+---------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> select case when 'A' collate gbk_bin = ('a' collate gbk_bin) then 1 else 0 end;
+-------------------------------------------------------------------------+
| case when 'A' collate gbk_bin = ('a' collate gbk_bin) then 1 else 0 end |
+-------------------------------------------------------------------------+
|                                                                       0 |
+-------------------------------------------------------------------------+
1 row in set (0.00 sec)

四、MySQL字符集的設定

      MySQL的字符集和校對規則有4個級別的預設設定:伺服器級、資料庫級、表級和欄位級;它們分別在不同的地方設定,作用也不同。

      4.1 伺服器的字符集和校對規則

        首先通過以下命令來檢視當前伺服器的的字符集和校對規則:

mysql> show variables like 'character_set_server';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| character_set_server | utf8  |
+----------------------+-------+
1 row in set, 1 warning (0.00 sec)

mysql> show variables like 'collation_server';
+------------------+-----------------+
| Variable_name    | Value           |
+------------------+-----------------+
| collation_server | utf8_general_ci |
+------------------+-----------------+
1 row in set, 1 warning (0.00 sec)

一般通用的編碼規則就選utf8,如果有需要要更改,那麼在伺服器端基本有以下三種方式:

  • (Linux環境下)直接修改配置檔案my.cnf;具體步驟如下:1.關閉MySQL;2.在配置檔案裡面的[mysqld]欄位下面[mysqld safe]欄位前面新增引數“ character-set-server=utf8 " ;3.重啟MySQL;4.使用命令’ show variables like " %char%" ‘ 來檢視結果。
  • (windows環境下)修改的是my.ini配置檔案:步驟與上面的基本一樣,只不過需要注意的是MySQL版本如果在5.53之前,新增的引數是‘ default-character-set=utf8 ' ,在此之後就是“ character-set-server=utf8 ";另外,如果這樣設定後發現沒有更改成功,那麼可能與windows系統有關,只需要再在上面的引數下新增 " [client]  default-character-set=utf8 " (注意分兩行寫)應該就可以了。
  • 在啟動選項中指定;例如:mysqld --character-set-server=utf8;
  • 在安裝MySQL時就指定好字符集(推薦)

如果沒有指定都會使用預設值,比如上面都指定了字符集沒有指定校對規則,那麼就會使用預設的,如果不想使用預設的,那麼只需要在指定字符集的同時指定校對規則即可。

     4.2 資料庫的字符集和校對規則

       資料庫的字符集和校對規則在建立資料的時候就需要指定,如果對一個已存在的資料修改其字符集可以使用 " alter database " 命令,但是需要注意,這時候並不會改變該資料庫原有的資料編碼規則,稍後會通過一個例子來解釋;

        資料庫字符集的設定規則如下:

  • 如果有指定,那麼就使用指定的字符集和校對規則;
  • 如果只指定了字符集,那麼校對規則使用預設的;
  • 如果只指定了校對規則,那麼字符集就使用與該校對規則關聯的字符集;
  • 如果沒有指定字符集和校對規則,則使用伺服器的;

使用以下命令顯示當前資料庫的字符集和校對規則:

mysql> show variables like 'character_set_database';
+------------------------+-------+
| Variable_name          | Value |
+------------------------+-------+
| character_set_database | utf8  |
+------------------------+-------+
1 row in set, 1 warning (0.00 sec)

mysql> show variables like 'collation_database';
+--------------------+-----------------+
| Variable_name      | Value           |
+--------------------+-----------------+
| collation_database | utf8_general_ci |
+--------------------+-----------------+
1 row in set, 1 warning (0.00 sec)

      4.3 表字符集和校對規則

        表的字符集和校對規則在建立表的時候就需要指定,如果對一個已存在的表修改其字符集可以使用 " alter table " 命令,但是需要注意,這時候並不會改變該表原有的資料編碼規則;

       設定表的字符集和編碼規則與上面類似,就最後一點有點差別,如果表的沒有指定那麼會使用資料庫的字符集和校對規則。

可使用如下命令查看錶的字符集及校對規則:

mysql> show create table t \G;
*************************** 1. row ***************************
       Table: t
Create Table: CREATE TABLE `t` (
  `f` float(8,1) DEFAULT NULL,
  `d` decimal(8,1) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
1 row in set (0.00 sec)

     4.4 列字符集和校對規則

       這種方式MySQL支援但是使用的較少,對同一個表的不同列使用不同的字符集和校對規則在使用起來較麻煩,除非特別必要一般不用,設定方法也跟上面類似,要麼在建立表的時候指定,要麼在修改表的時候調整。

     4.5 連線字符集和校對規則

       上面的四種方式針對的都是資料儲存的規則,而對於實際情況來說還涉及到客戶端與伺服器的互動操作,如果兩邊的編碼方式不同則會存在一些問題,因此MySQL提供了3個不同的引數:character_set_client、character_set_connection和character_set_results,分別代表客戶端、連線和返回結果的字符集。一般這3個字符集應該是相同的,這樣才可以保證寫入的內容能夠被正確的讀出。

        一般這三個引數不會單獨設定,可使用命令 " set names *** " 來同時修改這3個引數的值,而且它不能寫在配置檔案裡面,需要應用每次連線資料庫後都執行一下這個命令,這顯然很繁瑣,更方便的是在[mysqld] 下面加一行引數:

         init_connect = 'SET NAMES utf8'  ;

這樣每個使用者在連線上來的時候都會觸發該命令從而定義好連線的字符集相同。

set names utf8; 命令等價於下面的3條命令

SET character_set_client = utf8;
SET character_set_results = utf8;
SET character_set_connection = utf8;

       另外,還可以使用命令 [_charset] ’string’ [COLLATE collation] 來指定文字字串的字符集和校對規則,如:

SELECT _utf8 ‘你好’ COLLATE utf8_general_ci;

這種文字字串在請求過程中不經過多餘的轉碼,直接轉換為內部字符集處理。

五、字符集的修改步驟

      前面提到當實際過程中遇到字符集的問題需要更改已有資料庫的字符集時,不能簡單的通過ALTER命令來修改資料庫或表的字符集,而是需要先將原有資料匯出,經過適當調整後重新匯入新的字符集資料庫中。

       下面這個例子是模擬將latin1字符集資料庫修改成GBK的過程:

       1. 匯出表結構

mysqldump -uroot -p --default-character-set=gbk -d databasename> createtab.aql
 
其中 --default-character-set=gbk 表示以什麼字符集連線
     -d 表示只匯出表結構,不匯出資料

      2. 開啟createtab.sql,手動將表結構定義的字符集修改為新的字符集

      3. 確保原資料庫不再更新時匯出所有記錄

mysqldump -uroot -p --quick --no-create-info --extended-insert --default-character-set=latin1 databasename> data.sql

--quick:該選項用於轉儲較大的表,因為它會一次一行的檢索表中的行而不是所有行,並在輸出前將它快取到記憶體中。
--no-create-info:不匯出每個轉儲表的 CREATE TABLE 語句。
--extended-insert:使用包括幾個VALUES列表的多行INSERT語法,這樣轉儲檔案更小,過載檔案時可以加速插入。
--default-character-set=latin1:按照原有字符集匯出資料,這樣能保證正確匯出不會亂碼。

     4. 開啟 data.sql,將SET NAMES latin1 修改為 SET NAMES gbk

     5. 使用新的字符集建立新的資料庫

create database databasename default charset gbk;

     6. 建立表,執行 createtab.sql

mysql -uroot -p databasename < createtab.sql

     7. 匯入資料,執行 data.sql

mysql -uroot -p databasename < data.sql

注意:在更改字符集時,選擇的新字符集一定要能相容原來的字符集,否則會造成亂碼,資料丟失。