如何在SQL(Oracle)中将LISTAGG与UDT一起使用?

时间:2018-12-07 18:49:47

标签: sql oracle user-defined-types listagg

似乎LISTAGG函数不能与UDT一起使用,我该如何克服这个问题?

首先,看看我的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;

我想要的是在一行中显示表格的每个元素,像这样:

objtype(1,'col1',10) , objtype(2,'col2',20), objtype(3,'col3',3000)

但是相反,我得到了这个错误:

  

dererur游乐区-

     

Erreur SQL:ORA-00932:数据类型不一致:预期的编号为USER.OBJTYPE

     
      
  1. 00000-“数据类型不一致:预期的%s得到了%s”
  2.   

我应该使用其他功能吗?那是什么?

感谢您的回复。

2 个答案:

答案 0 :(得分:1)

1)添加函数以生成对象的“文本”表示形式。

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-复杂而强大

ImpAggr正在实现自定义聚合机制。

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 FUNCTION CustomAggregation (input objtype) RETURN varchar2 
PARALLEL_ENABLE AGGREGATE USING ImpAggr;

和用法。

select CustomAggregation(t.col1) from myTab t;

答案 1 :(得分:0)

要将listagg与UDT一起使用,您需要以某种方式序列化数据。 从我的头开始,您可以按照以下步骤从对象生成XMLType,然后可以在XML对象上使用getStringVal()函数-或可以向对象添加toString成员函数。

例如:

select listagg(xmltype(t.col1).getStringVal(),', ') within group (order by 1) from myTab t;
..... 
<OBJTYPE><ID>1</ID><COL1>col1</COL1><COL2>10</COL2></OBJTYPE>, <OBJTYPE><ID>2</ID><COL1>col2</COL1><COL2>20</COL2></OBJTYPE>, <OBJTYPE><ID>3</ID><COL1>col3</COL1><COL2>3000</COL2></OBJTYPE>

或者您可以使用XMLAGG(带有或不带有getStringVal())

select xmlagg(xmltype(t.col1)).getStringVal() from myTab t;