=====Oracle PL/SQL Tokenizer - Strings zerlegen =====
**Aufgabe:** Ein Liste soll wieder in einzelne Werte zerlegt werden
Um solch einen String zu erzeugen => siehe auch [[prog:sql_liste_erstellen|Ein Listen von Werten in SQL erstellen]]
----
====APEX_UTIL.STRING_TO_TABLE====
Alternativ in Apex die Methode:
DECLARE
v_selected APEX_APPLICATION_GLOBAL.VC_ARR2;
BEGIN
--
-- Convert the colon separated string of values into
-- a PL/SQL array
v_selected := APEX_UTIL.STRING_TO_TABLE(:P100_PRODUCTLIST);
--
-- Loop over array to insert department numbers and sysdate
--
FOR i IN 1..v_selected.count
LOOP
dbms_output.put_line(v_selected(i));
END LOOP;
END;
----
==== in PL/SQL eine Liste wieder zerlegen mit DBMS_UTILITY ====
Mit Hilfe von **dbms_utility.comma_to_table** lässt sich eine Liste in ein Array transformieren.
Beispiel:
declare
v_values DBMS_UTILITY.lname_array;
v_tabLength BINARY_INTEGER;
-- not working
v_list varchar2(255):=replace('0100:26941:0:0',':',',');
-- working
-- v_list varchar2(255):=replace('a:b:c:d',':',',');
BEGIN
dbms_output.put_line(v_list);
DBMS_UTILITY.COMMA_TO_TABLE( list => v_list
, tablen => v_tabLength
, tab => v_values
);
if v_tabLength=4 then
dbms_output.put_line('INST_KEY :='|| v_values(1));
dbms_output.put_line('KONTONUMMER :='|| v_values(2));
dbms_output.put_line('KONTO_SUBNUMMER :='|| v_values(3));
dbms_output.put_line('LIMITSEQUENZ :='|| v_values(4));
else
raise_application_error( -20020, 'Konto Key has not enough values ::' || v_list);
end if;
END;
siehe auch: http://docs.oracle.com/cd/E11882_01/timesten.112/e21645/d_util.htm#i1002468
== BUG - Falls String nur aus Zahlen wie "1,2,3,5" besteht ==
In meiner 12c Umgebung erhalten ich allerdings den folgenden Fehler wenn der String aus Zahlen besteht:
ERROR at line 1:
ORA-20001: comma-separated list invalid near #
ORA-06512: at "SYS.DBMS_UTILITY", line 236
ORA-06512: at "SYS.DBMS_UTILITY", line 272
ORA-06512: at line 16
Daher meine eigene Routine erstellt, da mir gerade die Apex Methode nicht mehr einfällt ...
----
==== PL/SQL Routine zum Zerlegen eines Strings ====
Seperator kann eine beliebige Zeichenkette sein.
create or replace PACKAGE GPI_APEX_UTILS AS
-- =====================
type splitResultTab IS TABLE OF VARCHAR2(2000) INDEX BY BINARY_INTEGER;
-- =====================
-- split a string
-- =====================
function splitString( p_string varchar2
, p_seperator varchar2)
return splitResultTab;
-- =====================
-- test the function
--- =====================
procedure testsplitString( p_string varchar2
, p_seperator varchar2);
END GPI_APEX_UTILS;
/
create or replace PACKAGE body GPI_APEX_UTILS
-- =====================
-- split a string
-- =====================
function splitString ( p_string varchar2
, p_seperator varchar2)
return splitResultTab
is
v_returnTab splitResultTab;
v_token_count pls_integer;
v_tocken varchar2(2000);
v_string varchar2(32000);
v_pos1 pls_integer;
v_sep_length pls_integer;
begin
-- get the count of the tocken (count sperator + one )
v_token_count:= REGEXP_COUNT(p_string,p_seperator)+1;
v_sep_length:=length(p_seperator);
if v_token_count=1 then
raise_application_error( -20020, ' seperator Char not exist in string to split - p_seperator:=' || p_seperator );
end if;
-- add at the end on seperator sign as end signal for the loop!
v_string:=p_string||p_seperator;
-- loop of the result string
-- in each round cut off the tocken at the begin of the string
for i in 1 .. v_token_count
loop
-- find the first delimiter in the string
v_pos1 :=instr(v_string,p_seperator);
-- get the tocken
v_tocken:=substr(v_string,1,v_pos1-1);
v_returnTab(i):=v_tocken;
-- cut the read tocken from the string
v_string:=substr(v_string,v_pos1+v_sep_length,length(v_string));
end loop;
return v_returnTab;
end splitString;
-- =====================
-- test the function
--- =====================
procedure testsplitString( p_string varchar2
, p_seperator varchar2)
is
v_resTab splitResultTab;
begin
v_resTab:=splitString(p_string=> p_string, p_seperator => p_seperator);
FOR i IN v_resTab.FIRST .. v_resTab.LAST
LOOP
-- ausgeben
IF v_resTab.EXISTS(i)
THEN
DBMS_OUTPUT.put_line('element #' || i || ' = ' || v_resTab(i));
END IF;
END LOOP;
end;
END GPI_APEX_UTILS;
Testen:
sqlplus gpi/gpi
exec GPI_APEX_UTILS.testsplitString('0100::26941::0::0','::')
element #1 = 0100
element #2 = 26941
element #3 = 0
element #4 = 0
----
==== RegEx Lösungen ====
* http://stackoverflow.com/questions/31654411/split-string-by-space-and-character-as-delimiter-in-oracle-with-regexp-substr
* https://blogs.oracle.com/aramamoo/entry/how_to_split_comma_separated_string_and_pass_to_in_clause_of_select_statement
----
==== Quellen ====
Mehr => [[prog:plsql_code_pices|PL/SQL - Code Beispiele]]