Kiedyś podczas pisania procedury SQL potrzebowałem funkcję, która podzieli mi tekst oddzielony przecinkami na części. Wiedziałem, że taka funkcja istnieje w MySQL ( splitstring ) ale w Oracle nie przewidzieli jej. Na własne potrzeby zacząłem poszukiwania gotowych rozwiązań ( moje własne kończyły się fiaskiem ). Google było bardzo pomocne i natrafiłem na stronę http://glosoli.blogspot.com/2006/07/oracle-plsql-function-to-split-strings.html
Poniżej prezentuję kod funkcji split, którą polecam:
create or replace function split (
the_list varchar2,
the_index number,
delim varchar2 :=';'
)
return varchar2
is
start_pos number;
end_pos number;
begin
if the_index = 1 then
start_pos := 1;
elsif the_index < 0 then
start_pos := instr(the_list, delim, -1, abs(the_index)) + 1;
else
start_pos := instr(the_list, delim, 1, the_index - 1);
if start_pos = 0 then
return null;
else
start_pos := start_pos + length(delim);
end if;
end if;
if the_index < 0 then
end_pos := instr(the_list, delim, start_pos+1, 1);
else
end_pos := instr(the_list, delim, start_pos, 1);
end if;
if end_pos = 0 then
return substr(the_list, start_pos);
else
return substr(the_list, start_pos, end_pos - start_pos);
end if;
end split;
Moja modyfikacja :
create or replace function split (
(
par_ciag VARCHAR2,
par_rozdzielnik VARCHAR2
) RETURN tab_tekst
PIPELINED IS
var_pozycja NUMBER;
var_ciag VARCHAR2(32767);
tab_rezultat tab_tekst;
BEGIN
var_ciag := par_ciag;
tab_rezultat := tab_tekst();
LOOP
var_pozycja := nvl(instr(var_ciag, par_rozdzielnik), 0);
IF var_pozycja > 0
THEN
PIPE ROW(substr(var_ciag, 1, var_pozycja - 1));
var_ciag := substr(var_ciag, var_pozycja + length(par_rozdzielnik));
ELSE
PIPE ROW(var_ciag);
EXIT;
END IF;
END LOOP;
RETURN;
end split;
Dodatkowo trzeba stworzyć typ
TYPE tab_tekst IS TABLE OF VARCHAR2(4000);
Przykładowe wywołanie
SELECT t.* FROM TABLE(split('aaa;bbb', ';')) t