字元集的編碼範圍是該集合中的字元集合。
字串運算式具有編碼範圍屬性,它可以有兩個值
ASCII
:運算式只能包含 ASCII 字元;也就是說,Unicode 範圍U+0000
到U+007F
中的字元。UNICODE
:運算式可以包含 Unicode 範圍U+0000
到U+10FFFF
中的字元。這包括基本多文種平面 (BMP) 範圍中的字元 (U+0000
到U+FFFF
) 和 BMP 範圍之外的補充字元 (U+10000
到U+10FFFF
)。
ASCII
範圍是 UNICODE
範圍的子集,因此具有 ASCII
編碼範圍的字串可以安全地轉換為具有 UNICODE
編碼範圍的任何字串的字元集,而不會遺失資訊。它也可以安全地轉換為任何為 ascii
字元集超集的字元集。(除了 swe7
之外,所有 MySQL 字元集都是 ascii
的超集,swe7
為瑞典語重音字元重複使用了一些標點符號字元。)
在排序規則強制性規則不足以解決歧義的情況下,編碼範圍的使用可以讓運算式中的字元集轉換在許多情況下進行,否則 MySQL 會傳回 「排序規則非法混合」錯誤。(如需強制性的資訊,請參閱第 12.8.4 節,〈運算式中的排序規則強制性〉。)
以下討論提供運算式及其編碼範圍的範例,並描述編碼範圍的使用如何變更字串運算式評估
字串常數的編碼範圍取決於字串內容,並且可能與字串字元集的編碼範圍不同。請考慮這些陳述式
SET NAMES utf8mb4; SELECT 'abc'; SELECT _utf8mb4'def';
雖然在上述每種情況下,字元集都是
utf8mb4
,但字串實際上不包含任何 ASCII 範圍之外的字元,因此它們的編碼範圍是ASCII
而不是UNICODE
。由於字元集的原因,具有
ascii
字元集的欄位具有ASCII
編碼範圍。在下表中,c1
具有ASCII
編碼範圍CREATE TABLE t1 (c1 CHAR(1) CHARACTER SET ascii);
以下範例說明編碼範圍如何在沒有編碼範圍的情況下,讓結果在發生錯誤的情況下確定
CREATE TABLE t1 ( c1 CHAR(1) CHARACTER SET latin1, c2 CHAR(1) CHARACTER SET ascii ); INSERT INTO t1 VALUES ('a','b'); SELECT CONCAT(c1,c2) FROM t1;
沒有編碼範圍時,會發生此錯誤
ERROR 1267 (HY000): Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (ascii_general_ci,IMPLICIT) for operation 'concat'
使用編碼範圍時,可以進行子集到超集 (
ascii
到latin1
) 轉換,並傳回結果+---------------+ | CONCAT(c1,c2) | +---------------+ | ab | +---------------+
具有一個字串引數的函數會繼承其引數的編碼範圍。
UPPER(_utf8mb4'abc')
的結果具有ASCII
編碼範圍,因為其引數具有ASCII
編碼範圍。(儘管有_utf8mb4
引介詞,字串'abc'
不包含任何 ASCII 範圍之外的字元。)對於傳回字串但不具有字串引數,並且使用
character_set_connection
作為結果字元集的函數,如果character_set_connection
是ascii
,則結果編碼範圍為ASCII
,否則為UNICODE
FORMAT(numeric_column, 4);
編碼範圍的使用會變更 MySQL 評估以下範例的方式
SET NAMES ascii; CREATE TABLE t1 (a INT, b VARCHAR(10) CHARACTER SET latin1); INSERT INTO t1 VALUES (1,'b'); SELECT CONCAT(FORMAT(a, 4), b) FROM t1;
沒有編碼範圍時,會發生此錯誤
ERROR 1267 (HY000): Illegal mix of collations (ascii_general_ci,COERCIBLE) and (latin1_swedish_ci,IMPLICIT) for operation 'concat'
使用編碼範圍時,會傳回結果
+-------------------------+ | CONCAT(FORMAT(a, 4), b) | +-------------------------+ | 1.0000b | +-------------------------+
具有兩個或多個字串引數的函數會將 「最寬」引數編碼範圍用於結果編碼範圍,其中
UNICODE
比ASCII
寬。請考慮以下CONCAT()
呼叫CONCAT(_ucs2 X'0041', _ucs2 X'0042') CONCAT(_ucs2 X'0041', _ucs2 X'00C2')
對於第一個呼叫,編碼範圍是
ASCII
,因為兩個引數都在 ASCII 範圍內。對於第二個呼叫,編碼範圍是UNICODE
,因為第二個引數在 ASCII 範圍之外。函數傳回值的編碼範圍僅根據會影響結果字元集和排序規則的那些引數的編碼範圍來決定。
IF(column1 < column2, 'smaller', 'greater')
結果編碼範圍是
ASCII
,因為兩個字串引數 (第二個引數和第三個引數) 都具有ASCII
編碼範圍。第一個引數對於結果編碼範圍並不重要,即使運算式使用字串值。