自定义聚集函数
自定義聚集函數(shù)接口簡介
Oracle提供了很多預(yù)定義好的聚集函數(shù),比如Max(), Sum(), AVG(), 但是這些預(yù)定義的聚集函數(shù)基本上都是適應(yīng)于標(biāo)量數(shù)據(jù)(scalar data), 對于復(fù)雜的數(shù)據(jù)類型,比如說用戶自定義的Objecttype, Clob等, 是不支持的。
但是,幸運(yùn)的是, 用戶可以通過實(shí)現(xiàn)Oracle的Extensibility Framework中的ODCIAggregateinterface來創(chuàng)建自定義聚集函數(shù),而且自定義的聚集函數(shù)跟內(nèi)建的聚集函數(shù)用法上沒有差別。
通過實(shí)現(xiàn)ODCIAggregate rountines來創(chuàng)建自定義的聚集函數(shù)??梢酝ㄟ^定義一個(gè)對象類型(Object Type),然后在這個(gè)類型內(nèi)部實(shí)現(xiàn)ODCIAggregate接口函數(shù)(routines), 可以用任何一種Oracle支持的語言來實(shí)現(xiàn)這些接口函數(shù),比如C/C++, JAVA, PL/SQL等。在這個(gè)Object Type定義之后,相應(yīng)的接口函數(shù)也都在該Object Type Body內(nèi)部實(shí)現(xiàn)之后, 就可以通過CREATE FUNCTION語句來創(chuàng)建自定義的聚集函數(shù)了。
每個(gè)自定義的聚集函數(shù)需要實(shí)現(xiàn)4個(gè)ODCIAggregate接口函數(shù), 這些函數(shù)定義了任何一個(gè)聚集函數(shù)內(nèi)部需要實(shí)現(xiàn)的操作,這些函數(shù)分別是initialization, iteration, merging和termination。
?
a. static function ODCIAggregateInitialize(sctxIN OUTstring_agg_type ) return number
??自定義聚集函數(shù)初始化操作,從這兒開始一個(gè)聚集函數(shù)。初始化的聚集環(huán)境(aggregation context)會(huì)以對象實(shí)例(object typeinstance)傳回給oracle.
b. member function ODCIAggregateIterate(selfIN OUT string_agg_type ,value IN varchar2) return number
??自定義聚集函數(shù),最主要的步驟,這個(gè)函數(shù)定義我們的聚集函數(shù)具體做什么操作,后面的例子,是取最大值,最小值,平均值,還是做連接操作.self為當(dāng)前聚集函數(shù)的指針,用來與前面的計(jì)算結(jié)果進(jìn)行關(guān)聯(lián)
??這個(gè)函數(shù)用來遍歷需要處理的數(shù)據(jù),被oracle重復(fù)調(diào)用。每次調(diào)用的時(shí)候,當(dāng)前的aggreation context和 新的(一組)值會(huì)作為傳入?yún)?shù)。 這個(gè)函數(shù)會(huì)處理這些傳入值,然后返回更新后的aggregation context.這個(gè)函數(shù)對每一個(gè)NON-NULL的值都會(huì)被執(zhí)行一次。NULL值不會(huì)被傳遞個(gè)聚集函數(shù)。
c. member function ODCIAggregateMerge (selfIN string_agg_type,returnValue OUT?varchar2,flags IN number) return number
??用來合并兩個(gè)聚集函數(shù)的兩個(gè)不同的指針對應(yīng)的結(jié)果,用戶合并不同結(jié)果結(jié)的數(shù)據(jù),特別是處理并行(parallel)查詢聚集函數(shù)的時(shí)候.
??這個(gè)函數(shù)用來把兩個(gè)aggregation context整合在一起,一般用來并行計(jì)算中(當(dāng)一個(gè)函數(shù)被設(shè)置成enable parallel處理的時(shí)候)。
d. member functionOCDIAggregateTerminate(self IN string_agg_type,returnValue OUT varchar2,flagsIN number)
???終止聚集函數(shù)的處理,返回聚集函數(shù)處理的結(jié)果.
??這個(gè)函數(shù)是Oracle調(diào)用的最后一個(gè)函數(shù)。它接收aggregation context作為參數(shù),返回最后的aggregatevalue.??
應(yīng)用場景一:字符串聚集
| CREATE OR REPLACE TYPE typ_concatenate_impl AS OBJECT ( ???retstr VARCHAR2(30000),?????--拼湊使用的中間字符串 ???SEPARATORFLAG?VARCHAR2(64), --分隔符,默認(rèn)用自由定義|,可以修改此處 ???STATIC FUNCTION ODCIAGGREGATEINITIALIZE(sctx IN OUT typ_concatenate_impl) RETURN NUMBER, ???MEMBER FUNCTION ODCIAGGREGATEITERATE(self IN OUT typ_concatenate_impl, value IN VARCHAR2) RETURN NUMBER, ???MEMBER FUNCTION ODCIAGGREGATETERMINATE(self IN typ_concatenate_impl, returnvalue OUT VARCHAR2, flags IN NUMBER) RETURN NUMBER, ???MEMBER FUNCTION ODCIAGGREGATEMERGE(self IN OUT typ_concatenate_impl, ctx2 IN typ_concatenate_impl) RETURN NUMBER ) / CREATE OR REPLACE TYPE BODY typ_concatenate_impl IS ???--自定義聚集函數(shù)初始化操作 ???STATIC FUNCTION ODCIAGGREGATEINITIALIZE(sctx IN OUT typ_concatenate_impl) RETURN NUMBER IS ???BEGIN ???????sctx := typ_concatenate_impl('',','); ???????RETURN ODCICONST.SUCCESS; ???END; ???--定義函數(shù)的功能,實(shí)現(xiàn)字符串拼接 ???MEMBER FUNCTION ODCIAGGREGATEITERATE(self IN OUT typ_concatenate_impl, value IN VARCHAR2) RETURN NUMBER IS ???BEGIN ???????self.retstr := self.retstr || value||self.SEPARATORFLAG; ???????RETURN ODCICONST.SUCCESS; ???END; ???--定義終止聚集函數(shù)的處理,返回聚集函數(shù)處理的結(jié)果 ???MEMBER FUNCTION ODCIAGGREGATETERMINATE(self IN typ_concatenate_impl, returnvalue OUT VARCHAR2, FLAGS IN NUMBER) ???RETURN NUMBER IS ???BEGIN ???????IF returnvalue IS NOT NULL THEN ???????????returnvalue := SUBSTR(self.retstr,1,LENGTH(self.retstr)-1); ???????ELSE ???????????returnvalue := self.retstr; ???????END IF; ???????RETURN ODCICONST.SUCCESS; ???END; ???--用來合并兩個(gè)聚集函數(shù)的兩個(gè)不同的指針對應(yīng)的結(jié)果,此處默認(rèn)即可 ???MEMBER FUNCTION ODCIAGGREGATEMERGE(self IN OUT typ_concatenate_impl, ctx2 IN typ_concatenate_impl) RETURN NUMBER IS ???BEGIN ???????RETURN ODCICONST.SUCCESS; ???END; END; / ? --創(chuàng)建自定義函數(shù) CREATE OR REPLACE FUNCTION f_concatenate_str(i_str VARCHAR2) RETURN VARCHAR2 ???AGGREGATE USING typ_concatenate_impl; / |
?
???創(chuàng)建測試表和數(shù)據(jù),并進(jìn)行測試
| CREATE TABLE TEST (ID NUMBER, NAME VARCHAR2(20)); INSERT INTO TEST VALUES (1, 'AAA'); INSERT INTO TEST VALUES (2, 'BBB'); INSERT INTO TEST VALUES (1, 'ABC'); INSERT INTO TEST VALUES (3, 'CCC'); INSERT INTO TEST VALUES (2, 'DDD'); COMMIT; |
查看執(zhí)行后的結(jié)果,并與WMSYS.WM_CONCAT函數(shù)執(zhí)行效果對照。
| SQL> SELECT id,f_concatenate_str(name) name FROM test GROUP BY id;?????????? ???????ID NAME ---------- ------------------------------------------------------------------ ????????1 AAA,ABC, ????????2 BBB,DDD, ????????3 CCC, ? SQL> SELECT id,wmsys.wm_concat(name) name FROM test GROUP BY id; ???????ID NAME ---------- ------------------------------------------------------------------ ????????1 AAA,ABC ????????2 BBB,DDD ????????3 CCC ? SQL> SELECT id,f_concatenate_str(name) OVER (PARTITION BY id) name FROM test; ???????ID NAME ---------- ------------------------------------------------------------------ ????????1 AAA,ABC, ????????1 AAA,ABC, ????????2 DDD,BBB, ????????2 DDD,BBB, ????????3 CCC, ? SQL> SELECT id,wmsys.wm_concat(name) OVER (PARTITION BY id) name FROM test; ???????ID NAME ---------- ------------------------------------------------------------------ ????????1 AAA,ABC ????????1 AAA,ABC ????????2 DDD,BBB ????????2 DDD,BBB ????????3 CCC |
???
實(shí)際上在Oracle10g版本中提供了一個(gè)未文檔化的函數(shù)wmsys.wm_concat(),也可以實(shí)現(xiàn)字符串的聚集拼接;這兩個(gè)函數(shù)異曲同工。
???這也說明Oracle提供的聚集函數(shù)已足夠強(qiáng)大,想發(fā)明不重復(fù)的輪子還是很困難的。總結(jié)
- 上一篇: 数据源管理 | 分布式NoSQL系统,C
- 下一篇: 1465 错排公式