本節說明 Unicode 字元集可用的校對及其區分屬性。如需有關 Unicode 的一般資訊,請參閱第 12.9 節,「Unicode 支援」。
MySQL 支援多個 Unicode 字元集
utf8mb4:使用每個字元一到四個位元組的 Unicode 字元集 UTF-8 編碼。utf8mb3:使用每個字元一到三個位元組的 Unicode 字元集 UTF-8 編碼。此字元集已棄用;請改用utf8mb4。utf8:utf8mb3的已棄用別名。請改用utf8mb4。注意在未來版本中,
utf8預計將成為utf8mb4的別名。ucs2:使用每個字元兩個位元組的 Unicode 字元集 UCS-2 編碼。已棄用;預計在未來版本的 MySQL 中將移除對此字元集的支援。utf16:使用每個字元兩個或四個位元組的 Unicode 字元集 UTF-16 編碼。與ucs2類似,但具有增補字元的擴充。utf16le:Unicode 字元集的 UTF-16LE 編碼。與utf16類似,但採用小端而非大端。utf32:使用每個字元四個位元組的 Unicode 字元集 UTF-32 編碼。
utf8mb3 字元集已棄用,您應預期它會在未來的 MySQL 版本中移除。請改用 utf8mb4。utf8 目前是 utf8mb3 的別名,但現在已棄用,而 utf8 預計隨後會成為 utf8mb4 的參考。utf8mb3 也會顯示在資訊架構資料表的資料行中,以及 SQL SHOW 陳述式的輸出中,以取代 utf8。
為避免 utf8 意義上的歧義,請考慮明確指定 utf8mb4 作為字元集參考。
utf8mb4、utf16、utf16le 和 utf32 支援基本多文種平面 (BMP) 字元和 BMP 之外的增補字元。utf8mb3 和 ucs2 僅支援 BMP 字元。
大多數 Unicode 字元集都具有一般校對 (名稱中以 _general 表示或沒有語言指定詞)、二進位校對 (名稱中以 _bin 表示) 以及數個語言特定的校對 (以語言指定詞表示)。例如,對於 utf8mb4,utf8mb4_general_ci 和 utf8mb4_bin 是其一般和二進位校對,而 utf8mb4_danish_ci 是其語言特定的校對之一。
大多數字元集都有單一的二進位校對。utf8mb4 例外,它有兩個:utf8mb4_bin 和 utf8mb4_0900_bin。這兩個二進位校對具有相同的排序順序,但其區別在於其填補屬性和校對權重特性。請參閱校對填補屬性和字元校對權重。
對 utf16le 的校對支援有限。唯一可用的校對是 utf16le_general_ci 和 utf16le_bin。這些與 utf16_general_ci 和 utf16_bin 類似。
MySQL 根據 http://www.unicode.org/reports/tr10/ 中描述的 Unicode 校對演算法 (UCA) 實作 校對。校對使用 4.0.0 版 UCA 權重索引鍵:http://www.unicode.org/Public/UCA/4.0.0/allkeys-4.0.0.txt。xxx_unicode_ci 校對僅部分支援 Unicode 校對演算法。不支援某些字元,而且不完全支援組合標記。這會影響越南語、約魯巴語和納瓦荷語等語言。在字串比較中,組合字元會被視為與使用單一 Unicode 字元寫入的相同字元不同,並且兩個字元會被視為具有不同的長度 (例如,由 xxx_unicode_ciCHAR_LENGTH() 函式傳回或在結果集元資料中)。
基於高於 4.0.0 的 UCA 版本的 Unicode 校對會在校對名稱中包含版本。範例:
utf8mb4_unicode_520_ci是基於 UCA 5.2.0 權重索引鍵 (http://www.unicode.org/Public/UCA/5.2.0/allkeys.txt),utf8mb4_0900_ai_ci是基於 UCA 9.0.0 權重索引鍵 (http://www.unicode.org/Public/UCA/9.0.0/allkeys.txt)。
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)
Ä = A
Ö = O
Ü = Uß = sß = ss
Ä = Æ = AE
Ö = Œ = OE
Ü = UE
ß = ss
utf8mb4_german2_ci 類似於 latin1_german2_ci,但後者不會將 Æ 視為等於 AE 或將 Œ 視為等於 OE。由於 utf8mb4_general_ci 已足夠,因此沒有對應於德文字典順序的 latin1_german_ci 的 utf8mb4_german_ci。
字元的校對權重決定如下:
對於除
_bin(二進制) 校對之外的所有 Unicode 校對,MySQL 會執行資料表查找以找到字元的校對權重。對於除
utf8mb4_0900_bin之外的_bin校對,權重基於程式碼點,可能會加上前導零位元組。對於
utf8mb4_0900_bin,權重是utf8mb4編碼位元組。排序順序與utf8mb4_bin相同,但速度更快。
可以使用 WEIGHT_STRING() 函數顯示校對權重。(請參閱 第 14.8 節,「字串函數和運算符」)。如果校對使用權重查找表,但字元不在該表中 (例如,因為它是「新」字元),則校對權重的決定會變得更複雜。
對於一般校對 (
) 中的 BMP 字元,權重是程式碼點。xxx_general_ci對於 UCA 校對 (例如,
和特定語言校對) 中的 BMP 字元,適用以下演算法:xxx_unicode_ciif (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_ci0x0dc6,而 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 0E4A0E33和0E4A是 UCA 4.0.0 中的主要權重。FFFD是 KAB 和 KISH 的權重。所有補充字元彼此相等的規則並非最佳,但預計不會造成問題。這些字元非常罕見,因此由補充字元組成的多字元字串非常罕見。在日本,由於補充字元是晦澀的漢字象形文字,因此一般使用者不在意它們的順序為何。如果您真的希望根據 MySQL 規則排序的列,其次根據程式碼點值排序,這很容易:
ORDER BY s1 COLLATE utf32_unicode_ci, s1 COLLATE utf32_bin對於基於高於 4.0.0 的 UCA 版本 (例如,
) 的補充字元,補充字元不一定都具有相同的校對權重。有些具有來自 UCAxxx_unicode_520_ciallkeys.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_bin 和 utf16_bin 具有相同的排序。這與 SQL:2008 標準對 UCS_BASIC 校對的要求一致:「UCS_BASIC 是一種校對,其中排序完全由要排序字串中字元的 Unicode 純量值決定。它適用於 UCS 字元集。由於每個字元集都是 UCS 字元集的子集,因此 UCS_BASIC 校對可能適用於每個字元集。附註 11:字元的 Unicode 純量值是其程式碼點,視為不帶正負號的整數。」
如果字元集是 ucs2,則比較是逐位元組的,但 ucs2 字串無論如何都不應包含代理項。