有这样的一个需求,数据库(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;
函数随好,可不能乱用。