字符集和字符序合并规则
不同字符集字符序的表达式按一定优先级处理,来确定字符串比较运算时的使用的字符序和表达式的字符集。
字符序优先级
不同表达式字符序优先级由高到低排列如下:
当两个表达式字符序不同时,使用字符序优先级最高的表达式的字符序。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
m_db=# CREATE TABLE t_utf8(c1 varchar(16) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin); m_db=# INSERT INTO t_utf8 VALUES('STRING'); -- 比较时使用utf8mb4_bin字符序,结果为false。 m_db=# SELECT c1 = 'string' AS result FROM t_utf8; result -------- f (1 row) -- 比较时使用utf8mb4_general_ci字符序,结果为true。 m_db=# SELECT c1 = 'string' COLLATE utf8mb4_general_ci AS result FROM t_utf8; result -------- t (1 row) -- 将绑定参数“?”的字符序定义为collation_connection。 m_db=# PREPARE test_collation FROM 'SELECT c1 = ? AS result FROM t_utf8'; -- 绑定参数字符序与字符串常量同级别,在上一步prepare时已经确定了执行时使用c1的字符序,因此结果为false。 m_db=# SET @aa = 'string' COLLATE utf8mb4_general_ci; m_db=# EXECUTE test_collation using @aa; result -------- f (1 row) -- CASE表达式与c1列同级别,即使表达式含有显式的字符序,比较时仍然采用c1的字符序,二者不相等,输出“same level”。 m_db=# SELECT CASE 'string' COLLATE utf8mb4_general_ci WHEN c1 THEN 'different level' ELSE 'same level' END AS result FROM t_utf8; result ------------ same level (1 row) -- IN子查询与c1列同级别,即使表达式含有显式的字符序,比较时仍然采用c1的字符序,二者不相等。 m_db=# SELECT c1 FROM t_utf8 WHERE c1 in (SELECT 'string' COLLATE utf8mb4_general_ci); c1 ---- (0 rows) |
当两个相同优先级的表达式字符序不同时,采用以下方式处理:
- 如果两者字符集相同,优先使用后缀为_bin的字符序。
- 如果两者字符集相同,优先不使用default字符序。
- 如果两者字符集不同,优先使用BINARY字符序。
- 如果两者字符集不同,且一个为Unicode字符集,另一个不为Unicode字符集,非Unicode字符集的表达式需要转码为Unicode字符集,最终使用Unicode字符集的表达式的字符序。
- 如果不符合上述情况,两表达式将被标记为字符序冲突,字符序将被标记为无效。
示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
m_db=# CREATE TABLE t_utf8mb4_charset( c_utf8_bin varchar(16) character set utf8mb4 collate utf8mb4_bin, c_utf8_uni varchar(16) character set utf8mb4 collate utf8mb4_unicode_ci, c_utf8_gen varchar(16) character set utf8mb4 collate utf8mb4_general_ci); m_db=# INSERT INTO t_utf8mb4_charset VALUES('STRING', 'String', 'string'); -- 优先使用utf8mb4_bin字符序比较,结果为false。 m_db=# SELECT c_utf8_bin = c_utf8_uni FROM t_utf8mb4_charset; ?column? ---------- f (1 row) -- 字符序冲突,进行二进制比较,结果为false。 m_db=# SELECT c_utf8_uni = c_utf8_gen FROM t_utf8mb4_charset; ERROR: Collation mismatch between collations "utf8mb4_unicode_ci" and "utf8mb4_general_ci". LINE 1: SELECT c_utf8_uni = c_utf8_gen FROM t_utf8mb4_charset; ^ -- 显式指定的字符序冲突,抛出异常。 m_db=# SELECT c_utf8_uni COLLATE utf8mb4_unicode_ci = c_utf8_gen COLLATE utf8mb4_general_ci FROM t_utf8mb4_charset; ERROR: collation mismatch between explicit collations "utf8mb4_unicode_ci" and "utf8mb4_general_ci" LINE 1: ..._utf8_uni COLLATE utf8mb4_unicode_ci = c_utf8_gen COLLATE ut... ^ |
