2012-02-23 20 views
13

listagg to funkcja wprowadzona w Oracle 11.2! teraz ta funkcja jest podsłuch nam przeznaczyć jesteśmy migracji z MySQL do Oracle i mamy to zapytanie:alternatywa dla listagg w Oracle?

SELECT 
    p_id, 
    MAX(registered) AS registered, 
    listagg(MESSAGE, ' ') within GROUP (ORDER BY registered) AS MESSAGE 
    FROM 
    umm_parent_id_remarks_v m 
    GROUP BY 
    m.p_id; 

to działa dobrze w MySQL ile wiemy co gryzie nas jest pod Oracle zwraca VARCAR i nie CLOB, jak potrzebujemy! tekst jest ogromny i potrzebujemy go, aby być CLOB!

Oto, co próbowałem zrobić!

utwórz tabelę CLOB_T typu CLOB!

następnie utworzyć funkcję

create or replace 
function listaggclob (t in clob_t) 
    return clob 
as 
    ret clob := ''; 
    i number; 
begin 
    i := t.first; 
    while i is not null loop 
    if ret is not null then 
     ret := ret || ' '; 
    end if; 
    ret := ret || t(i); 
    i := t.next(i); 
    end loop; 
    return ret; 
end; 

teraz jeśli uruchomię go:

SELECT 
     p_id, 
     MAX(registered) AS registered, 
     listaggclob(cast(collect (MESSAGE) as clob_t)) MESSAGE 
     FROM 
     umm_parent_id_remarks_v m 
     GROUP BY 
     m.p_id; 

uzyskać

ORA-22814: atrybut lub wartość elementu jest większa niż określona w rodzaju

Czy istnieje jakieś rozwiązanie dla niego?

dziękuje

Odpowiedz

14
+1

+1 dzięki za link do zbierania! – tbone

+0

Napisałem własną funkcję i zaktualizowałem swoje pytanie, ponownie przejrzyj moje pytanie, dziękuję –

+0

Nie wiem, dlaczego otrzymujesz ten błąd - prawdopodobnie warto go opublikować jako nowe pytanie, ale dostaniesz więcej osób patrząc na to w ten sposób. –

2

Możesz chcieć spojrzeć na user-defined aggregate functions.

Dostępne są różne techniki agregacji ciągów znaków: here. Zawierają przykład dla zdefiniowanych przez użytkownika funkcji agregujących.

+0

Dobry zestaw opcji tam. Czy są jakieś informacje, które są szybsze? –

+0

Nie mam żadnych informacji o wydajności. Sądzę, że zależy to głównie od ogólnego planu wykonania i od tego, jak pasują do tego planu wykonania. Więc może się różnić od zapytania do zapytania. – Codo

2

można rozwiązać ten błąd ORA-22814 za pomocą MULTISET zamiast COLLECT:

SELECT 
    p_id, 
    MAX(registered) AS registered, 
    listaggclob(cast(multiset(
     select MESSAGE 
     from umm_parent_id_remarks_v 
     where umm_parent_id_remarks_v.p_id = m.p_id 
    ) as clob_t)) MESSAGE 
    FROM 
    umm_parent_id_remarks_v m 
    GROUP BY 
    m.p_id; 
2

WM_CONCAT pracował dla mnie.

SELECT replace(WMSYS.WM_CONCAT(myTable.name), ',', ';') 
FROM myTable 
GROUP BY myTable.id 

Zawinąłem ją z „zmiana” określenie innego separatora produkt („”) z tego używanego WM_CONCAT („”).

+2

Należy zauważyć, że WM_CONCAT nie jest dostępny w wersjach 12c, Express Edition i żadnej bazie danych, w której nie jest zainstalowany program Workspace Manager. –

+1

nie jest to obecnie obsługiwane ani dokumentowane –

1

Zastosowanie xmlAgg, przykład znajduje się poniżej:

SELECT RTRIM(XMLAGG(XMLELEMENT(E,colname,',').EXTRACT('//text()') ORDER BY colname).GetClobVal(),',') AS LIST 
FROM tablename; 

ten powróci wartość Clob a więc nie ma potrzeby, aby utworzyć funkcję niestandardową.

0

- Tworzenie Clobe Typ - utworzyć lub zamienić typu "MSCONCATIMPL_CLOB" jako przedmiot ( resultstring CLOB ogranicznik VARCHAR2 (10),

STATIC FUNCTION odciaggregateinitialize (io_srccontext IN OUT msconcatimpl_clob) RETURN NUMBER, 

MEMBER FUNCTION odciaggregateiterate (
    self IN OUT msconcatimpl_clob, 
    value IN CLOB 
) RETURN NUMBER, 

MEMBER FUNCTION odciaggregateterminate (
    self   IN msconcatimpl_clob, 
    o_returnvalue OUT CLOB, 
    i_flags   IN NUMBER 
) RETURN NUMBER, 

MEMBER FUNCTION odciaggregatemerge (
    self IN OUT msconcatimpl_clob, 
    i_ctx2 IN msconcatimpl_clob 
) RETURN NUMBER 

); / - Tworzenie Clobe Typ nadwozia -

utworzyć lub zamienić karoseria "MSCONCATIMPL_CLOB" IS funkcji statycznych odciaggregateinitialize (io_srccontext IN OUT msconcatimpl_clob) RETURN NUMER JEST BEGIN io_srccontext: = msconcatimpl_clob ( NULL, NULL ); io_srccontext.delimiter: = ''; POWRÓT odciconst.success; END odciaggregateinitialize;

MEMBER FUNCTION odciaggregateiterate (
    self IN OUT msconcatimpl_clob, 
    value IN CLOB 
) RETURN NUMBER 
    IS 
BEGIN 
    IF 
     value IS NOT NULL 
    THEN 
     IF 
      self.resultstring IS NULL 
     THEN 
      self.resultstring := self.resultstring || value; 
     ELSE 
      self.resultstring := self.resultstring 
      || self.delimiter 
      || value; 
     END IF; 
    END IF; 

    RETURN odciconst.success; 
END odciaggregateiterate; 

MEMBER FUNCTION odciaggregateterminate (
    self   IN msconcatimpl_clob, 
    o_returnvalue OUT CLOB, 
    i_flags   IN NUMBER 
) RETURN NUMBER 
    IS 
BEGIN 
    o_returnvalue := self.resultstring; 
    RETURN odciconst.success; 
END odciaggregateterminate; 

MEMBER FUNCTION odciaggregatemerge (
    self IN OUT msconcatimpl_clob, 
    i_ctx2 IN msconcatimpl_clob 
) RETURN NUMBER 
    IS 
BEGIN 
    IF 
      self.resultstring IS NULL 
     AND 
      i_ctx2.resultstring IS NOT NULL 
    THEN 
     self.resultstring := i_ctx2.resultstring; 
    ELSIF 
     self.resultstring IS NOT NULL 
    AND 
     i_ctx2.resultstring IS NOT NULL 
    THEN 
     self.resultstring := self.resultstring 
     || self.delimiter 
     || i_ctx2.resultstring; 
    END IF; 

    RETURN odciconst.success; 
END odciaggregatemerge; 

KONIEC; /

- Tworzenie Clobe Funkcja -

utworzyć lub zamienić ms_concat_clob funkcyjnych (wejściowe varchar2) zwracają CLOB PARALLEL_ENABLE zbiorczymi msconcatimpl_clob; /