欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

PLSQL表函数实现字符串拆分

程序员文章站 2022-03-02 13:57:37
...

在应用程序开发中,会出现单选或多选框条件输入的需求。如输入框的输入值为'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') ;动态SQL调试麻烦。

 

方法二,将'sz|nj'拆分插入到临时表中,再关联该临时表实现,如select * from tab_1 where col_1 in (select a from tt); 但是临时表涉及到表的创建和维护,还有IO。

 

(miki西游 @mikixiyou 原文链接: http://mikixiyou.iteye.com/blog/1681631 )

 

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

 

函数代码如下:

create or replace function f_get_unitstring(p_str_all in varchar2,
                                            p_str_gap in varchar2)
  return t_ntb_allstring is
  --create or replace type t_ntb_allstring  is table of varchar2(20);
  v_ntb_allstring t_ntb_allstring;

  str_unit varchar2(20);
  str_char varchar2(1);

  i_str_length number;
  i_str_index  number;

begin
  /*p_str_city:='nj~wx~sz~cz~zj~nt~yc~';*/
  --p_str_all := '1|2|3|';
  --p_str_gap := '|';

  v_ntb_allstring := t_ntb_allstring();

  i_str_length := length(p_str_all);

  i_str_index := 1;

  while (i_str_index <= i_str_length) loop
    str_char := substr(p_str_all, i_str_index, 1);
  
    if (str_char = p_str_gap) then
    
      if (str_unit is not null) then
        v_ntb_allstring.extend(1);
        v_ntb_allstring(v_ntb_allstring.count) := str_unit;
        str_unit := null;
      end if;
    
    else
      str_unit := str_unit || str_char;
    
      if (i_str_index = i_str_length) then
        v_ntb_allstring.extend(1);
        v_ntb_allstring(v_ntb_allstring.count) := str_unit;
        str_unit := '';
      end if;
    
    end if;
  
    i_str_index := i_str_index + 1;
  end loop;

  return(v_ntb_allstring);
end;

 

测试如下:

 
SQL> select * from table(f_get_unitstring('1aa|2cc|3bb','|'));
 
COLUMN_VALUE
--------------------
1aa
2cc
3bb
 
SQL> 

 

 

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

 

如果你有大数据量处理要求,我将此方法修改一下。转而使用pipelined函数来实现这个需求。

但在此处性能优势不会体现出来,只有在你有大数据量如亿级别的字符串拆分,它才能派上用场。

 

代码如下:

create or replace function f_get_unitstring(p_str_all in varchar2,
                                            p_str_gap in varchar2)
  return t_ntb_allstring
  pipelined is
  --create or replace type t_ntb_allstring  is table of varchar2(20);
  v_ntb_allstring t_ntb_allstring;
  str_unit varchar2(20);
  str_char varchar2(1);
  i_str_length number;
  i_str_index  number;
begin
  v_ntb_allstring := t_ntb_allstring();
  i_str_length := length(p_str_all);
  i_str_index := 1;
  while (i_str_index <= i_str_length) loop
    str_char := substr(p_str_all, i_str_index, 1);  
    if (str_char = p_str_gap) then
      if (str_unit is not null) then
        --  v_ntb_allstring.extend(1);
        --  v_ntb_allstring(v_ntb_allstring.count) := str_unit;
        pipe row(str_unit);
        str_unit := null;
      end if;
    else
      str_unit := str_unit || str_char;
      if (str_unit is not null) then
        --  v_ntb_allstring.extend(1);
        --  v_ntb_allstring(v_ntb_allstring.count) := str_unit;
        pipe row(str_unit);
        str_unit := null;
      end if;
    end if;
    i_str_index := i_str_index + 1;
  end loop;
  --return(v_ntb_allstring);
end;
 

 

这些方法仅供参考,欢迎交流。谢谢!@mikixiyou