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

Obtener ORA-22922 (valor LOB inexistente) o ningún resultado con wm_concat()

Afortunadamente, funciona con listagg( ... ) función proporcionada desde 11.2 (ya estamos funcionando), por lo que no tuvimos que investigar más:

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

(Donde wm_concat(...) es, como uno debe saber, alguna función interna y oficialmente sin respaldo.)

una solución bastante agradable (porque no está tan inflado) para implementar el distinct la funcionalidad es a través de la funcionalidad de expresiones regulares autorreferenciadas que debería funcionar en muchos casos:

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

(Tal vez/Ojalá veamos algunos listagg( distinct abc ) que funcionen funcionalidad en el futuro, que sería muy ordenada y genial como wm_concat sintaxis. P.ej. esto no es un problema desde hace mucho tiempo con string_agg( distinct abc ) de Postgres )

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

Si la lista supera los 4000 caracteres , uno no puede usar listagg más (ORA-22922 otra vez). Pero afortunadamente podemos usar el xmlagg función aquí (como se menciona aquí ). Si desea realizar un distinct en un resultado truncado de 4000 caracteres aquí, podrías superar en comentario el (1) -líneas 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