更新时间:2025-09-11 GMT+08:00
分享

字符集和字符序合并规则

不同字符集字符序的表达式按一定优先级处理,来确定字符串比较运算时的使用的字符序和表达式的字符集。

字符序优先级

不同表达式字符序优先级由高到低排列如下:

  • COLLATE语法拥有最高优先级。

  • 含有字符序冲突的表达式(如:两个不同字符序的字符串拼接表达式)。

  • 支持字符序的数据类型的列、用户自定义变量、存储过程参数以及CASE表达式等。

  • 特定的系统函数(如:version()和opengauss_version()函数表达式)。

  • 字符串常量和绑定参数。

  • NULL表达式。

  • 一个表达式的数据类型不支持字符序,这个表达式拥有最低优先级。

当两个表达式字符序不同时,使用字符序优先级最高的表达式的字符序。

示例:

 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
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)

-- 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)

-- 删除表
m_db=# DROP TABLE t_utf8;

当两个相同优先级的表达式字符序不同时,采用以下方式处理:

  • 如果两者字符集相同,优先使用后缀为_bin的字符序。
  • 如果两者字符集相同,优先不使用default字符序。
  • 如果不符合上述情况,两表达式将被标记为字符序冲突,字符序将被标记为无效。
    • 因COLLATE语法指定同字符集不同字符序产生的冲突,将提示异常。

    • 若冲突的两个字符序均为M-Compatibility下支持的字符序,将提示异常。
    • 无效字符序如果被用作排序运算时(如:>、<等),将提示异常。
    • 字符串等值比较时,如果字符序无效,将直接作为二进制比较相等。

示例:

 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
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)

-- 字符序冲突,提示异常。
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...
                                                             ^
-- 删除表
m_db=# DROP TABLE t_utf8mb4_charset;
  • 只有字符串类型(不包括"char"、name)的对象和表达式的字符集可以和数据库的字符集不同。

  • 在字符集和字符序合并规则中,认为 C、POSIX和DEFAULT字符序对应的字符集为server_encoding。

相关文档