在絕大多數的陳述式中,MySQL 使用哪個校對來解析比較運算是顯而易見的。例如,在以下情況下,校對是欄位 x
的校對應該是很清楚的
SELECT x FROM T ORDER BY x;
SELECT x FROM T WHERE x = x;
SELECT DISTINCT x FROM T;
然而,對於多個運算元,可能會出現歧義。例如,此陳述式會執行欄位 x
與字串文字 'Y'
之間的比較
SELECT x FROM T WHERE x = 'Y';
如果 x
和 'Y'
具有相同的校對,則對於用於比較的校對沒有歧義。但是,如果它們具有不同的校對,則比較應該使用 x
的校對,還是 'Y'
的校對? x
和 'Y'
都有校對,那麼哪個校對優先?
校對的混合也可能發生在比較以外的上下文中。例如,多引數串連運算(例如 CONCAT(x,'Y')
)會結合其引數來產生單一字串。結果應該具有哪個校對?
為了解決這類問題,MySQL 會檢查一個項目的校對是否可以被強制轉換為另一個項目的校對。MySQL 會如下指派強制性值
MySQL 使用具有下列規則的強制性值來解決歧義
使用具有最低強制性值的校對。
如果雙方的強制性相同,則
如果雙方都是 Unicode,或雙方都不是 Unicode,則會產生錯誤。
如果其中一方具有 Unicode 字元集,而另一方具有非 Unicode 字元集,則具有 Unicode 字元集的一方勝出,且會將自動字元集轉換套用至非 Unicode 方。例如,下列陳述式不會傳回錯誤
SELECT CONCAT(utf8mb4_column, latin1_column) FROM t1;
它傳回的結果具有
utf8mb4
的字元集,且與utf8mb4_column
的校對相同。在串連之前,latin1_column
的值會自動轉換為utf8mb4
。對於具有來自相同字元集的運算元,但混合了
_bin
校對和_ci
或_cs
校對的運算,會使用_bin
校對。這類似於混合非二進位和二進位字串的運算如何將運算元評估為二進位字串,套用於校對而不是資料類型。
雖然自動轉換不在 SQL 標準中,但該標準確實表示每個字元集(就支援的字元而言)都是 Unicode 的「子集」。由於這是廣為人知的原則,即「適用於超集的原則也適用於子集」,因此我們認為 Unicode 的校對可以適用於與非 Unicode 字串的比較。更廣泛地說,MySQL 使用字元集詞彙的概念,該概念有時可用於判斷字元集之間的子集關係,並啟用在其他情況下會產生錯誤的運算中轉換運算元。請參閱 第 12.2.1 節「字元集詞彙」。
下表說明了先前規則的一些應用。
比較 | 使用的校對 |
---|---|
column1 = 'A' |
使用 column1 的校對 |
column1 = 'A' COLLATE x |
使用 'A' COLLATE x 的校對 |
column1 COLLATE x = 'A' COLLATE y |
錯誤 |
若要判斷字串表達式的強制性,請使用 COERCIBILITY()
函數(請參閱 第 14.15 節「資訊函數」)
mysql> SELECT COERCIBILITY(_utf8mb4'A' COLLATE utf8mb4_bin);
-> 0
mysql> SELECT COERCIBILITY(VERSION());
-> 3
mysql> SELECT COERCIBILITY('A');
-> 4
mysql> SELECT COERCIBILITY(1000);
-> 5
mysql> SELECT COERCIBILITY(NULL);
-> 6
對於數值或時間值隱式轉換為字串的情況,例如在運算式 CONCAT(1, 'abc')
中引數 1
的轉換,結果會是一個字元 (非二進位) 字串,其字元集和校對方式由 character_set_connection
和 collation_connection
系統變數決定。請參閱第 14.3 節「運算式求值中的型別轉換」。