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

Ottenere ORA-22922 (valore LOB inesistente) o nessun risultato con wm_concat()

Fortunatamente, funziona con listagg( ... ) funzione fornita da 11.2 (stiamo già correndo), quindi non abbiamo dovuto indagare ulteriormente:

listagg( abc, ',' ) within group ( order by abc )

(Dove wm_concat(...) è, come si dovrebbe sapere, una funzione interna e ufficialmente non supportata.)

una soluzione piuttosto interessante (perché non è così gonfio) implementare il distinct la funzionalità avviene tramite la funzionalità regexp autoreferenziale che dovrebbe funzionare in molti casi:

regexp_replace( 
  listagg( abc, ',' ) within group ( order by abc )
, '(^|,)(.+)(,\2)+', '\1\2' )

(Forse/speriamo di vedere alcuni listagg( distinct abc ) funzionanti funzionalità in futuro, che sarebbe molto carina e interessante come wm_concat sintassi. Per esempio. questo non è un problema da molto tempo con string_agg( distinct abc ) di Postgres )

-- 1: postgres sql example:
select string_agg( distinct x, ',' ) from unnest('{a,b,a}'::text[]) as x`

Se l'elenco supera i 4000 caratteri , uno non può utilizzare listagg più (ORA-22922 di nuovo). Ma fortunatamente possiamo usare xmlagg funzione qui (come menzionato qui ).Se vuoi realizzare un distinct su un risultato troncato di 4000 caratteri qui, potresti commentare il (1) -linee segnate .

-- in smallercase everything that could/should be special for your query
-- comment in (1) to realize a distinct on a 4000 chars truncated result
WITH cfg AS ( 
  SELECT 
    ','                  AS list_delim,
    '([^,]+)(,\1)*(,|$)' AS list_dist_match,  -- regexp match for distinct functionality
    '\1\3'               AS LIST_DIST_REPL  -- regexp replace for distinct functionality
  FROM DUAL
)
SELECT
  --REGEXP_REPLACE( DBMS_LOB.SUBSTR(             -- (1)
  RTRIM( XMLAGG( XMLELEMENT( E, mycol, listdelim ).EXTRACT('//text()') 
  ORDER BY mycol ).GetClobVal(), LIST_DELIM ) 
  --, 4000 ), LIST_DIST_MATCH, LIST_DIST_REPL )  -- (1)
  AS mylist
FROM mytab, CFG