同字段筛选不同值(sql中字符串拆分)

有这样的一个需求,数据库(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;

函数随好,可不能乱用。

 

 

你可能感兴趣的:(数据库)