Oracle
 sql >> Database >  >> RDS >> Oracle

list per associare la variabile in SQL Developer

Il problema è che dbms_utility.comma_to_table procedura richiede che gli elementi dell'elenco siano identificatori Oracle validi, sebbene ciò non sia davvero chiarito nei documenti. Questo articolo di AskTom si riferisce ad esso, tuttavia, tramite il sottostante name_tokenize procedura :

Non ha a che fare con l'associazione o lo sviluppatore SQL, è una restrizione del database.

Puoi vedere lo stesso tipo di errore se chiami dbms_utility.comma_to_table procedura direttamente:

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

Oppure chiamando dbms_utility.name_tokenize direttamente:

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"

Non puoi usarlo se i tuoi valori separati da virgole sono parole riservate o non sono consentiti come identificatori per qualche altro motivo; iniziando con un numero, per esempio. Avresti lo stesso problema se l'elenco contenesse TABLE o 42TAB . Non è esattamente ciò a cui è destinato, come dice Tom.

Puoi aggirare parzialmente le restrizioni forzando tutti gli elementi a essere doppiamente virgolettati, cosa che potresti fare con una replace . e quindi è consentito uno qualsiasi di questi esempi:

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

anonymous block completed

Quindi, per il tuo codice, modifica iv_raw mentre lo passi, quindi rimuovi le virgolette da ogni valore restituito:

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;

Allora funziona:

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

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

Ma sei ancora limitato a ogni elemento di 30 caratteri o meno, poiché si tratta di una restrizione anche sugli identificatori tra virgolette.