本節說明 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 0E4A
0E33
和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
字串無論如何都不應包含代理項。