PLSQL开发实现字符串拆分


在应用程序开发中,会出现单选或多选框条件输入的需求。如输入框的输入值为'sz',或'sz|nj|zj|nt',在SQL中会这样处理。

select * from tab_1 where col_1='sz' ;这是单选框输入。

select * from tab_1 where col_1 ='sz|nj' ;这是多选框输入。

很明显,多选输入值不会查询出结果。

如何解决这个问题?

有使用动态SQL实现的方法,如拼装成这样的SQL语句:select * from tab_1 where col_1 in ('sz','nj') ;

还有将'sz|nj'拆分插入到临时表中,再关联该临时表实现,如select * from tab_1 where col_1 in (select a from tt);

临时表涉及到表的创建和维护,还有IO。

我最近想到一个方法:将传入的字符串以嵌套表类型返回,使用表函数调用,实现这类需求。

函数代码如下:

  1. create or replace function f_get_unitstring(p_str_all in varchar2,   
  2.                                             p_str_gap in varchar2)   
  3.   return t_ntb_allstring is  
  4.   --create or replace type t_ntb_allstring  is table of varchar2(20);   
  5.   v_ntb_allstring t_ntb_allstring;   
  6.   
  7.   str_unit varchar2(20);   
  8.   str_char varchar2(1);   
  9.   
  10.   i_str_length number;   
  11.   i_str_index  number;   
  12.   
  13. begin  
  14.   /*p_str_city:='nj~wx~sz~cz~zj~nt~yc~';*/   
  15.   --p_str_all := '1|2|3|';   
  16.   --p_str_gap := '|';   
  17.   
  18.   v_ntb_allstring := t_ntb_allstring();   
  19.   
  20.   i_str_length := length(p_str_all);   
  21.   
  22.   i_str_index := 1;   
  23.   
  24.   while (i_str_index <= i_str_length) loop   
  25.     str_char := substr(p_str_all, i_str_index, 1);   
  26.      
  27.     if (str_char = p_str_gap) then  
  28.        
  29.       if (str_unit is not nullthen  
  30.         v_ntb_allstring.extend(1);   
  31.         v_ntb_allstring(v_ntb_allstring.count) := str_unit;   
  32.         str_unit := null;   
  33.       end if;   
  34.        
  35.     else  
  36.       str_unit := str_unit || str_char;   
  37.        
  38.       if (i_str_index = i_str_length) then  
  39.         v_ntb_allstring.extend(1);   
  40.         v_ntb_allstring(v_ntb_allstring.count) := str_unit;   
  41.         str_unit := '';   
  42.       end if;   
  43.        
  44.     end if;   
  45.      
  46.     i_str_index := i_str_index + 1;   
  47.   end loop;   
  48.   
  49.   return(v_ntb_allstring);   
  50. end;  

测试如下:

  1. SQL> select * from table(f_get_unitstring('1aa|2cc|3bb','|'));   
  2.     
  3. COLUMN_VALUE   
  4. --------------------   
  5. 1aa   
  6. 2cc   
  7. 3bb   
  8.     
  9. SQL>

以上解决方法仅供参数,欢迎交流。

再增加一种方法。

使用pipelined函数也能实现这个需求。但在此处性能优势不会体现出来,如果您碰巧碰到大数据量如亿级别的字符串拆分,该方法就能派上用场。

代码如下:

  1. create or replace function f_get_unitstring(p_str_all in varchar2,   
  2.                                             p_str_gap in varchar2)   
  3.   return t_ntb_allstring   
  4.   pipelined is  
  5.   --create or replace type t_ntb_allstring  is table of varchar2(20);   
  6.   v_ntb_allstring t_ntb_allstring;   
  7.   str_unit varchar2(20);   
  8.   str_char varchar2(1);   
  9.   i_str_length number;   
  10.   i_str_index  number;   
  11. begin  
  12.   v_ntb_allstring := t_ntb_allstring();   
  13.   i_str_length := length(p_str_all);   
  14.   i_str_index := 1;   
  15.   while (i_str_index <= i_str_length) loop   
  16.     str_char := substr(p_str_all, i_str_index, 1);     
  17.     if (str_char = p_str_gap) then  
  18.       if (str_unit is not nullthen  
  19.         --  v_ntb_allstring.extend(1);   
  20.         --  v_ntb_allstring(v_ntb_allstring.count) := str_unit;   
  21.         pipe row(str_unit);   
  22.         str_unit := null;   
  23.       end if;   
  24.     else  
  25.       str_unit := str_unit || str_char;   
  26.       if (str_unit is not nullthen  
  27.         --  v_ntb_allstring.extend(1);   
  28.         --  v_ntb_allstring(v_ntb_allstring.count) := str_unit;   
  29.         pipe row(str_unit);   
  30.         str_unit := null;   
  31.       end if;   
  32.     end if;   
  33.     i_str_index := i_str_index + 1;   
  34.   end loop;   
  35.   --return(v_ntb_allstring);   
  36. end;  

这些方法仅供参考,欢迎交流。

相关内容