如何在 sql (oracle) 中将 LISTAGG 与 UDT 一起使用?

How to use LISTAGG with UDT in sql (oracle)?

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;

我想要的是在一行中显示 table 的每个元素,如下所示:

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

但是我得到了这个错误:

Rapport d'erreur -

Erreur SQL : ORA-00932: inconsistent datatypes: expected NUMBER got USER.OBJTYPE

  1. 00000 - "inconsistent datatypes: expected %s got %s"

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

感谢您的回复。

要将 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;

1) 添加函数以生成对象的 "text" 表示。

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;