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

Obtendo ORA-22922 (valor LOB inexistente) ou nenhum resultado com wm_concat()


Felizmente, funciona com o listagg( ... ) função fornecida desde 11.2 (já estamos rodando), então não tivemos que investigar mais:
listagg( abc, ',' ) within group ( order by abc )

(Onde wm_concat(...) é, como se deve saber, alguma função interna e oficialmente não suportada.)

uma solução bastante interessante (porque não é tão inchado) implementar o distinct a funcionalidade é por meio da funcionalidade regexp de auto-referência que deve funcionar em muitos casos:
regexp_replace( 
  listagg( abc, ',' ) within group ( order by abc )
, '(^|,)(.+)(,\2)+', '\1\2' )

(Talvez/Esperamos ver algum listagg( distinct abc ) funcionando funcionalidade no futuro, o que seria muito legal e legal como o wm_concat sintaxe. Por exemplo. isso não é problema desde muito tempo com o string_agg( distinct abc ) do Postgres )
-- 1: postgres sql example:
select string_agg( distinct x, ',' ) from unnest('{a,b,a}'::text[]) as x`

Se a lista exceder 4.000 caracteres , um não pode usar listagg mais (ORA-22922 novamente). Mas felizmente podemos usar o xmlagg função aqui (como mencionado aqui ).Se você deseja realizar um distinct em um resultado truncado de 4.000 caracteres aqui, você pode comentar o (1) -linhas marcadas .
-- 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