It seems that the LISTAGG function doesn't work with UDT, how can i overcome this problem ?
First, have a look at my sql :
create or replace type objtype as object(
id int,
col1 varchar2(30),
col2 float
);
create table myTab(
col1 objtype
);
insert into myTab values (objtype(1,'col1',10));
insert into myTab values (objtype(2,'col2',20));
insert into myTab values (objtype(3,'col3',3000));
select listagg(t.col1,', ') within group (order by 1) from myTab t;
What i want is to show every element of the table in one row, like this :
objtype(1,'col1',10) , objtype(2,'col2',20), objtype(3,'col3',3000)
But instead i get this error :
Rapport d'erreur -
Erreur SQL : ORA-00932: inconsistent datatypes: expected NUMBER got USER.OBJTYPE
- 00000 - "inconsistent datatypes: expected %s got %s"
Should i use another function ? what is it then ?
Thanks for your response.
1) Add function to produce "text" representation of object.
create or replace type objtype as object(
id int,
col1 varchar2(30),
col2 float,
member function toStr return varchar2
);
create or replace type body objtype is
member function toStr return varchar2 is
begin
return 'objtype('||self.id||','||col1||','||col2||')';
end;
end;
select listagg(t.col1.toStr(),', ') within group (order by 1) from myTab t;
2) Create User-defined Aggregates - complicated and powerful
ImpAggr is implementing custom aggregation mechanism.
create or replace type ImpAggr as object(
list_of_object varchar2(32000), -- second highest value seen so far
static function ODCIAggregateInitialize(sctx IN OUT ImpAggr)
return number,
member function ODCIAggregateIterate(self IN OUT ImpAggr,
value IN objtype) return number,
member function ODCIAggregateTerminate(self IN ImpAggr,
returnValue OUT varchar2, flags IN number) return number,
member function ODCIAggregateMerge(self IN OUT ImpAggr,
ctx2 IN ImpAggr) return number
);
/
create or replace type body ImpAggr is
static function ODCIAggregateInitialize(sctx IN OUT ImpAggr)
return number is
begin
-- Aggregate Initialize
sctx := ImpAggr(null);
return ODCIConst.Success;
end;
member function ODCIAggregateIterate(self IN OUT ImpAggr, value IN objtype) return number is
begin
-- Aggregate Iterate
self.list_of_object :=list_of_object || ',objtype('||value.id||','||value.col1||','||value.col2||')';
return ODCIConst.Success;
end;
member function ODCIAggregateTerminate(self IN ImpAggr,
returnValue OUT varchar2, flags IN number) return number is
begin
-- retrun result list_of_object.
returnValue := self.list_of_object;
return ODCIConst.Success;
end;
member function ODCIAggregateMerge(self IN OUT ImpAggr, ctx2 IN ImpAggr) return number is
begin
-- merge content only if aggregation process gone in parallel execution
self.list_of_object := ','||ctx2.list_of_object;
return ODCIConst.Success;
end;
end;
/
Create aggregation function.
CREATE FUNCTION CustomAggregation (input objtype) RETURN varchar2
PARALLEL_ENABLE AGGREGATE USING ImpAggr;
And usage.
select CustomAggregation(t.col1) from myTab t;