Oracle
 sql >> Datenbank >  >> RDS >> Oracle

ORA-22922 (nicht vorhandener LOB-Wert) oder überhaupt kein Ergebnis mit wm_concat() erhalten

Glücklicherweise funktioniert es mit dem listagg( ... ) Funktion seit 11.2 bereitgestellt (wir laufen schon weiter), also mussten wir nicht weiter nachforschen:

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

(Wobei wm_concat(...) ist, wie man wissen sollte, eine interne und offiziell nicht unterstützte Funktion.)

eine ziemlich nette Lösung (weil es nicht so aufgebläht ist) um den distinct zu implementieren Die Funktionalität erfolgt über die selbstreferenzierende Regexp-Funktionalität was in vielen Fällen funktionieren sollte:

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

(Vielleicht/Hoffentlich sehen wir einige funktionierende listagg( distinct abc ) Funktionalität in der Zukunft, die sehr ordentlich und cool wäre wie wm_concat Syntax. Z.B. mit Postgres' string_agg( distinct abc ) ist das schon lange kein Problem mehr )

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

Wenn die Liste 4000 Zeichen überschreitet , man kann listagg nicht verwenden mehr (ORA-22922 wieder).Aber zum Glück können wir den xmlagg verwenden Funktion hier (wie hier erwähnt). ).Wenn Sie einen distinct realisieren möchten bei einem 4000 Zeichen abgeschnittenen Ergebnis hier könnten Sie den (1) auskommentieren -markierte Linien .

-- 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