Oracle
 sql >> Base de Dados >  >> RDS >> Oracle

list para vincular a variável no SQL Developer


O problema é que o dbms_utility.comma_to_table procedimento requer que os elementos da lista sejam identificadores válidos do Oracle, embora isso não esteja claro nos documentos. Este artigo do AskTom refere-se a ele, porém, por meio do name_tokenize procedimento :

Não tem a ver com a vinculação ou SQL Developer, é uma restrição de banco de dados.

Você pode ver o mesmo tipo de erro se chamar o dbms_utility.comma_to_table procedimento diretamente:
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 chamando dbms_utility.name_tokenize diretamente:
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"

Você não pode usar isso se seus valores separados por vírgula forem palavras reservadas ou não são permitidos como identificadores por algum outro motivo; começando com um número, por exemplo. Você teria o mesmo problema se a lista contivesse TABLE ou 42TAB . Isso não é realmente o que se destina, como Tom menciona.

Você pode contornar parcialmente as restrições forçando todos os elementos a serem aspas duplas, o que você pode fazer com um replace . e, em seguida, qualquer um desses exemplos é permitido:
declare
  arr dbms_utility.uncl_array;
  len binary_integer;
begin
  dbms_utility.comma_to_table('"USER","TABLE","42TAB"', len, arr);
end;
/

anonymous block completed

Então, para o seu código, modifique iv_raw conforme você o passa e, em seguida, remova as aspas duplas de cada valor retornado:
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;

Então isso funciona:
select * from table(ui_util.comma_to_table('USER,TABLE,42T'));

COLUMN_VALUE
--------------------
USER
TABLE
42T

Mas você ainda está restrito a cada elemento com 30 caracteres ou menos, já que isso é uma restrição até mesmo para identificadores entre aspas.