Problemet är att dbms_utility .comma_to_table
förfarande
kräver att elementen i listan är giltiga Oracle-identifierare, även om det egentligen inte framgår av dokumenten. Denna AskTom-artikel
hänvisar dock till det via den underliggande name_tokenize förfarande
:
Det har inte att göra med bindningen eller SQL-utvecklaren, det är en databasbegränsning.
Du kan se samma typ av fel om du anropar dbms_utility.comma_to_table
procedur direkt:
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 genom att anropa dbms_utility.name_tokenize
direkt:
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 inte använda detta om dina kommaseparerade värden är reserverade ord
eller är inte tillåtna som identifierare av någon annan anledning; börjar med en siffra, till exempel. Du skulle få samma problem om listan innehöll TABELL
eller 42TAB
. Det är inte riktigt vad den är avsedd för, som Tom nämner.
Du kan delvis komma runt begränsningarna genom att tvinga alla element att vara dubbla citattecken, vilket du kan göra med en ersätt
. och sedan är något av dessa exempel tillåtna:
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å för din kod, ändra iv_raw
när du skickar över det och ta sedan bort de dubbla citattecken från varje returnerat värde:
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;
Då fungerar detta:
select * from table(ui_util.comma_to_table('USER,TABLE,42T'));
COLUMN_VALUE
--------------------
USER
TABLE
42T
Men du är fortfarande begränsad till att varje element är 30 tecken eller mindre, eftersom det är en begränsning för även citerade identifierare.