自己写的使用聚集函数实现多行字串合并处理
-----------------------------------------------------------------------------------------------------------
--以下请在pl/sql里依次执行,
--功能说明:有几篇文章都写过了关于ORACLE中的自制聚集函数的例子,这里再加一篇自已写的对多行数据在a 字段group by 后,对别的字段值进行字串合并的例子.
--NO.1
create or replace type string_merge_type as object
(
-- author : administrator
-- created : 12-九月-06 10:36:27
-- purpose : 对多行字串进行合并,用指定的字符作间隔符
-- attributes
str varchar2(30000),
static function odciaggregateinitialize(sctx in out string_merge_type)
return number,
member function odciaggregateiterate(self in out string_merge_type,
value in varchar2) return number,
member function odciaggregateterminate(self in string_merge_type,
returnvalue out varchar2,
flags in number)
return number,
member function odciaggregatemerge(self in out string_merge_type,
ctx2 in string_merge_type)
return number
) ;

--No.2
create or replace type body string_merge_type is
static function odciaggregateinitialize(sctx in out string_merge_type)
return number is
begin
sctx := string_merge_type(null);
return odciconst.success;
end;
member function odciaggregateiterate(self in out string_merge_type,
value in varchar2) return number is
begin
self.str := self.str || value || ',';
return odciconst.success;
end;
member function odciaggregateterminate(self in string_merge_type,
returnvalue out varchar2,
flags in number) return number is
begin
returnvalue := substr(self.str, 1, length(self.str) - 1);
return odciconst.success;
end;
member function odciaggregatemerge(self in out string_merge_type,
ctx2 in string_merge_type)
return number is
begin
self.str:=self.str||ctx2.str; --可直接用null;
return odciconst.success;
end;
end; 

--另:如果添加对于相同值在合并后的字串中只出现一次的处理 ---
--No.2
create or replace type body string_merge_type is
static function odciaggregateinitialize(sctx in out string_merge_type)
return number is
begin
sctx := string_merge_type(null);
sctx.str:=',';
return odciconst.success;
end;
member function odciaggregateiterate(self in out string_merge_type,
value in varchar2) return number is
begin
if instr(self.str,','||value||',',1,1)=0 then
self.str := self.str || value || ',';
end if;
return odciconst.success;
end;
member function odciaggregateterminate(self in string_merge_type,
returnvalue out varchar2,
flags in number) return number is
begin
returnvalue :=ltrim(rtrim(self.str,','),',');
return odciconst.success;
end;
member function odciaggregatemerge(self in out string_merge_type,
ctx2 in string_merge_type)
return number is
begin
self.str:=self.str||ctx2.str; --可直接用null;
return odciconst.success;
end;
end; 

--No.3
CREATE or replace FUNCTION merger(input varchar2 ) RETURN varchar2
PARALLEL_ENABLE AGGREGATE USING string_merge_type;

--函数功能测试
/*
TODO: owner="Administrator" created="12-四月-06"
text="测试函数特性"
*/
drop table test_xxm;
create table test_xxm (a_s varchar2(5),b_s varchar2(5),c_n number(4,2),d_n number(5,0));
insert into test_xxm (a_s,b_s,c_n,d_n) values('aa','a1',2,5);
insert into test_xxm (a_s,b_s,c_n,d_n) values('bb','a4',3,4);
insert into test_xxm (a_s,b_s,c_n,d_n) values('cc','a2',4,6);
insert into test_xxm (a_s,b_s,c_n,d_n) values('aa','a2',2,1);
insert into test_xxm (a_s,b_s,c_n,d_n) values('bb','a3',5,3);
insert into test_xxm(a_s,b_s,c_n,d_n)values('bb','a3',6,2);
--不同查询方式下的测试结果 ,查询表test_xxm的结果
select * from test_xxm ;
aa a1 2.00 5
bb a4 3.00 4
cc a2 4.00 6
aa a2 2.00 1
bb a3 5.00 3
bb a3 6.00 2 ;
select merger(b_s) from test_xxm ;
a1,a4,a2,a2,a3,a3;
select merger(b_s) from test_xxm group by b_s;
1 a1
2 a2,a2
3 a3,a3
4 a4
select merger(B_S) OVER (ORDER BY b_s) from test_xxm ;
a1
a1,a2,a2
a1,a2,a2
a1,a2,a2,a3
a1,a2,a2,a3,a3
a1,a2,a2,a3,a3,a4 ;
select merger(B_S) OVER (ORDER BY b_s desc) from test_xxm ;
a4
a4,a3,a3
a4,a3,a3
a4,a3,a3,a2,a2
a4,a3,a3,a2,a2
a4,a3,a3,a2,a2,a1 ;
select merger(B_S) OVER (PARTITION BY a_s ORDER BY b_s desc) from test_xxm ;
a2
a2,a1
a4
a4,a3,a3
a4,a3,a3
a2 ;
select merger(B_S) from test_xxm group by a_s ;
a1,a2
a4,a3,a3
a2
select merger(B_S),merger(c_n) from test_xxm group by a_s ;
a1,a2 2
a4,a3 3,5
a2 4
select a_s, max(b_s)
from (select a_s, merger(b_s) over(partition by a_s order by b_s) b_s
from test_xxm)
group by a_s
本来是可以在pl/sql中用创建type的方式来写和编辑,更为方便,但我发现在pl/sql中self是不被允许的,而聚合函数在这里要用到的地方是不可改为他名的,所在如果编译成功后如果在pl/sql中打开,请不要用spec&body的方式打开,否则什么也不动再编译也会报错,这可能算是pl/sql的一个bug吧!
posted on 2006-11-05 17:26 changhai-xuri 阅读(613) 评论(1) 收藏 举报

浙公网安备 33010602011771号