In questo post indicherò due semplici modi per realizzare una function StringTokenizer in PL/SQL. Un primo modo e’ quello di utilizzare le espressioni regolari usando le function REGEXP_SUBSTR e REGEXP_INSTR fornite da Oracle. Le Function REGEXP_SUBSTR e REGEXP_INSTR non sono altro che l’estensione delle rispettive function SUBSTR e INSTR di Oracle. La function STRINGTOKENIZER_REGEX, che potete vedere sotto, si comporta come la classe StringTokenizer in Java, cioè’ eliminando tutti i token che sono a NULL. Il risultato finale sara’ un DBMS_SQL.varchar2_table con tutti i token validi. Vediamo, adesso, il codice:
CREATE OR REPLACE
FUNCTION STRINGTOKENIZER_REGEX
(p_string IN LONG, p_separators IN VARCHAR2)
RETURN DBMS_SQL.varchar2_table
IS
l_token_tbl DBMS_SQL.varchar2_table;
pattern VARCHAR2(250);
param_clob CLOB;
BEGIN
param_clob := TO_CLOB(p_string);
pattern := '[^(' || p_separators || ')]+' ;
SELECT REGEXP_SUBSTR (param_clob, pattern, 1, LEVEL) token
BULK COLLECT
INTO l_token_tbl
FROM DUAL
WHERE REGEXP_SUBSTR (param_clob, pattern, 1, LEVEL) IS NOT NULL
CONNECT BY REGEXP_INSTR (param_clob, pattern, 1, LEVEL) > 0;
RETURN l_token_tbl;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('STRINGTOKENIZER_REGEX - Error '||TO_CHAR(SQLCODE)||': '||SQLERRM);
dbms_output.put_line(DBMS_UTILITY.format_error_backtrace);
RAISE;
END STRINGTOKENIZER_REGEX;
/
Si può’ fare la stessa cosa, vista sopra, senza usare le espressioni regolari usando direttamente le funzioni di SUBSTR e INSTR di Oracle. In questo caso la funzione PL/SQL STRINGTOKENIZER scritta sotto restituisce sempre un DBMS_SQL.varchar2_table ma con anche i token NULL. Vediamo il codice:
CREATE OR REPLACE
FUNCTION STRINGTOKENIZER
(p_string IN LONG, p_separators IN VARCHAR2)
RETURN DBMS_SQL.varchar2_table
IS
l_token_tbl DBMS_SQL.varchar2_table;
l_start NUMBER;
l_pos NUMBER;
l_index NUMBER;
BEGIN
l_start := 1;
l_pos :=1;
l_index:=1;
WHILE TRUE LOOP
l_pos := INSTR (p_string ,p_separators ,l_start);
IF l_start > LENGTH(p_string) THEN
EXIT;
END IF;
IF l_pos = 0 THEN
l_token_tbl(l_index):=Substr(p_string ,l_start, LENGTH(p_string)+1-l_start);
EXIT;
END IF;
l_token_tbl(l_index):=Substr(p_string ,l_start, l_pos-l_start);
l_start:=l_pos+LENGTH(p_separators);
l_index:=l_index+1;
END LOOP;
RETURN l_token_tbl;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line('STRINGTOKENIZER - Error '||TO_CHAR(SQLCODE)||': '||SQLERRM);
dbms_output.put_line(DBMS_UTILITY.format_error_backtrace);
RAISE;
END STRINGTOKENIZER;
/
Scriviamo adesso uno script PL/SQL per testare le nostre function:
DECLARE
ret DBMS_SQL.VARCHAR2_TABLE;
BEGIN
-- Now call the stored program
ret := STRINGTOKENIZER('aaa|bbb|ccc|ddd|eeee|','|');
-- Output the results
IF ret IS NOT NULL THEN
IF ret.count > 0 THEN
FOR i IN ret.first..ret.last LOOP
IF ret.exists(i) THEN
null; -- type of data not known
dbms_output.put_line(SubStr('ret('||TO_CHAR(i)||') = '||ret(i),1,255));
END IF;
END LOOP;
END IF;
END IF;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(SubStr('Error '||TO_CHAR(SQLCODE)||': '||SQLERRM, 1, 255));
dbms_output.put_line(dbms_utility.format_error_backtrace);
RAISE;
END;
Il test di sopra e’ relativo alla function STRINGTOKENIZER ma e’ facilmente m. Per concludere entrambe le funzioni sembrano funzionare perfettamente. L’unica differenza come gia’ detto e’ relative ai token a NULL per quanto riguarda l’output. C’e’ pero’ un’altra differenza che e’ relativa alle performance, l’uso infatti delle espressioni regolari e’ infatti meno performante nel caso di stringhe molto lunghe da parsificare.

0 comments ↓
There are no comments yet...Kick things off by filling out the form below.
Leave a Comment