Le problème est que dbms_utility.comma_to_table
procédure
exige que les éléments de la liste soient des identifiants Oracle valides, bien que cela ne soit pas vraiment précisé dans la documentation. Cet article AskTom
s'y réfère cependant, via le sous-jacent name_tokenize
procédure
:
Cela n'a rien à voir avec la liaison ou SQL Developer, c'est une restriction de base de données.
Vous pouvez voir le même type d'erreur si vous appelez le dbms_utility.comma_to_table
procédure directement :
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
Ou en appelant dbms_utility.name_tokenize
directement :
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"
Vous ne pouvez pas l'utiliser si vos valeurs séparées par des virgules sont mots réservés
ou ne sont pas autorisés comme identifiants pour une autre raison ; commençant par un chiffre, par exemple. Vous auriez le même problème si la liste contenait TABLE
ou 42TAB
. Ce n'est pas vraiment ce à quoi il est destiné, comme le mentionne Tom.
Vous pouvez partiellement contourner les restrictions en forçant tous les éléments à être entre guillemets, ce que vous pourriez faire avec un replace
. puis n'importe lequel de ces exemples est autorisé :
declare
arr dbms_utility.uncl_array;
len binary_integer;
begin
dbms_utility.comma_to_table('"USER","TABLE","42TAB"', len, arr);
end;
/
anonymous block completed
Donc pour votre code, modifiez iv_raw
au fur et à mesure que vous le transmettez, puis supprimez les guillemets doubles de chaque valeur renvoyée :
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;
Alors ça marche :
select * from table(ui_util.comma_to_table('USER,TABLE,42T'));
COLUMN_VALUE
--------------------
USER
TABLE
42T
Mais vous êtes toujours limité à chaque élément comportant 30 caractères ou moins, car il s'agit d'une restriction sur les identifiants même entre guillemets.