My Remarks!

the Life, the Universe and almost Everything what's Left

String Tokenizer with Oracle PL/SQL

info-14This article describes how to tokenize a string, just with plain "out of the box" Oracle SQL. In the IT we often encounter requirements to split a string in parts. With Oracle PL/SQL we have a quite elegant solution for that.

 

The solution is based on the ability of oracle to use regular expressions within a SQL statement. In the first example we have comma seperated string, containing the most important crew members of the USS Enterprise:

SELECT regexp_substr(str, '[^,]+', 1, LEVEL) AS splitted_element,
           LEVEL AS element_no
      FROM (SELECT rownum AS id, 'Kirk,Spock,Scotty,McCoy,Uhura' str FROM dual)
    CONNECT BY instr(str, ',', 1, LEVEL - 1) > 0
           AND id = PRIOR id
           AND PRIOR dbms_random.value IS NOT null;
Now, we develop this base functionality to a general function which splits a string in it's components:
create or replace package itstar_toolbox is

  type t_tab_strings is table of varchar2(1000);
  [...]
  function split_string(pi_string in varchar2, pi_delimiter in varchar2)
    return t_tab_strings is
  
    cursor c_tokenizer(ci_string in varchar2, ci_delimiter in varchar2) is
      SELECT regexp_substr(str, '[^' || ci_delimiter || ']+', 1, LEVEL) AS splitted_element,
             LEVEL AS element_no
        FROM (SELECT rownum AS id, ci_string str FROM dual)
      CONNECT BY instr(str, ci_delimiter, 1, LEVEL - 1) > 0
             AND id = PRIOR id
             AND PRIOR dbms_random.value IS NOT null;
  
    l_tab t_tab_strings := t_tab_strings();
  begin
    for c1 in c_tokenizer(pi_string, pi_delimiter) loop
      l_tab.extend;
      l_tab(l_tab.last) := c1.splitted_element;
    end loop;
  
    return l_tab;
  end;
And now even comes the icing on the cake: Pipelining Function to makes you feel like real SQL:
  function split_string_pipe(pi_string in varchar2, pi_delimiter in varchar2)
    return t_tab_strings pipelined is
    l_tab t_tab_strings;
  begin
    l_tab := split_string(pi_string, pi_delimiter);
    for i in 1..l_tab.count loop
      pipe row (l_tab(i));
    end loop;
    return;
  end;

The result is just great and elegant:

SQL> SELECT * FROM TABLE(itstar_toolbox.split_string_pipe('Kirk,Spock,Scotty,McCoy,Uhura', ',')) a;
 
COLUMN_VALUE
--------------------------------------------------------------------------------
Kirk
Spock
Scotty
McCoy
Uhura
 
SQL> 

find me on Stack Overflow