Il problema è che dbms_utility.comma_to_table
procedura
richiede che gli elementi dell'elenco siano identificatori Oracle validi, sebbene ciò non sia davvero chiarito nei documenti. Questo articolo di AskTom
si riferisce ad esso, tuttavia, tramite il sottostante name_tokenize
procedura
:
Non ha a che fare con l'associazione o lo sviluppatore SQL, è una restrizione del database.
Puoi vedere lo stesso tipo di errore se chiami dbms_utility.comma_to_table
procedura direttamente:
declare
arr dbms_utility.uncl_array;
len binary_integer;
begin
dbms_utility.comma_to_table('USER', len, arr);
end;
/
Error report -
ORA-20001: comma-separated list invalid near R
ORA-06512: at "SYS.DBMS_UTILITY", line 236
ORA-06512: at "SYS.DBMS_UTILITY", line 256
ORA-06512: at line 5
Oppure chiamando dbms_utility.name_tokenize
direttamente:
declare
a varchar2(30);
b varchar2(30);
c varchar2(30);
d varchar2(30);
e binary_integer;
begin
dbms_utility.name_tokenize('USER', a, b, c, d, e);
end;
/
Error report -
ORA-00931: missing identifier
ORA-06512: at "SYS.DBMS_UTILITY", line 167
ORA-06512: at line 8
00931. 00000 - "missing identifier"
Non puoi usarlo se i tuoi valori separati da virgole sono parole riservate
o non sono consentiti come identificatori per qualche altro motivo; iniziando con un numero, per esempio. Avresti lo stesso problema se l'elenco contenesse TABLE
o 42TAB
. Non è esattamente ciò a cui è destinato, come dice Tom.
Puoi aggirare parzialmente le restrizioni forzando tutti gli elementi a essere doppiamente virgolettati, cosa che potresti fare con una replace
. e quindi è consentito uno qualsiasi di questi esempi:
declare
arr dbms_utility.uncl_array;
len binary_integer;
begin
dbms_utility.comma_to_table('"USER","TABLE","42TAB"', len, arr);
end;
/
anonymous block completed
Quindi, per il tuo codice, modifica iv_raw
mentre lo passi, quindi rimuovi le virgolette da ogni valore restituito:
FUNCTION comma_to_table(iv_raw IN VARCHAR2)
RETURN bind_tab_typ
PIPELINED
IS
ltab_lname dbms_utility.lname_array;
ln_len BINARY_INTEGER;
BEGIN
dbms_utility.comma_to_table(list => '"' || replace(iv_raw, ',', '","') || '"'
,tablen => ln_len
,tab => ltab_lname);
FOR i IN 1 .. ln_len LOOP
PIPE ROW (replace(ltab_lname(i), '"'));
END LOOP;
END comma_to_table;
Allora funziona:
select * from table(ui_util.comma_to_table('USER,TABLE,42T'));
COLUMN_VALUE
--------------------
USER
TABLE
42T
Ma sei ancora limitato a ogni elemento di 30 caratteri o meno, poiché si tratta di una restrizione anche sugli identificatori tra virgolette.