El problema es que dbms_utility.comma_to_table
procedimiento
requiere que los elementos de la lista sean identificadores de Oracle válidos, aunque en realidad eso no está claro en los documentos. Este artículo de AskTom
sin embargo, se refiere a él a través del subyacente name_tokenize
procedimiento
:
No tiene que ver con el enlace o SQL Developer, es una restricción de la base de datos.
Puede ver el mismo tipo de error si llama a dbms_utility.comma_to_table
procedimiento directamente:
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
O llamando a dbms_utility.name_tokenize
directamente:
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"
No puede usar esto si sus valores separados por comas son palabras reservadas
o no están permitidos como identificadores por alguna otra razón; comenzando con un número, por ejemplo. Obtendría el mismo problema si la lista contuviera TABLE
o 42TAB
. Esto no es realmente para lo que está destinado, como menciona Tom.
Puede eludir parcialmente las restricciones forzando que todos los elementos estén entre comillas dobles, lo que podría hacer con un replace
. y luego se permite cualquiera de esos ejemplos:
declare
arr dbms_utility.uncl_array;
len binary_integer;
begin
dbms_utility.comma_to_table('"USER","TABLE","42TAB"', len, arr);
end;
/
anonymous block completed
Entonces, para su código, modifique iv_raw
a medida que lo pasa, y luego elimine las comillas dobles de cada valor devuelto:
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;
Entonces esto funciona:
select * from table(ui_util.comma_to_table('USER,TABLE,42T'));
COLUMN_VALUE
--------------------
USER
TABLE
42T
Pero aún está restringido a que cada elemento tenga 30 caracteres o menos, ya que eso es una restricción incluso en los identificadores citados.