文件首頁
MySQL 8.4 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 39.9Mb
PDF (A4) - 40.0Mb
Man Pages (TGZ) - 258.5Kb
Man Pages (Zip) - 365.5Kb
Info (Gzip) - 4.0Mb
Info (Zip) - 4.0Mb


12.10.1 Unicode 字元集

本節說明 Unicode 字元集可用的校對及其區分屬性。如需有關 Unicode 的一般資訊,請參閱第 12.9 節,「Unicode 支援」

MySQL 支援多個 Unicode 字元集

  • utf8mb4:使用每個字元一到四個位元組的 Unicode 字元集 UTF-8 編碼。

  • utf8mb3:使用每個字元一到三個位元組的 Unicode 字元集 UTF-8 編碼。此字元集已棄用;請改用 utf8mb4

  • utf8utf8mb3 的已棄用別名。請改用 utf8mb4

    注意

    在未來版本中,utf8 預計將成為 utf8mb4 的別名。

  • ucs2:使用每個字元兩個位元組的 Unicode 字元集 UCS-2 編碼。已棄用;預計在未來版本的 MySQL 中將移除對此字元集的支援。

  • utf16:使用每個字元兩個或四個位元組的 Unicode 字元集 UTF-16 編碼。與 ucs2 類似,但具有增補字元的擴充。

  • utf16le:Unicode 字元集的 UTF-16LE 編碼。與 utf16 類似,但採用小端而非大端。

  • utf32:使用每個字元四個位元組的 Unicode 字元集 UTF-32 編碼。

注意

utf8mb3 字元集已棄用,您應預期它會在未來的 MySQL 版本中移除。請改用 utf8mb4utf8 目前是 utf8mb3 的別名,但現在已棄用,而 utf8 預計隨後會成為 utf8mb4 的參考。utf8mb3 也會顯示在資訊架構資料表的資料行中,以及 SQL SHOW 陳述式的輸出中,以取代 utf8

為避免 utf8 意義上的歧義,請考慮明確指定 utf8mb4 作為字元集參考。

utf8mb4utf16utf16leutf32 支援基本多文種平面 (BMP) 字元和 BMP 之外的增補字元。utf8mb3ucs2 僅支援 BMP 字元。

大多數 Unicode 字元集都具有一般校對 (名稱中以 _general 表示或沒有語言指定詞)、二進位校對 (名稱中以 _bin 表示) 以及數個語言特定的校對 (以語言指定詞表示)。例如,對於 utf8mb4utf8mb4_general_ciutf8mb4_bin 是其一般和二進位校對,而 utf8mb4_danish_ci 是其語言特定的校對之一。

大多數字元集都有單一的二進位校對。utf8mb4 例外,它有兩個:utf8mb4_binutf8mb4_0900_bin。這兩個二進位校對具有相同的排序順序,但其區別在於其填補屬性和校對權重特性。請參閱校對填補屬性字元校對權重

utf16le 的校對支援有限。唯一可用的校對是 utf16le_general_ciutf16le_bin。這些與 utf16_general_ciutf16_bin 類似。

Unicode 校對演算法 (UCA) 版本

MySQL 根據 http://www.unicode.org/reports/tr10/ 中描述的 Unicode 校對演算法 (UCA) 實作 xxx_unicode_ci 校對。校對使用 4.0.0 版 UCA 權重索引鍵:http://www.unicode.org/Public/UCA/4.0.0/allkeys-4.0.0.txtxxx_unicode_ci 校對僅部分支援 Unicode 校對演算法。不支援某些字元,而且不完全支援組合標記。這會影響越南語、約魯巴語和納瓦荷語等語言。在字串比較中,組合字元會被視為與使用單一 Unicode 字元寫入的相同字元不同,並且兩個字元會被視為具有不同的長度 (例如,由 CHAR_LENGTH() 函式傳回或在結果集元資料中)。

基於高於 4.0.0 的 UCA 版本的 Unicode 校對會在校對名稱中包含版本。範例:

mysql> SELECT COLLATION_NAME, PAD_ATTRIBUTE
       FROM INFORMATION_SCHEMA.COLLATIONS
       WHERE CHARACTER_SET_NAME = 'utf8mb4';
+----------------------------+---------------+
| COLLATION_NAME             | PAD_ATTRIBUTE |
+----------------------------+---------------+
| utf8mb4_general_ci         | PAD SPACE     |
| utf8mb4_bin                | PAD SPACE     |
| utf8mb4_unicode_ci         | PAD SPACE     |
| utf8mb4_icelandic_ci       | PAD SPACE     |
...
| utf8mb4_0900_ai_ci         | NO PAD        |
| utf8mb4_de_pb_0900_ai_ci   | NO PAD        |
| utf8mb4_is_0900_ai_ci      | NO PAD        |
...
| utf8mb4_ja_0900_as_cs      | NO PAD        |
| utf8mb4_ja_0900_as_cs_ks   | NO PAD        |
| utf8mb4_0900_as_ci         | NO PAD        |
| utf8mb4_ru_0900_ai_ci      | NO PAD        |
| utf8mb4_ru_0900_as_cs      | NO PAD        |
| utf8mb4_zh_0900_as_cs      | NO PAD        |
| utf8mb4_0900_bin           | NO PAD        |
+----------------------------+---------------+

mysql> CREATE TABLE t1 (c CHAR(10) COLLATE utf8mb4_bin);
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO t1 VALUES('a');
Query OK, 1 row affected (0.01 sec)

mysql> SELECT * FROM t1 WHERE c = 'a ';
+------+
| c    |
+------+
| a    |
+------+
1 row in set (0.00 sec)

mysql> ALTER TABLE t1 MODIFY c CHAR(10) COLLATE utf8mb4_0900_bin;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM t1 WHERE c = 'a ';
Empty set (0.00 sec)


Ü = Y < Ö

Ä = A
Ö = O
Ü = U

ß = s

ß = ss

Ä = Æ = AE
Ö = Œ = OE
Ü = UE
ß = ss

utf8mb4_german2_ci 類似於 latin1_german2_ci,但後者不會將 Æ 視為等於 AE 或將 Œ 視為等於 OE。由於 utf8mb4_general_ci 已足夠,因此沒有對應於德文字典順序的 latin1_german_ciutf8mb4_german_ci

字元校對權重

字元的校對權重決定如下:

  • 對於除 _bin (二進制) 校對之外的所有 Unicode 校對,MySQL 會執行資料表查找以找到字元的校對權重。

  • 對於除 utf8mb4_0900_bin 之外的 _bin 校對,權重基於程式碼點,可能會加上前導零位元組。

  • 對於 utf8mb4_0900_bin,權重是 utf8mb4 編碼位元組。排序順序與 utf8mb4_bin 相同,但速度更快。

可以使用 WEIGHT_STRING() 函數顯示校對權重。(請參閱 第 14.8 節,「字串函數和運算符」)。如果校對使用權重查找表,但字元不在該表中 (例如,因為它是「新」字元),則校對權重的決定會變得更複雜。

  • 對於一般校對 (xxx_general_ci) 中的 BMP 字元,權重是程式碼點。

  • 對於 UCA 校對 (例如,xxx_unicode_ci 和特定語言校對) 中的 BMP 字元,適用以下演算法:

    if (code >= 0x3400 && code <= 0x4DB5)
      base= 0xFB80; /* CJK Ideograph Extension */
    else if (code >= 0x4E00 && code <= 0x9FA5)
      base= 0xFB40; /* CJK Ideograph */
    else
      base= 0xFBC0; /* All other characters */
    aaaa= base +  (code >> 15);
    bbbb= (code & 0x7FFF) | 0x8000;

    結果是由兩個校對元素組成的序列,aaaa 後面跟著 bbbb。例如:

    mysql> SELECT HEX(WEIGHT_STRING(_ucs2 0x04CF COLLATE ucs2_unicode_ci));
    +----------------------------------------------------------+
    | HEX(WEIGHT_STRING(_ucs2 0x04CF COLLATE ucs2_unicode_ci)) |
    +----------------------------------------------------------+
    | FBC084CF                                                 |
    +----------------------------------------------------------+

    因此,U+04cf 西里爾小型字母 PALOCHKA (ӏ) 在所有 UCA 4.0.0 校對中,都大於 U+04c0 西里爾字母 PALOCHKA (Ӏ)。使用 UCA 5.2.0 校對時,所有 palochkas 會一起排序。

  • 對於一般校對中的補充字元,權重是 0xfffd REPLACEMENT CHARACTER 的權重。對於 UCA 4.0.0 校對中的補充字元,其校對權重為 0xfffd。也就是說,對於 MySQL,所有補充字元彼此相等,並且大於幾乎所有 BMP 字元。

    以下是 Deseret 字元和 COUNT(DISTINCT) 的範例:

    CREATE TABLE t (s1 VARCHAR(5) CHARACTER SET utf32 COLLATE utf32_unicode_ci);
    INSERT INTO t VALUES (0xfffd);   /* REPLACEMENT CHARACTER */
    INSERT INTO t VALUES (0x010412); /* DESERET CAPITAL LETTER BEE */
    INSERT INTO t VALUES (0x010413); /* DESERET CAPITAL LETTER TEE */
    SELECT COUNT(DISTINCT s1) FROM t;

    結果為 2,因為在 MySQL xxx_unicode_ci 校對中,替換字元的權重為 0x0dc6,而 Deseret Bee 和 Deseret Tee 的權重皆為 0xfffd。(如果改為使用 utf32_general_ci 校對,則結果為 1,因為所有三個字元在該校對中的權重皆為 0xfffd。)

    以下是楔形文字和 WEIGHT_STRING() 的範例:

    /*
    The four characters in the INSERT string are
    00000041  # LATIN CAPITAL LETTER A
    0001218F  # CUNEIFORM SIGN KAB
    000121A7  # CUNEIFORM SIGN KISH
    00000042  # LATIN CAPITAL LETTER B
    */
    CREATE TABLE t (s1 CHAR(4) CHARACTER SET utf32 COLLATE utf32_unicode_ci);
    INSERT INTO t VALUES (0x000000410001218f000121a700000042);
    SELECT HEX(WEIGHT_STRING(s1)) FROM t;

    結果為:

    0E33 FFFD FFFD 0E4A

    0E330E4AUCA 4.0.0 中的主要權重。FFFD 是 KAB 和 KISH 的權重。

    所有補充字元彼此相等的規則並非最佳,但預計不會造成問題。這些字元非常罕見,因此由補充字元組成的多字元字串非常罕見。在日本,由於補充字元是晦澀的漢字象形文字,因此一般使用者不在意它們的順序為何。如果您真的希望根據 MySQL 規則排序的列,其次根據程式碼點值排序,這很容易:

    ORDER BY s1 COLLATE utf32_unicode_ci, s1 COLLATE utf32_bin
  • 對於基於高於 4.0.0 的 UCA 版本 (例如,xxx_unicode_520_ci) 的補充字元,補充字元不一定都具有相同的校對權重。有些具有來自 UCA allkeys.txt 檔案的明確權重。其他則具有根據此演算法計算的權重:

    aaaa= base +  (code >> 15);
    bbbb= (code & 0x7FFF) | 0x8000;

「依字元的程式碼值排序」和「依字元的二進制表示法排序」之間存在差異,此差異僅在 utf16_bin 中出現,因為使用了代理項。

假設 utf16_bin (用於 utf16 的二進制校對) 是「逐位元組」而不是「逐字元」的二進制比較。如果這樣的話,utf16_bin 中字元的順序會與 utf8mb4_bin 中的順序不同。例如,以下圖表顯示了兩個罕見的字元。第一個字元在 E000-FFFF 範圍內,因此它大於代理項,但小於補充字元。第二個字元是補充字元。

Code point  Character                    utf8mb4      utf16
----------  ---------                    -------      -----
0FF9D       HALFWIDTH KATAKANA LETTER N  EF BE 9D     FF 9D
10384       UGARITIC LETTER DELTA        F0 90 8E 84  D8 00 DF 84

圖表中的兩個字元依程式碼點值排序,因為 0xff9d < 0x10384。它們依 utf8mb4 值排序,因為 0xef < 0xf0。但如果我們使用逐位元組比較,它們不是依 utf16 值排序,因為 0xff > 0xd8

因此,MySQL 的 utf16_bin 校對不是「逐位元組」。它是「依程式碼點」。當 MySQL 在 utf16 中看到補充字元編碼時,它會轉換為字元的程式碼點值,然後進行比較。因此,utf8mb4_binutf16_bin 具有相同的排序。這與 SQL:2008 標準對 UCS_BASIC 校對的要求一致:「UCS_BASIC 是一種校對,其中排序完全由要排序字串中字元的 Unicode 純量值決定。它適用於 UCS 字元集。由於每個字元集都是 UCS 字元集的子集,因此 UCS_BASIC 校對可能適用於每個字元集。附註 11:字元的 Unicode 純量值是其程式碼點,視為不帶正負號的整數。」

如果字元集是 ucs2,則比較是逐位元組的,但 ucs2 字串無論如何都不應包含代理項。

雜項資訊

xxx_general_mysql500_ci 校對保留了原始 xxx_general_ci 校對在 5.1.24 之前的排序,並允許升級在 MySQL 5.1.24 之前建立的資料表 (錯誤 #27877)。