The problem is that the dbms_utility.comma_to_table procedure requires the elements of the list to be valid Oracle identifiers, though that isn't made clear in the docs really. This AskTom article refers to it though, via the underlying name_tokenize procedure:
Note that you do not have to use REAL object names (these tables and
procedures do not have to exist) but you must use VALID object
identifiers. If you do not use a valid object identifier,
NAME_TOKENIZE will raise an error.
It isn't to do with the binding or SQL Developer, it's a database restriction.
You can see the same kind of error if you call the dbms_utility.comma_to_table procedure directly:
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
Or by calling dbms_utility.name_tokenize directly:
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"
You can't use this if your comma-separated values are reserved words or aren't allowed as identifiers for some other reason; starting with a number, for example. You'd get the same issue if the list contained TABLE or 42TAB. This isn't really what it is intended for, as Tom mentions.
You can partially get around the restrictions by forcing all the elements to be double-quoted, which you could do with a replace. and then any of those examples are allowed:
declare
arr dbms_utility.uncl_array;
len binary_integer;
begin
dbms_utility.comma_to_table('"USER","TABLE","42TAB"', len, arr);
end;
/
anonymous block completed
So for your code, modify iv_raw as you pass it across, and then remove the double-quotes from each returned value:
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;
Then this works:
select * from table(ui_util.comma_to_table('USER,TABLE,42T'));
COLUMN_VALUE
--------------------
USER
TABLE
42T
But you're still restricted to each element being 30 characters or less, since that is a restriction on even quoted identifiers.