在MYSQL兼容模式(即sql_compatibility = 'MYSQL')的数据库下,且设置参数b_format_version='5.7'和b_format_dev_version='s2'时,可以将不同字符集字符序的表达式按一定优先级处理,来确定字符串比较运算时的使用的字符序和表达式的字符集。
字符序优先级
不同表达式字符序优先级由高到低排列如下:
-
COLLATE语法拥有最高优先级。
-
含有字符序冲突的表达式(如:两个不同字符序的字符串拼接表达式)。
-
支持字符序的数据类型的列、用户自定义变量、存储过程参数、CASE表达式等。
-
特定的系统函数(如:version()和opengauss_version()函数表达式)。
-
字符串常量和绑定参数。
-
NULL表达式。
-
如果一个表达式的数据类型不支持字符序,那么这个表达式的优先级最低。
当两个表达式字符序不同时,使用字符序优先级最高的表达式的字符序。
示例:
gaussdb=# CREATE TABLE t_utf8(c1 varchar(16) character set utf8mb4 collate utf8mb4_bin);
gaussdb=# INSERT INTO t_utf8 VALUES('STRING');
-- 比较时使用utf8mb4_bin字符序,结果为false。
gaussdb=# SELECT c1 = 'string' AS result FROM t_utf8;
result
--------
f
(1 row)
-- 比较时使用utf8mb4_general_ci字符序,结果为true。
gaussdb=# SELECT c1 = 'string' COLLATE utf8mb4_general_ci AS result FROM t_utf8;
result
--------
t
(1 row)
-- 将绑定参数“$1”的字符序定义为collation_connection。
gaussdb=# PREPARE test_collation(text) AS SELECT c1 = $1 AS result FROM t_utf8;
-- 绑定参数字符序与字符串常量同级别,即使传入的表达式含有显式的字符序,比较时仍然采用c1的字符序。
gaussdb=# EXECUTE test_collation('string' COLLATE utf8mb4_general_ci);
result
--------
f
(1 row)
-- CASE表达式与c1列同级别,即使表达式含有显式的字符序,比较时仍然采用c1的字符序,二者不相等,输出“same level”。
gaussdb=# 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的字符序,二者不相等。
gaussdb=# SELECT c1 FROM t_utf8 WHERE c1 in (SELECT 'string' COLLATE utf8mb4_general_ci);
c1
----
(0 rows)
|
当两个相同优先级的表达式字符序不同时,采用以下方式处理:
- 如果两者字符集相同,优先使用后缀为_bin的字符序。
- 如果两者字符集相同,优先不使用default字符序。
- 如果不符合上述情况,两表达式将被标记为字符序冲突,字符序将被标记为无效。
示例:
gaussdb=# 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);
gaussdb=# INSERT INTO t_utf8mb4_charset VALUES('STRING', 'String', 'string');
-- 优先使用utf8mb4_bin字符序比较,结果为false。
gaussdb=# SELECT c_utf8_bin = c_utf8_uni FROM t_utf8mb4_charset;
-- 字符序冲突,进行二进制比较,结果为false。
gaussdb=# SELECT c_utf8_uni = c_utf8_gen FROM t_utf8mb4_charset;
-- 显式指定的字符序冲突,抛出异常。
gaussdb=# SELECT c_utf8_uni COLLATE utf8mb4_unicode_ci = c_utf8_gen COLLATE utf8mb4_general_ci FROM t_utf8mb4_charset;
|