是否有在PL/SQL中拆分字符串的功能?

Sam*_*Sam 48 string oracle plsql split tokenize

我需要编写一个过程来规范化一个记录,该记录具有由一个char连接的多个标记.我需要获取这些标记分割字符串并将每个标记作为新记录插入表中.Oracle是否有类似"拆分"功能的东西?

Ton*_*ews 35

apex_util.string_to_table- 看到对这个问题的回答.

此外,在上述功能存在之前,我曾在我的博客上发布了一个解决方案.

更新

在APEX更高版本,apex_util.string_to_table弃用,和类似的功能apex_string.split是优选的.


Red*_*ter 17

你必须自己动手.例如,

/* from :http://www.builderau.com.au/architect/database/soa/Create-functions-to-join-and-split-strings-in-Oracle/0,339024547,339129882,00.htm

select split('foo,bar,zoo') from dual;
select * from table(split('foo,bar,zoo'));

pipelined function is SQL only (no PL/SQL !)
*/

create or replace type split_tbl as table of varchar2(32767);
/
show errors

create or replace function split
(
    p_list varchar2,
    p_del varchar2 := ','
) return split_tbl pipelined
is
    l_idx    pls_integer;
    l_list    varchar2(32767) := p_list;
    l_value    varchar2(32767);
begin
    loop
        l_idx := instr(l_list,p_del);
        if l_idx > 0 then
            pipe row(substr(l_list,1,l_idx-1));
            l_list := substr(l_list,l_idx+length(p_del));

        else
            pipe row(l_list);
            exit;
        end if;
    end loop;
    return;
end split;
/
show errors;

/* An own implementation. */

create or replace function split2(
  list in varchar2,
  delimiter in varchar2 default ','
) return split_tbl as
  splitted split_tbl := split_tbl();
  i pls_integer := 0;
  list_ varchar2(32767) := list;
begin
  loop
    i := instr(list_, delimiter);
    if i > 0 then
      splitted.extend(1);
      splitted(splitted.last) := substr(list_, 1, i - 1);
      list_ := substr(list_, i + length(delimiter));
    else
      splitted.extend(1);
      splitted(splitted.last) := list_;
      return splitted;
    end if;
  end loop;
end;
/
show errors

declare
  got split_tbl;

  procedure print(tbl in split_tbl) as
  begin
    for i in tbl.first .. tbl.last loop
      dbms_output.put_line(i || ' = ' || tbl(i));
    end loop;
  end;

begin
  got := split2('foo,bar,zoo');
  print(got);
  print(split2('1 2 3 4 5', ' '));
end;
/
Run Code Online (Sandbox Code Playgroud)


Fro*_*y Z 16

如果APEX_UTIL没有,您可以使用解决方案REGEXP_SUBSTR().

灵感来自http://nuijten.blogspot.fr/2009/07/splitting-comma-delimited-string-regexp.html:

DECLARE
  I INTEGER;
  TYPE T_ARRAY_OF_VARCHAR IS TABLE OF VARCHAR2(2000) INDEX BY BINARY_INTEGER;
  MY_ARRAY T_ARRAY_OF_VARCHAR;
  MY_STRING VARCHAR2(2000) := '123,456,abc,def';
BEGIN
  FOR CURRENT_ROW IN (
    with test as    
      (select MY_STRING from dual)
      select regexp_substr(MY_STRING, '[^,]+', 1, rownum) SPLIT
      from test
      connect by level <= length (regexp_replace(MY_STRING, '[^,]+'))  + 1)
  LOOP
    DBMS_OUTPUT.PUT_LINE(CURRENT_ROW.SPLIT);
    MY_ARRAY(MY_ARRAY.COUNT) := CURRENT_ROW.SPLIT;
  END LOOP;
END;
/
Run Code Online (Sandbox Code Playgroud)


Meo*_*r68 10

这仅适用于Oracle 10G及更高版本.

基本上,您使用regex_substr对字符串进行拆分.

https://blogs.oracle.com/aramamoo/entry/how_to_split_comma_separated_string_and_pass_to_in_clause_of_select_statement

  • 你提到的页面确实非常好,但最好在这里复制代码,以便更容易,更快速地查看它.在死链接的情况下也更好...... (6认同)

小智 5

您可以使用SUBSTR和INSTR的组合,如下所示:

示例字符串: field = 'DE124028#@$1048708#@$000#@$536967136#@$'

分离器是#@ $.

以获得'1048708'为例:

如果该字段具有固定长度(此处为7):

substr(field,instr(field,'#@$',1,1)+3,7)
Run Code Online (Sandbox Code Playgroud)

如果字段长度可变:

substr(field,instr(field,'#@$',1,1)+3,instr(field,'#@$',1,2) - (instr(field,'#@$',1,1)+3)) 
Run Code Online (Sandbox Code Playgroud)

您应该查看SUBSTR和INSTR函数以获得更大的灵活性.


小智 5

请找下您可能会觉得有用的示例

--1st子串

select substr('alfa#bravo#charlie#delta', 1,  
  instr('alfa#bravo#charlie#delta', '#', 1, 1)-1) from dual;
Run Code Online (Sandbox Code Playgroud)

--2nd子串

select substr('alfa#bravo#charlie#delta', instr('alfa#bravo#charlie#delta', '#', 1, 1)+1,  
  instr('alfa#bravo#charlie#delta', '#', 1, 2) - instr('alfa#bravo#charlie#delta', '#', 1, 1) -1) from dual;
Run Code Online (Sandbox Code Playgroud)

--3rd子串

select substr('alfa#bravo#charlie#delta', instr('alfa#bravo#charlie#delta', '#', 1, 2)+1,  
  instr('alfa#bravo#charlie#delta', '#', 1, 3) - instr('alfa#bravo#charlie#delta', '#', 1, 2) -1) from dual;
Run Code Online (Sandbox Code Playgroud)

- 第4个子串

select substr('alfa#bravo#charlie#delta', instr('alfa#bravo#charlie#delta', '#', 1, 3)+1) from dual;
Run Code Online (Sandbox Code Playgroud)

最好的祝福

埃马努埃莱


fer*_*cho 5

您可以使用regexp_substr()。例:

create or replace type splitTable_Type is table of varchar2(100);

declare
    l_split_table splitTable_Type;
begin
  select
      regexp_substr('SMITH,ALLEN,WARD,JONES','[^,]+', 1, level)
  bulk collect into
      l_split_table
  from dual
  connect by
      regexp_substr('SMITH,ALLEN,WARD,JONES', '[^,]+', 1, level) is not null;
end;
Run Code Online (Sandbox Code Playgroud)

该查询遍历逗号分隔的字符串,搜索逗号(,),然后通过将逗号视为定界符来分割字符串。每当遇到定界符时,它就将字符串作为一行返回。

level在声明regexp_substr('SMITH,ALLEN,WARD,JONES','[^,]+', 1, level)是指在Oracle中虚列其在分层查询用来识别数字格式的层级:水平CONNECT BY