問題是dbms_utility.comma_to_table
procedure要求列表中的元素是有效的Oracle標識符,儘管這在文檔中並沒有明確說明。 This AskTom article是指它雖然,通過底層name_tokenize
procedure:
注意,您不必使用真實對象的名稱(這些表和 程序不必存在),但你必須使用有效的對象 標識符。如果您不使用有效的對象標識符,則NAME_TOKENIZE將引發錯誤。
這不是綁定或SQL Developer,它是一個數據庫限制。
你可以看到相同類型的錯誤,如果你調用dbms_utility.comma_to_table
程序直接:
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
或者通過直接調用dbms_utility.name_tokenize
:
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"
你不能,如果你的逗號使用分開的值是reserved words或由於某些其他原因不允許作爲標識符;例如,以數字開頭。如果列表中包含TABLE
或42TAB
,則會出現同樣的問題。正如湯姆提到的,這並不是真正意圖的目的。
您可以通過強制所有元素被雙引號來部分解決限制,您可以使用replace
來做到這一點。然後所有的這些例子被允許:
declare
arr dbms_utility.uncl_array;
len binary_integer;
begin
dbms_utility.comma_to_table('"USER","TABLE","42TAB"', len, arr);
end;
/
anonymous block completed
因此,對於你的代碼,修改iv_raw
當你經過它跨越,然後從每個刪除雙引號返回值:
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;
那麼這工作原理:
select * from table(ui_util.comma_to_table('USER,TABLE,42T'));
COLUMN_VALUE
--------------------
USER
TABLE
42T
但你仍然受限於每一個元素是30個字符以內,因爲這是在偶數帶引號的標識符的限制。
什麼類型是返回'bind_tab_typ'? –