MySQL 字符集

一、MySQL 字符集簡介

1.1 字符集簡介

  • MySQL 服務器能夠支持多種字符集,在同一臺服務器、同一個數據庫甚至同一個表的不一樣字段均可以指定使用不一樣的字符集,相比 Oracle 等其餘數據庫管理系統,在同一個數據庫只能使用相同的字符集,MySQL 明顯存在更大的靈活性。mysql

  • MySQL 的字符集包括字符集(character)和校對規則(collation)兩個概念。sql

    • 字符集用來定義存儲字符串的方式。
    • 校對規則用來定義比較字符串的方式。
    • 字符集和校對規則是一對多的關係,MySQL 支持 30 多種字符集的 70 多種校對規則。
  • 校對規則命名約定:它們以其相關的字符集名開始,一般包括一個語言名,而且以 _ci(大小寫不敏感)、_cs(大小寫敏感)或 _bin(二元,即比較是基於字符編碼的值而與 language 無關)結束。shell

1.2 查看字符集經常使用命令

  • 1)查看全部可用的字符集數據庫

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

    # 查看默認安裝的字符集
    > show variables like '%char%'; 
    
        +--------------------------+-----------------------------------------------------------+
        | Variable_name            | Value                                                     |
        +--------------------------+-----------------------------------------------------------+
        | character_set_client     | utf8mb4                                                   |
        | character_set_connection | utf8mb4                                                   |
        | character_set_database   | utf8mb4                                                   |
        | character_set_filesystem | binary                                                    |
        | character_set_results    | utf8mb4                                                   |
        | character_set_server     | utf8mb4                                                   |
        | character_set_system     | utf8                                                      |
        | character_sets_dir       | /usr/local/mysql-8.0.11-macos10.13-x86_64/share/charsets/ |
        +--------------------------+-----------------------------------------------------------+
        8 rows in set (0.01 sec)
  • 3)顯示全部的字符集和該字符集默認的校對規則緩存

    # 顯示全部的字符集和該字符集默認的校對規則
    > desc information_schema.character_sets;
    
        +----------------------+------------------+------+-----+---------+-------+
        | Field                | Type             | Null | Key | Default | Extra |
        +----------------------+------------------+------+-----+---------+-------+
        | CHARACTER_SET_NAME   | varchar(64)      | NO   |     | NULL    |       |
        | DEFAULT_COLLATE_NAME | varchar(64)      | NO   |     | NULL    |       |
        | DESCRIPTION          | varchar(2048)    | NO   |     | NULL    |       |
        | MAXLEN               | int(10) unsigned | NO   |     | NULL    |       |
        +----------------------+------------------+------+-----+---------+-------+
        4 rows in set (0.00 sec)
  • 4)查看相關字符集的校對規則服務器

    # 查看相關字符集的校對規則
    # show collation like 字符集名;
    > show collation like 'gbk%';
    
        +----------------+---------+----+---------+----------+---------+---------------+
        | Collation      | Charset | Id | Default | Compiled | Sortlen | Pad_attribute |
        +----------------+---------+----+---------+----------+---------+---------------+
        | gbk_bin        | gbk     | 87 |         | Yes      |       1 | PAD SPACE     |
        | gbk_chinese_ci | gbk     | 28 | Yes     | Yes      |       1 | PAD SPACE     |
        +----------------+---------+----+---------+----------+---------+---------------+
        2 rows in set (0.00 sec)
    • 上面例子中 GBK 的校對規則,其中 gbk_chinese_ci 是默認的校對規則,對大小寫不敏感;而 gbk_bin 按照編碼的值進行比較,對大小寫敏感。
    # 查看相關字符集的校對規則
    > desc information_schema.collations;
    
        +--------------------+---------------------+------+-----+---------+-------+
        | Field              | Type                | Null | Key | Default | Extra |
        +--------------------+---------------------+------+-----+---------+-------+
        | COLLATION_NAME     | varchar(64)         | NO   |     | NULL    |       |
        | CHARACTER_SET_NAME | varchar(64)         | NO   |     | NULL    |       |
        | ID                 | bigint(20) unsigned | NO   |     | 0       |       |
        | IS_DEFAULT         | varchar(3)          | NO   |     |         |       |
        | IS_COMPILED        | varchar(3)          | NO   |     |         |       |
        | SORTLEN            | int(10) unsigned    | NO   |     | NULL    |       |
        | PAD_ATTRIBUTE      | varchar(9)          | NO   |     | NULL    |       |
        +--------------------+---------------------+------+-----+---------+-------+
        7 rows in set (0.00 sec)

二、MySQL 字符集設置

  • MySQL 的字符集和校對規則有 4 個級別的默認設置:服務器級、數據庫級、表級和字段級,它們分別在不一樣的地方設置,做用也不相同。ui

  • 查看默認安裝的字符集編碼

    # 查看默認安裝的字符集
    > show variables like '%char%'; 
    
        +--------------------------+-----------------------------------------------------------+
        | Variable_name            | Value                                                     |
        +--------------------------+-----------------------------------------------------------+
        | character_set_client     | utf8mb4                                                   |
        | character_set_connection | utf8mb4                                                   |
        | character_set_database   | utf8mb4                                                   |
        | character_set_filesystem | binary                                                    |
        | character_set_results    | utf8mb4                                                   |
        | character_set_server     | utf8mb4                                                   |
        | character_set_system     | utf8                                                      |
        | character_sets_dir       | /usr/local/mysql-8.0.11-macos10.13-x86_64/share/charsets/ |
        +--------------------------+-----------------------------------------------------------+
        8 rows in set (0.01 sec)
    • 若是 character_set_databasecharacter_set_server 依然是 latin1 的字符集,也就是說 mysql 後續建立的表都是 latin1 字符集的,不是 utf8,會形成一些麻煩。因此有必要修改 my.cnf,在修改 my.cnf 以前必定要關閉 mysql 進程,否則會遇到 mysql 的 sock 不能鏈接的問題。

2.1 服務器字符集設置

  • 1)查看服務器字符集code

    • 能夠用如下命令查看當前服務器的字符集和校對規則

      # 查看當前服務器的字符集
      > show variables like 'character_set_server';
      
          +----------------------+---------+
          | Variable_name        | Value   |
          +----------------------+---------+
          | character_set_server | utf8mb4 |
          +----------------------+---------+
          1 row in set (0.00 sec)
      
      # 查看當前服務器的校對規則
      > show variables like 'collation_server';
      
          +------------------+--------------------+
          | Variable_name    | Value              |
          +------------------+--------------------+
          | collation_server | utf8mb4_0900_ai_ci |
          +------------------+--------------------+
          1 row in set (0.00 sec)
  • 2)設置服務器字符集

    • 服務器字符集和校對規則,能夠在 MySQL 服務啓動的時候肯定。

    • 能夠在 my.cnf 中設置

      [mysqld]
      character-set-server=gbk
    • 或者在啓動選項中指定

      mysqld --character-set-server=gbk
    • 或者在編譯時指定

      shell> cmake . -DDEFAULT_CHARSET=gbk
    • 若是沒有特別的指定服務器字符集,那麼默認使用 latin1 做爲服務器字符集。上面 3 種設置的方式都只指定了字符集,沒有指定校對規則,這樣意味着使用該字符集默認的校對規則。若是要使用該字符集的非默認校對規則,則須要在指定字符集的同時指定校對規則。

2.2 數據庫字符集設置

  • 數據庫的字符集和校對規則在建立數據庫的時候指定,也能夠在建立完數據庫後經過 「alter database」 命令進行修改。須要注意的是,若是數據庫裏已經存在數據,由於修改字符集並不能將已有的數據按照新的字符集進行存放,因此不能經過修改數據庫的字符集直接修改數據的內容。

  • 設置數據庫字符集的規則以下

    • 若是指定了字符集和校對規則,則使用指定的字符集和校對規則;
    • 若是指定了字符集沒有指定校對規則,則使用指定字符集的默認校對規則;
    • 若是指定了校對規則但未指定字符集,則字符集使用與該校對規則關聯的字符集;
    • 若是沒有指定字符集和校對規則,則使用服務器字符集和校對規則做爲數據庫的字符集和校對規則。
  • 推薦在建立數據庫時明確指定字符集和校對規則,避免受到默認值的影響。

  • 1)查看當前數據庫的字符集和校對規則

    # 查看當前數據庫的字符集
    > show variables like 'character_set_database';
    
        +------------------------+---------+
        | Variable_name          | Value   |
        +------------------------+---------+
        | character_set_database | utf8mb4 |
        +------------------------+---------+
        1 row in set (0.01 sec)
    
    # 查看當前數據庫的校對規則
    > show variables like 'collation_database';
    
        +--------------------+--------------------+
        | Variable_name      | Value              |
        +--------------------+--------------------+
        | collation_database | utf8mb4_0900_ai_ci |
        +--------------------+--------------------+
        1 row in set (0.01 sec)
  • 2)設置數據庫字符集

    # 建立數據庫時指定數據的字符集
    # create database 數據庫名 character set 字符集;
    > create database test character set gbk;
    
        Query OK, 1 row affected (0.02 sec)
    > use test;
    
        Database changed
    
    > show variables like 'character_set_database';
    
        +------------------------+-------+
        | Variable_name          | Value |
        +------------------------+-------+
        | character_set_database | gbk   |
        +------------------------+-------+
        1 row in set (0.01 sec)
    
    > show variables like 'collation_database';
    
        +--------------------+----------------+
        | Variable_name      | Value          |
        +--------------------+----------------+
        | collation_database | gbk_chinese_ci |
        +--------------------+----------------+
        1 row in set (0.00 sec)
  • 3)修改數據庫字符集

    # 修改數據庫字符集
    # alter database 數據庫名 character set 字符集;
    > alter database test character set utf8;
    
        Query OK, 1 row affected, 1 warning (0.10 sec)
    > show variables like 'character_set_database';
    
        +------------------------+-------+
        | Variable_name          | Value |
        +------------------------+-------+
        | character_set_database | utf8  |
        +------------------------+-------+
        1 row in set (0.01 sec)
    
    > show variables like 'collation_database';
    
        +--------------------+-----------------+
        | Variable_name      | Value           |
        +--------------------+-----------------+
        | collation_database | utf8_general_ci |
        +--------------------+-----------------+
        1 row in set (0.00 sec)

2.3 表字符集設置

  • 表的字符集和校對規則在建立表的時候指定,能夠經過 「alter table」 命令進行修改,一樣,若是表中已有記錄,修改字符集對原有的記錄並無影響,不會按照新的字符集進行存放。表的字段仍然使用原來的字符集。

  • 設置表的字符集的規則和上面基本相似

    • 若是指定了字符集和校對規則,使用指定的字符集和校對規則;
    • 若是指定了字符集沒有指定校對規則,使用指定字符集的默認校對規則;
    • 若是指定了校對規則但未指定字符集,則字符集使用與該校對規則關聯的字符集;
    • 若是沒有指定字符集和校對規則,使用數據庫字符集和校對規則做爲表的字符集和校對規則。
  • 推薦在建立表的時候明確指定字符集和校對規則,以免受到默認值的影響。

  • 1)查看當前表的字符集和校對規則

    # 查看當前表的字符集和校對規則
    # show create table 表名;
    > show create table test;
    
        +-------+--------------------------------------------------------------------------------------------+
        | Table | Create Table                                                                               |
        +-------+--------------------------------------------------------------------------------------------+
        | test  | CREATE TABLE `test` (
                                        `c1` float(10,2) DEFAULT NULL,
                                        `c2` decimal(10,2) DEFAULT NULL
                                      ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci     |
        +-------+--------------------------------------------------------------------------------------------+
        1 row in set (0.00 sec)
  • 2)設置表字符集

    # 建立表時指定數據的字符集
    # create table 表名 (
          列名稱字段 數據類型(長度) 約束條件,
          列名稱字段 數據類型(長度) 約束條件
      ) default charset = 字符集名;
    > create table test (
          no int,
          name varchar(20),
          age int,
          score int
      ) default charset = gbk;
    
        Query OK, 0 rows affected (0.08 sec)
  • 3)修改表字符集

    # 修改表的字符集
    # alter table 表名稱 cahracter set 字符集;
    > alter table test character set utf8;
    
        Query OK, 0 rows affected (0.05 sec)
        Records: 0  Duplicates: 0  Warnings: 0

2.4 列字符集設置

  • MySQL 能夠定義列級別的字符集和校對規則,主要是針對相同的表不一樣字段須要使用不一樣的字符集的狀況,應該說通常遇到這種狀況的概率比較小,這只是 MySQL 提供給咱們一個靈活設置的手段。

  • 列字符集和校對規則的定義能夠在建立表時指定,或者在修改表時調整,若是在建立表的時候沒有特別指定字符集和校對規則,則默認使用表的字符集和校對規則。

2.5 鏈接字符集設置

  • 上面 4 種設置方式,肯定的是數據保存的字符集和校對規則,對於實際的應用訪問來講,還存在客戶端和服務器之間交互的字符集和校對規則的設置。

  • 對於客戶端和服務器的交互操做,MySQL 提供了 3 個不一樣的參數

    • character_set_client:客戶端
    • character_set_connection:鏈接
    • character_set_results:返回結果
  • 一般狀況下,這 3 個字符集應該是相同的,才能夠確保用戶寫入的數據能夠正確地讀出,特別是對於中文字符,不一樣的寫入字符集和返回結果字符集將致使寫入的記錄不能正確讀出。

  • 另外,字符串常量的字符集也是由 character_set_connection 參數來指定的。

  • 1)設置鏈接字符集

    • 一般狀況下,不會單個地設置這 3 個參數,能夠經過如下命令來設置鏈接的字符集和校對規則,這個命令能夠同時修改這 3 個參數的值。使用這個方法修改鏈接的字符集和校對規則,須要應用每次鏈接數據庫後都執行這個命令。

      # set names 字符集;
      > set names gbk;
      
          Query OK, 0 rows affected (0.00 sec)
      
       > show variables like '%char%';
      
          +--------------------------+-----------------------------------------------------------+
          | Variable_name            | Value                                                     |
          +--------------------------+-----------------------------------------------------------+
          | character_set_client     | gbk                                                       |
          | character_set_connection | gbk                                                       |
          | character_set_database   | gbk                                                       |
          | character_set_filesystem | binary                                                    |
          | character_set_results    | gbk                                                       |
          | character_set_server     | utf8mb4                                                   |
          | character_set_system     | utf8                                                      |
          | character_sets_dir       | /usr/local/mysql-8.0.11-macos10.13-x86_64/share/charsets/ |
          +--------------------------+-----------------------------------------------------------+
          8 rows in set (0.01 sec)
    • 另外一個更簡便的辦法,是在 my.cnf 中設置如下語句,這樣服務器啓動後,全部鏈接默認就是使用 GBK 字符集進行鏈接的,而不須要在程序中再執行 「set names」 命令。

      [mysql]
      default-character-set=gbk
  • 2)設置字符串字符集

    • 能夠經過 [_charset_name]'string' [COLLATE collation_name] 命令強制字符串的字符集和校對規則。

      > select _gbk '字符集';
      > select _latin1 '字符集';
    • 一般狀況下,基本不須要用戶強制指定字符串字符集。

2.6 字符集的修改步驟

  • 若是在應用開始階段沒有正確地設置字符集,在運行一段時間之後才發現存在不能知足要求須要調整,又不想丟棄這段時間的數據,那麼就須要進行字符集的修改。字符集的修改不能直接經過 alter database character set *** 或者 alter table tablename character set *** 命令進行,這兩個命令都沒有更新已有記錄的字符集,而只是對新建立的表或者記錄生效。已有記錄的字符集調整,須要先將數據導出,通過適當的調整從新導入後纔可完成。

  • 如下模擬的是將 latin1 字符集的數據庫修改爲 gbk 字符集的數據庫的過程。

  • 1)導出表結構

    # mysqldump -uroot -p --default-character-set=目標字符集 -d 源數據庫名> 目標文件路徑.sql
    $ mysqldump -uroot -p --default-character-set=gbk -d test> /Users/haiqianj/Desktop/testdbcreatetab.sql
    • 其中 --default-character-set=gbk 表示設置以什麼字符集鏈接,-d 表示只導出表結構,不導出數據。
  • 2)打開 testdbcreatetab.sql,將表結構定義中的字符集修改成新的字符集

    --
    -- Table structure for table `A`
    --
    
    DROP TABLE IF EXISTS `A`;
    /*!40101 SET @saved_cs_client     = @@character_set_client */;
     SET character_set_client = gbk ;
    CREATE TABLE `A` (
      `ano` int(11) NOT NULL,
      `aname` varchar(20) CHARACTER SET gbk COLLATE gbk_chinese_ci DEFAULT NULL,
      `loc` varchar(100) CHARACTER SET gbk COLLATE gbk_chinese_ci DEFAULT NULL,
      PRIMARY KEY (`ano`)
    ) ENGINE=InnoDB DEFAULT CHARSET=gbk;
    /*!40101 SET character_set_client = @saved_cs_client */;
  • 3)確保記錄再也不更新,導出全部記錄

    # mysqldump -uroot -p --quick --no-create-info --extended-insert --default-character-set=源字符集 源數據庫名> 目標文路徑.sql
    $ mysqldump -uroot -p --quick --no-create-info --extended-insert --default-character-set=latin1 test> /Users/haiqianj/Desktop/testdbdata.sql
    • --quick:該選項用於轉儲大的表。它強制 mysqldump 從服務器一次一行地檢索表中的行而不是檢索全部行,並在輸出前將它緩存到內存中。
    • --extended-insert:使用包括幾個 values 列表的多行 insert 語法。這樣使轉儲文件更小,重載文件時能夠加速插入。
    • --no-create-info:不導出每一個轉儲表的 create table 語句。
    • --default-character-set=latin1:按照原有的字符集導出全部數據,這樣導出的文件中,全部中文都是可見的,不會保存成亂碼。
  • 4)打開 testdbdata.sql,將 set names latin1 修改爲 set names gbk

    set names 目標字符集;
    set names gbk;
  • 5)使用新的字符集建立新的數據庫

    # create database 新數據庫名 default charset 目標字符集;
    > create database newtest default charset gbk;
  • 6)建立表,執行 testdbcreatetab.sql

    # mysql -uroot -p 新數據庫名 < 目標文路徑.sql
    $ mysql -uroot -p newtest < /Users/haiqianj/Desktop/testdbcreatetab.sql
  • 7)導入數據,執行 testdbdata.sql

    # mysql -uroot -p 新數據庫名 < 目標文路徑.sql
    $ mysql -uroot -p newtest < /Users/haiqianj/Desktop/testdbdata.sql
  • 8)查看修改後的數據庫

    > show create database newtest;
    
        +----------+-----------------------------------------------------------------+
        | Database | Create Database                                                 |
        +----------+-----------------------------------------------------------------+
        | newtest  | CREATE DATABASE `newtest` /*!40100 DEFAULT CHARACTER SET gbk */ |
        +----------+-----------------------------------------------------------------+
        1 row in set (0.00 sec)
    
    > show create table A;
    
        +-------+-------------------------------------------------------------------------------------------------------+
        | Table | Create Table                                                                                          |
        +-------+-------------------------------------------------------------------------------------------------------+
        | A     | CREATE TABLE `A` (
                                     `ano` int(11) NOT NULL,
                                     `aname` varchar(20) CHARACTER SET gbk COLLATE gbk_chinese_ci DEFAULT NULL,
                                     `loc` varchar(100) CHARACTER SET gbk COLLATE gbk_chinese_ci DEFAULT NULL,
                                     PRIMARY KEY (`ano`)
                                   ) ENGINE=InnoDB DEFAULT CHARSET=gbk                                                  |
        +-------+-------------------------------------------------------------------------------------------------------+
        1 row in set (0.00 sec)
  • 注意:選擇目標字符集的時候,要注意最好是源字符集的超集,或者肯定比源字符集的字庫更大,不然若是目標字符集的字庫小於源字符集的字庫,那麼目標字符集中不支持的字符導入後會變成亂碼,丟失一部分數據。例如,GBK 字符集的字庫大於 GB 2312 字符集,那麼 GBK 字符集的數據,若是導入 GB 2312 數據庫中,就會丟失 GB 2312 中不支持的那部分漢字的數據。

相關文章
相關標籤/搜索