我有一个在列上定义了排序规则的表:
CREATE TEMPORARY TABLE test_table (
utf8_col VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin
);
INSERT INTO test_table VALUES('ã');根据MySQL 矫顽力规则,当将来自该列的值与文字进行比较时:
SELECT utf8_col < _utf8mb4'ñ' FROM test_table;这将导致比较失败,因为列CCV具有更高的优先级,并且应该使用utf8_bin排序规则,它不能处理utf8mb4字符集。
然而,这种比较是成功的。为什么会这样呢?
发布于 2019-03-22 15:26:09
为什么上述比较成功?
因为MySQL很好,并且自动纠正用户错误,但这仅仅是因为它可以。
你没有错:
以及:
但是,您没有看到您认为在测试中看到的内容,因为您没有使用需要"mb4“版本的"utf8”排序规则的数据进行测试。您正在使用一个“安全”值进行测试,该值适合于非补充字符能力的utf8字符集。在这种情况下,MySQL只需使用列的字符集-- utf8 -- utf8_bin排序规则就可以了。
当您使用一个4字节字符(即一个补充字符)时,世界看起来有点不同。在这种情况下,字符不能存在于utf8字符集中(因为utf8字符集只能通过U+FFFF /字符处理BMP字符/头65,536个代码点/ U+0000,每个字符为1到3个字节)。因此,由于字符串文本的字符集不能更改为与列的排序规则- utf8_bin一起工作的字符集,因此您将得到一个错误,声明:
用于“<”操作的非法排序规则(utf8_bin,隐式)和(utf8mb4_0900_ai_ci,强制)的非法混合
我使用代码点U+1F369 (即甜甜圈表情符号:“🍩”)进行测试:
CREATE TABLE test_table (
utf8_col VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin
);
INSERT INTO test_table VALUES('ã'); # any utf8 character from U+0000 to U+FFFF
# Test against any utf8 character from U+0000 to U+FFFF in _utf8mb4
SELECT utf8_col,
CHARSET(utf8_col) AS 'charset',
COLLATION(utf8_col) AS 'collation',
CONCAT(utf8_col, _utf8mb4'ñ') AS 'concat1',
CHARSET(CONCAT(utf8_col, _utf8mb4'ñ')) AS 'charset_concat1'
FROM test_table;
# Test against any utf8 character from U+10000 to U+10FFFF in _utf8mb4
SELECT utf8_col,
CHARSET(utf8_col) AS 'charset',
COLLATION(utf8_col) AS 'collation',
CONCAT(utf8_col, _utf8mb4'') AS 'concat2',
CHARSET(CONCAT(utf8_col, _utf8mb4'')) AS 'charset_concat2'
FROM test_table;
# FAIL
SELECT utf8_col < _utf8mb4'ñ' FROM test_table; # Success
SELECT utf8_col < _utf8mb4'' FROM test_table; # FAIL请参阅上面的示例代码在dbfiddle.uk上行动
第一个SELECT的结果集是:
utf8_col charset collation concat1 charset_concat1
ã utf8 utf8_bin ãñ utf8这表明utf8mb4字符串是被胁迫到utf8中的,每个人都很高兴。我很高兴,直到甜甜圈先生在第二次SELECT声明中出现(你会认为甜甜圈会让一切变得更好,不是吗?)我通常做😸)。
https://dba.stackexchange.com/questions/232834
复制相似问题