Problem polega na tym, że dbms_utility.comma_to_table
procedura
wymaga, aby elementy listy były prawidłowymi identyfikatorami Oracle, chociaż tak naprawdę nie jest to wyjaśnione w dokumentacji. Ten artykuł AskTom
odnosi się do niego jednak, za pośrednictwem podstawowego name_tokenize
procedura
:
Nie ma to nic wspólnego z wiązaniem lub SQL Developerem, to ograniczenie bazy danych.
Możesz zobaczyć ten sam rodzaj błędu, jeśli wywołasz dbms_utility.comma_to_table
procedura bezpośrednio:
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
Lub dzwoniąc do dbms_utility.name_tokenize
bezpośrednio:
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"
Nie możesz tego użyć, jeśli Twoje wartości oddzielone przecinkami to słowa zastrzeżone
lub nie są dozwolone jako identyfikatory z innego powodu; na przykład zaczynając od numeru. Otrzymasz ten sam problem, jeśli lista zawiera TABLE
lub 42TAB
. To nie jest to, do czego jest przeznaczony, jak wspomina Tom.
Możesz częściowo obejść ograniczenia, zmuszając wszystkie elementy do podwójnego cudzysłowu, co możesz zrobić za pomocą replace
. a następnie dowolny z tych przykładów jest dozwolony:
declare
arr dbms_utility.uncl_array;
len binary_integer;
begin
dbms_utility.comma_to_table('"USER","TABLE","42TAB"', len, arr);
end;
/
anonymous block completed
Więc dla swojego kodu zmodyfikuj iv_raw
w miarę jej przekazywania, a następnie usuwaj podwójne cudzysłowy z każdej zwracanej wartości:
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;
Wtedy to działa:
select * from table(ui_util.comma_to_table('USER,TABLE,42T'));
COLUMN_VALUE
--------------------
USER
TABLE
42T
Ale nadal jesteś ograniczony do tego, że każdy element ma 30 znaków lub mniej, ponieważ jest to ograniczenie nawet dla identyfikatorów cytowanych.