文件首頁
MySQL 9.0 參考手冊
相關文件 下載本手冊
PDF (美式信紙) - 40.0Mb
PDF (A4) - 40.1Mb
Man Pages (TGZ) - 258.2Kb
Man Pages (Zip) - 365.3Kb
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 的參照。在資訊綱要表格的欄位中以及 SQL SHOW 陳述式的輸出中,也會顯示 utf8mb3 而不是 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 校對會在校對名稱中包含版本。範例

LOWER()UPPER() 函數會根據其引數的排序規則執行大小寫轉換。只有當引數排序規則使用夠高的 UCA 版本時,才會轉換僅在 Unicode 4.0.0 以上版本中具有大寫和小寫版本的字元。

排序規則的填充屬性

基於 UCA 9.0.0 及更高版本的排序規則比基於 UCA 9.0.0 之前版本的排序規則更快。它們的填充屬性也為 NO PAD,與基於 UCA 9.0.0 之前版本的排序規則中使用的 PAD SPACE 相反。對於非二進位字串的比較,NO PAD 排序規則會像對待任何其他字元一樣對待字串結尾的空格(請參閱比較中尾隨空格的處理)。

若要判斷排序規則的填充屬性,請使用 INFORMATION_SCHEMA COLLATIONS 資料表,其中具有 PAD_ATTRIBUTE 欄位。例如:

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        |
+----------------------------+---------------+

具有 NO PAD 排序規則的非二進位字串值(CHARVARCHARTEXT)的比較在尾隨空格方面與其他排序規則不同。例如,'a''a ' 會被比較為不同的字串,而不是相同的字串。這可以使用 utf8mb4 的二進位排序規則來觀察。utf8mb4_bin 的填充屬性是 PAD SPACE,而 utf8mb4_0900_bin 的填充屬性是 NO PAD。因此,涉及 utf8mb4_0900_bin 的運算不會新增尾隨空格,而涉及具有尾隨空格的字串的比較,對於這兩種排序規則可能會有所不同。

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)

語言特定的排序規則

如果僅基於 Unicode 校對演算法 (UCA) 的排序對某種語言效果不佳,則 MySQL 會實作語言特定的 Unicode 排序規則。語言特定的排序規則是基於 UCA 的,並具有額外的語言自訂規則。此章節稍後將會出現此類規則的範例。若要了解特定語言的排序問題,http://unicode.orghttp://www.unicode.org/cldr/charts/30/collation/index.html 中提供了通用地區設定資料儲存庫 (CLDR) 排序圖表。

例如,非語言特定的 utf8mb4_0900_ai_ci 和語言特定的 utf8mb4_LOCALE_0900_ai_ci Unicode 排序規則都具有下列特性:

  • 此排序規則基於 UCA 9.0.0 和 CLDR v30,不區分重音符號和大小寫。這些特性在排序規則名稱中以 _0900_ai_ci 表示。例外情況:utf8mb4_la_0900_ai_ci 不是基於 CLDR,因為 CLDR 中未定義古典拉丁文。

  • 此排序規則適用於 [U+0, U+10FFFF] 範圍中的所有字元。

  • 如果排序規則不是語言特定的,它會以預設順序排序所有字元,包括補充字元(如下所述)。如果排序規則是語言特定的,它會根據語言特定的規則正確排序該語言的字元,並以預設順序排序非該語言的字元。

  • 預設情況下,排序規則會根據 DUCET 表(預設 Unicode 校對元素表)中列出的程式碼點,依據表中指定的權重值來排序具有該程式碼點的字元。排序規則會使用其隱含權重值(根據 UCA 建構)排序沒有 DUCET 表中列出的程式碼點的字元。

  • 對於非語言特定的排序規則,縮合序列中的字元會被視為個別字元。對於語言特定的排序規則,縮合可能會變更字元排序順序。

包含下表中所示的地區碼或語言名稱的排序規則名稱是語言特定的排序規則。Unicode 字元集可能包含一或多種這些語言的排序規則。

表 12.3 Unicode 排序規則語言指定符

語言 語言指定符
波士尼亞文 bs
保加利亞文 bg
中文 zh
古典拉丁文 laroman
克羅埃西亞文 hrcroatian
捷克文 csczech
丹麥文 dadanish
世界語 eoesperanto
愛沙尼亞文 etestonian
加利西亞文 gl
德文電話簿排序 de_pbgerman2
匈牙利文 huhungarian
冰島文 isicelandic
日文 ja
拉脫維亞文 lvlatvian
立陶宛文 ltlithuanian
蒙古文 mn
挪威文 / 巴克摩文 nb
挪威文 / 新挪威文 nn
波斯文 persian
波蘭文 plpolish
羅馬尼亞文 roromanian
俄文 ru
塞爾維亞文 sr
僧伽羅文 sinhala
斯洛伐克文 skslovak
斯洛維尼亞文 slslovenian
現代西班牙文 esspanish
傳統西班牙文 es_tradspanish2
瑞典文 svswedish
土耳其文 trturkish
越南文 vivietnamese

MySQL 提供保加利亞文排序規則 utf8mb4_bg_0900_ai_ciutf8mb4_bg_0900_as_cs

克羅埃西亞文排序規則針對這些克羅埃西亞文字母進行了調整:ČĆĐLjNjŠŽ

MySQL 為塞爾維亞文提供 utf8mb4_sr_latn_0900_ai_ciutf8mb4_sr_latn_0900_as_cs 排序規則,並為波士尼亞文提供 utf8mb4_bs_0900_ai_ciutf8mb4_bs_0900_as_cs 排序規則,這些語言在使用拉丁字母書寫時皆適用。

MySQL 為挪威文的兩種主要變體都提供排序規則:對於巴克摩文,您可以使用 utf8mb4_nb_0900_ai_ciutf8mb4_nb_0900_as_cs;對於新挪威文,MySQL 現在提供 utf8mb4_nn_0900_ai_ciutf8mb4_nn_0900_as_cs

對於日文,utf8mb4 字元集包含 utf8mb4_ja_0900_as_csutf8mb4_ja_0900_as_cs_ks 排序規則。這兩種排序規則都區分重音符號和大小寫。utf8mb4_ja_0900_as_cs_ks 也區分假名字母,並將片假名字元與平假名字元區分開來,而 utf8mb4_ja_0900_as_cs 則將片假名和平假名字元視為排序時相同。需要日文排序規則但不區分假名字母的應用程式,可以使用 utf8mb4_ja_0900_as_cs 來獲得更好的排序效能。utf8mb4_ja_0900_as_cs 使用三個權重層級進行排序;utf8mb4_ja_0900_as_cs_ks 使用四個。

對於不區分重音符號的古典拉丁文排序規則,IJ 會被比較為相等,而 UV 也會被比較為相等。IJ 以及 UV 在基本字母層級上比較會相等。換句話說,J 被視為帶有重音符號的 I,而 U 被視為帶有重音符號的 V

MySQL 在使用西里爾文字書寫時,為蒙古文提供排序規則:utf8mb4_mn_cyrl_0900_ai_ciutf8mb4_mn_cyrl_0900_as_cs

西班牙文排序規則適用於現代和傳統西班牙文。對於兩者,ñ(帶波浪號的 n)都是介於 no 之間的單獨字母。此外,對於傳統西班牙文,ch 是介於 cd 之間的單獨字母,而 ll 是介於 lm 之間的單獨字母。

傳統西班牙文排序規則也可用於阿斯圖里亞斯文和加利西亞文。MySQL 也為加利西亞文提供 utf8mb4_gl_0900_ai_ciutf8mb4_gl_0900_as_cs 排序規則。(它們分別與 utf8mb4_es_0900_ai_ciutf8mb4_es_0900_as_cs 的排序規則相同。)

瑞典文排序規則包含瑞典規則。例如,在瑞典語中,存在以下關係,這並非德國或法國語系使用者所預期的:

Ü = Y < Ö

_general_ci 與 _unicode_ci 排序規則

對於任何 Unicode 字元集,使用 xxx_general_ci 排序規則執行的運算都比使用 xxx_unicode_ci 排序規則執行的運算快。例如,utf8mb4_general_ci 排序規則的比較速度更快,但比 utf8mb4_unicode_ci 的比較稍微不正確。原因是 utf8mb4_unicode_ci 支援擴展之類的對應;也就是說,當一個字元與其他字元的組合比較時相等。例如,ß 在德文和一些其他語言中等於 ssutf8mb4_unicode_ci 也支援縮合和可忽略的字元。utf8mb4_general_ci 是不支援擴展、縮合或可忽略字元的舊式排序規則。它只能在字元之間進行一對一比較。

為了進一步說明,以下等式在 utf8mb4_general_ciutf8mb4_unicode_ci 中都成立(關於這在比較或搜尋中的影響,請參閱第 12.8.6 節,「校對效果範例」)。

Ä = A
Ö = O
Ü = U

兩種校對之間的差異在於,以下情況對於 utf8mb4_general_ci 為真:

ß = s

而以下情況對於 utf8mb4_unicode_ci 為真,其支援德語 DIN-1 排序(也稱為字典排序):

ß = ss

如果使用 utf8mb4_unicode_ci 的排序對於某種語言效果不佳,MySQL 會實作語言特定的 Unicode 校對。例如,utf8mb4_unicode_ci 對於德語字典排序和法語效果良好,因此無需建立特殊的 utf8mb4 校對。

utf8mb4_general_ci 對於德語和法語也令人滿意,只是 ß 等於 s,而不是 ss。如果您的應用程式可以接受這種情況,則應使用 utf8mb4_general_ci,因為它速度更快。如果無法接受這種情況(例如,如果您需要德語字典排序),請使用 utf8mb4_unicode_ci,因為它更準確。

如果您需要德語 DIN-2(電話簿)排序,請使用 utf8mb4_german2_ci 校對,它會比較以下幾組字元是否相等:

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

utf8mb4_german2_ci 類似於 latin1_german2_ci,但後者不會比較 Æ 是否等於 AEŒ 是否等於 OE。沒有對應於德語字典排序的 latin1_german_ciutf8mb4_german_ci,因為 utf8mb4_general_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 替換字元的權重。對於 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_binutf16 的二進位校對)是二進位比較,是「逐位元組」而不是「逐字元」。如果真是如此,則 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 之前建立的表格(Bug #27877)。