Oracle
 sql >> Base de données >  >> RDS >> Oracle

liste pour lier la variable dans SQL Developer

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.