sql >> Base de Datos >  >> RDS >> Oracle

lista para vincular variable en SQL Developer

El problema es que dbms_utility.comma_to_table procedimiento requiere que los elementos de la lista sean identificadores de Oracle válidos, aunque en realidad eso no está claro en los documentos. Este artículo de AskTom sin embargo, se refiere a él a través del subyacente name_tokenize procedimiento :

No tiene que ver con el enlace o SQL Developer, es una restricción de la base de datos.

Puede ver el mismo tipo de error si llama a dbms_utility.comma_to_table procedimiento directamente:

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

O llamando a dbms_utility.name_tokenize directamente:

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"

No puede usar esto si sus valores separados por comas son palabras reservadas o no están permitidos como identificadores por alguna otra razón; comenzando con un número, por ejemplo. Obtendría el mismo problema si la lista contuviera TABLE o 42TAB . Esto no es realmente para lo que está destinado, como menciona Tom.

Puede eludir parcialmente las restricciones forzando que todos los elementos estén entre comillas dobles, lo que podría hacer con un replace . y luego se permite cualquiera de esos ejemplos:

declare
  arr dbms_utility.uncl_array;
  len binary_integer;
begin
  dbms_utility.comma_to_table('"USER","TABLE","42TAB"', len, arr);
end;
/

anonymous block completed

Entonces, para su código, modifique iv_raw a medida que lo pasa, y luego elimine las comillas dobles de cada valor devuelto:

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;

Entonces esto funciona:

select * from table(ui_util.comma_to_table('USER,TABLE,42T'));

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

Pero aún está restringido a que cada elemento tenga 30 caracteres o menos, ya que eso es una restricción incluso en los identificadores citados.