Problemet er, at dbms_utility.comma_to_table
procedure
kræver, at listens elementer er gyldige Oracle-identifikatorer, selvom det egentlig ikke er tydeliggjort i dokumenterne. Denne AskTom-artikel
henviser dog til det via den underliggende >name_tokenize
procedure
:
Det har ikke at gøre med bindingen eller SQL-udvikleren, det er en databaserestriktion.
Du kan se den samme type fejl, hvis du kalder dbms_utility.comma_to_table
procedure direkte:
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
Eller ved at kalde dbms_utility.name_tokenize
direkte:
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"
Du kan ikke bruge dette, hvis dine kommaseparerede værdier er reserverede ord
eller er ikke tilladt som identifikatorer af en eller anden grund; begyndende med et tal, for eksempel. Du ville få det samme problem, hvis listen indeholdt TABLE
eller 42TAB
. Det er egentlig ikke det, den er beregnet til, som Tom nævner.
Du kan delvist omgå begrænsningerne ved at tvinge alle elementer til at blive citeret i dobbelte citater, hvilket du kunne gøre med en replace
. og så er alle disse eksempler tilladt:
declare
arr dbms_utility.uncl_array;
len binary_integer;
begin
dbms_utility.comma_to_table('"USER","TABLE","42TAB"', len, arr);
end;
/
anonymous block completed
Så for din kode skal du ændre iv_raw
efterhånden som du sender det videre, og fjern derefter de dobbelte anførselstegn fra hver returnerede værdi:
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;
Så virker dette:
select * from table(ui_util.comma_to_table('USER,TABLE,42T'));
COLUMN_VALUE
--------------------
USER
TABLE
42T
Men du er stadig begrænset til, at hvert element må være på 30 tegn eller mindre, da det er en begrænsning for selv citerede identifikatorer.