为提高效率,提问时请提供以下信息,问题描述清晰可优先响应。
【DM版本】:DMV8
【操作系统】:麒麟
【CPU】:arm
【问题描述】*:达梦数据库中如何将一个字符串按指定字符切割转为一个临时表或数组,如pg中的regex_split_to_table和regex_split_to_array的功能
如果数据量不是很大的话,可以用递归查询来变通实现
SELECT ID,LEVEL AS SUBID,REGEXP_SUBSTR(NAME,'[^,]+',1,LEVEL) AS SUB
FROM (select 1 id,'a,b,c' name from dual
union all select 2,'b,c' from dual
union all select 3,'a,b,c,d,e,f' from dual
) A
CONNECT BY PRIOR ID = ID
AND PRIOR SYS_GUID() IS NOT NULL
AND LEVEL <= REGEXP_COUNT(NAME,',') + 1
在DM数据库中,可以使用DBMS_UTILITY.COMMA_TO_TABLE
函数或者正则表达式相关的函数来实现字符串的切割,并将结果转换为一个临时表或数组。不过,DBMS_UTILITY.COMMA_TO_TABLE
函数只能按逗号切割字符串,如果要按照其他字符切割,则需要使用正则表达式。
DECLARE
l_list1 VARCHAR2(50) := 'A,B,C,D,E,F,G,H,I,J';
l_list2 VARCHAR2(50);
l_tablen BINARY_INTEGER;
l_tab DBMS_UTILITY.LNAME_ARRAY;
BEGIN
DBMS_OUTPUT.put_line('l_list1 : ' || l_list1);
DBMS_UTILITY.comma_to_table(l_list1,
l_tablen,
l_tab);
FOR i IN 1 .. l_tablen LOOP
PRINT(i || ' : ' || l_tab(i));
END LOOP;
DBMS_UTILITY.table_to_comma(l_tab,
l_tablen,
l_list2);
PRINT('l_list2 : ' || l_list2);
END;
您好!您这个问题其实好比较复杂,有如下可以考虑的方案:
1)对接原厂工程师,提交系统功函数兼容性需求。
2)考虑自定义函数,做类似实现。
3)其实这个可能,从更底层的维度,是一个表结构设计的问题,不太建立在元组中,存放需要分割的字段,和数据库的设计范式,不太相符。
4)直接当前DM上实现,可以考虑用层次查询,不过写起来就费老劲了,e.g
SELECT ID , substr(a.NAME, instr(a.NAME, ',', 1, levels.lvl) + 1, instr(a.NAME, ',', 1, levels.lvl + 1) -(instr(a.NAME, ',', 1, levels.lvl) + 1)) as NAME FROM ( SELECT ID, ',' || NAME || ',' AS NAME, length(NAME) - nvl(length(REPLACE(NAME, ',')), 0) + 1 AS cnt FROM (select 1 id,'a,b,c' name from dual union all select 2,'b,c' from dual union all select 3,'a,b,c,d,e,f' from dual ) AAA ) a, ( SELECT rownum AS lvl FROM ( SELECT MAX(length(NAME || ',') - nvl(length(REPLACE(NAME, ',')), 0)) max_len FROM (select 1 id,'a,b,c' name from dual union all select 2,'b,c' from dual union all select 3,'a,b,c,d,e,f' from dual ) AAA ) CONNECT BY LEVEL <= max_len ) levels WHERE levels.lvl <= a.cnt ORDER BY ID;
上面这段代码的说明:核心是层次查询。