有这样的一个需求,数据库(Oracle)有一字段值:221Q,332W,234,455R,755,需要将其拆分为:221Q,332W,455R 与 234,755 这样的两组数据,并update到表中的其他两个字段。当时我写了一个函数,函数使用了oralce自带的行转列与列转行的两个函数,代码如下:
--Purpose:拆分,并去重
--Example:f_get_cg('755,769A,755A,020',0)返回755,020
-- f_get_cg('755,769A,755A,020',1)返回769A,755A
FUNCTION f_get_cg(p_str IN VARCHAR2, p_flg IN NUMBER) RETURN VARCHAR2 IS
rsult VARCHAR2(4000);
BEGIN
IF p_flg = 0 THEN
SELECT wmsys.wm_concat(cargo)
INTO rsult
FROM (SELECT DISTINCT cargo
FROM (SELECT REGEXP_SUBSTR(p_str, '[^,]+', 1, rownum) cargo
FROM DUAL
CONNECT BY ROWNUM <=
LENGTH(p_str) -
LENGTH(REPLACE(p_str, ',', '')) + 1))
WHERE regexp_like(cargo, '^[0-9]+$');
ELSE
SELECT wmsys.wm_concat(cargo)
INTO rsult
FROM (SELECT DISTINCT cargo
FROM (SELECT REGEXP_SUBSTR(p_str, '[^,]+', 1, rownum) cargo
FROM DUAL
CONNECT BY ROWNUM <=
LENGTH(p_str) -
LENGTH(REPLACE(p_str, ',', '')) + 1))
WHERE regexp_like(cargo, '^[0-9]+[A-Z]+$');
END IF;
RETURN(rsult);
END f_get_cg;
效率极其缓慢,5分钟才能update完5000笔记录。
后来换一种思路,只使用instr,substr函数去拆分,效率嗖就上来了,相同的5000笔记录,只要不到10秒钟时间:
FUNCTION f_split(p_list VARCHAR2, p_flg IN NUMBER) RETURN VARCHAR2
IS
p_sep VARCHAR2(1) := ',';
l_idx PLS_INTEGER;
v_list VARCHAR2(4000) := p_list;
v_tempstr VARCHAR2(100);
return_str VARCHAR2(4000);
BEGIN
LOOP
l_idx := instr(v_list, p_sep);
IF l_idx > 0 THEN
v_tempstr := substr(v_list, 1, l_idx - 1);
IF p_flg = 0
AND regexp_like(v_tempstr, '^[0-9]+$')
AND (return_str IS NULL OR instr(return_str, v_tempstr) = 0) THEN
return_str := return_str || p_sep || v_tempstr;
ELSIF p_flg = 1
AND regexp_like(v_tempstr, '^[0-9]+[A-Z]+$')
AND (return_str IS NULL OR instr(return_str, v_tempstr) = 0) THEN
return_str := return_str || p_sep || v_tempstr;
END IF;
v_list := substr(v_list, l_idx + length(p_sep));
ELSE
IF p_flg = 0
AND regexp_like(v_list, '^[0-9]+$')
AND (return_str IS NULL OR instr(return_str, v_list) = 0) THEN
return_str := return_str || p_sep || v_list;
ELSIF p_flg = 1
AND regexp_like(v_list, '^[0-9]+[A-Z]+$')
AND (return_str IS NULL OR instr(return_str, v_list) = 0) THEN
return_str := return_str || p_sep || v_list;
END IF;
EXIT;
END IF;
END LOOP;
RETURN substr(return_str, 2);
END f_split;
函数随好,可不能乱用。