本文于 17 天前发布,最后更新于 17 天前
一、问题背景
在达梦数据库的一个大小写不敏感实例中,关联两表查询,关联字段会将字段中的类似Test
和TEST
关联到一起,这种情况不符合预期结果,如何使SQL中的关联字段也像在大小写敏感实例库中一样关联呢?
二、问题复现
创建测试数据
--建表
CREATE TABLE T1 (ID INT, I_CODE VARCHAR2(20));
CREATE TABLE T2 (ID INT, I_CODE VARCHAR2(20));
--插入数据
insert into T1 VALUES (1,'AA');
insert into T1 VALUES (2,'Aa');
insert into T1 VALUES (3,'aa');
insert into T2 VALUES (1,'AA');
insert into T2 VALUES (2,'Aa');
insert into T2 VALUES (3,'aa');
commit;
直接关联查询
SELECT * FROM T1 N LEFT JOIN T2 T ON N.I_CODE = T.I_CODE;
可以看到关联时关联字段并没有区分大小写。
三、问题解决
方法1:设置会话级大小写敏感
支持版本:8.1.2.192(2022.12以后)
ALTER SESSION SET CASE_SENSITIVE=<属性>;
<属性>:= DEFAULT | TRUE | FALSE
- <属性>设置为 DEFAULT 时,代表会话与当前数据库的大小写敏感属性保持一致;
- <属性>设置为 TRUE 时,代表在大小写不敏感的库上可以使得会话中的字符类型数据以大小写敏感的方式进行比较,而在大小写敏感的库上则维持原始方式比较。
- <属性>设置为 FALSE 时,代表在大小写敏感的库上可以使得会话中的字符类型数据以大小写不敏感的方式进行比较,而在大小写不敏感的库上则维持原始方式比较。
方法2:函数BINARY或者MD5
直接利用函数进行字段的关联
SELECT * FROM T1 N LEFT JOIN T2 T ON BINARY(N.I_CODE) = BINARY(T.I_CODE);
--或
SELECT * FROM T1 N LEFT JOIN T2 T ON MD5(N.I_CODE) = MD5(T.I_CODE);
方法3:自定义函数ASCII_SUM
-- 自定义函数:计算字符串所有字符的ASCII码之和
CREATE OR REPLACE FUNCTION ASCII_SUM(str VARCHAR)
RETURN INT
AS
sum_val INT := 0;
BEGIN
FOR i IN 1..LENGTH(str) LOOP
sum_val := sum_val + ASCII(SUBSTR(str, i, 1));
END LOOP;
RETURN sum_val;
END;
/
然后进行正常的关联查询
SELECT * FROM T1 N LEFT JOIN T2 T ON N.I_CODE = T.I_CODE;
注意:该方法存在局限性,当字符串是Aa
与aA
时,虽然两字符串不一样,但经过自定义函数所求的ASCII值之和是一致的,因此,可能导致出现非预期的关联。
方法4:方法3的改进版
CREATE OR REPLACE FUNCTION ASCII_UNIQUE_CODE(str VARCHAR2)
RETURN VARCHAR2
AS
unique_code VARCHAR2(4000) := '';
BEGIN
FOR i IN 1..LENGTH(str) LOOP
-- 格式:位置-ASCII值;(如 "1-65;2-66;")
unique_code := unique_code || i || '-' || ASCII(SUBSTR(str, i, 1)) || ';';
END LOOP;
RETURN unique_code;
END;
/
测试验证
SELECT ASCII_UNIQUE_CODE('Aa');
SELECT ASCII_UNIQUE_CODE('aA');