a我考网

 找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 67|回复: 0

[综合] Oracle认证:Oracle自定义与函数自定义

[复制链接]
发表于 2012-8-4 13:54:49 | 显示全部楼层 |阅读模式
Oracle认证:Oracle自定义与函数自定义
3 o. x4 A. A( ?* ^3 `Oracle 提供了很多预定义好的***函数,比如Max(), Sum(), AVG() , 但是这些预定义的***函数基本上都是适应于标量数据(scalar data ) , 对于复杂的数据类型,比如说用户自定义的Object type, Clob 等, 是不支持的。! _, ?5 s2 s( Y* F
但是,幸运的是, 用户可以通过实现Oracle 的Extensibility Framework 中的ODCIAggregate interface 来创建自定义***函数,而且自定义的***函数跟内建的***函数用法上没有差别。4 ?4 G- K2 _8 l
通过实现ODCIAggregate rountines 来创建自定义的***函数。可以通过定义一个对象类型(Object Type ),然后在这个类型内部实现ODCIAggregate 接口函数(routines) , 可以用任何一种Oracle 支持的语言来实现这些接口函数,比如C/C++, JAVA, PL/SQL 等。在这个Object Type 定义之后,相应的接口函数也都在该Object Type Body 内部实现之后, 就可以通过CREATE FUNCTION 语句来创建自定义的***函数了。7 _0 L- F4 z0 C, B
每个自定义的***函数需要实现4 个ODCIAggregate 接口函数, 这些函数定义了任何一个***函数内部需要实现的操作,这些函数分别是initialization, iteration, merging 和termination 。
$ u, Y2 I, S" u, m3 `; A/ w1 ra. static function ODCIAggregateInitialize(sctx IN OUTstring_agg_type ) return number
4 V& }7 P6 E6 V+ @自定义***函数初始化操作, 从这儿开始一个***函数。初始化的***环境(aggregation context) 会以对象实例(object type instance) 传回给oracle.0 @, I8 ~) x2 I2 V
b. member function ODCIAggregateIterate(self IN OUT string_agg_type ,value IN varchar2) return number
' Y+ r8 P* V/ p0 Q自定义***函数, 最主要的步骤, 这个函数定义我们的***函数具体做什么操作, 后面的例子, 是取最大值, 最小值, 平均值, 还是做连接操作。self 为当前***函数的指针, 用来与前面的计算结果进行关联
+ J8 d  p9 t0 S. m. }% Y这个函数用来遍历需要处理的数据,被oracle 重复调用。每次调用的时候,当前的aggreation context 和 新的(一组)值会作为传入参数。 这个函数会处理这些传入值,然后返回更新后的aggregation context. 这个函数对每一个NON-NULL 的值都会被执行一次。NULL 值不会被传递个***函数。$ Z% I: }. R- i9 N0 p
c. member function ODCIAggregateMerge (self IN string_agg_type,returnValue OUT varchar2,flags IN number) return number
4 B9 {1 U3 z- U6 O* _0 h用来合并两个***函数的两个不同的指针对应的结果, 用户合并不同结果结的数据, 特别是处理并行(parallel) 查询***函数的时候。
& g6 s" D: G# m& g% k* C+ J这个函数用来把两个aggregation context 整合在一起,一般用来并行计算中(当一个函数被设置成enable parallel 处理的时候)。+ W; B5 M4 l: O
d. member function OCDIAggregateTerminate(self IN string_agg_type,returnValue OUT varchar2,flags IN number)* F( ^; r. f8 ]! p- [  q! t9 z6 l
终止***函数的处理, 返回***函数处理的结果。
( H/ H. K9 e7 l: }. D( H这个函数是Oracle 调用的最后一个函数。它接收aggregation context 作为参数,返回最后的aggregate value.
, Z* W2 a, P: U( D9 l5 z5 H应用场景一:字符串***9 i: X0 A% L8 Y/ |
CREATE OR REPLACE TYPE typ_concatenate_impl AS OBJECT+ l4 }  a* A9 {6 {
9 g9 m' E8 K; F& u+ F! y
retstr VARCHAR2(30000), -- 拼凑使用的中间字符串
$ X! S% A8 P- m& b+ x8 S% ]SEPARATORFLAG VARCHAR2(64), -- 分隔符,默认用自由定义| ,可以修改此处
1 C# j" Y, W4 D! N9 \4 B+ U; g; q  ESTATIC FUNCTION ODCIAGGREGATEINITIALIZE(sctx IN OUT typ_concatenate_impl) RETURN NUMBER,% M+ M8 x( i. Z8 H7 q6 U
MEMBER FUNCTION ODCIAGGREGATEITERATE(self IN OUT typ_concatenate_impl, value IN VARCHAR2) RETURN NUMBER,
, x! i! S5 w9 `. W! E; vMEMBER FUNCTION ODCIAGGREGATETERMINATE(self IN typ_concatenate_impl, returnvalue OUT VARCHAR2, flags IN NUMBER) RETURN NUMBER,
8 D+ r  I1 j% HMEMBER FUNCTION ODCIAGGREGATEMERGE(self IN OUT typ_concatenate_impl, ctx2 IN typ_concatenate_impl) RETURN NUMBER
2 a6 b0 [( v' o+ k* |* o; A7 L& y- U: D6 A: h% _4 M; p
/) d( u3 {  V# V/ Y. a' F3 m
CREATE OR REPLACE TYPE BODY typ_concatenate_impl IS& V: _3 h: R% Z. u
-- 自定义***函数初始化操作( m" [% P  E1 ^2 R  y. T) W7 ~
STATIC FUNCTION ODCIAGGREGATEINITIALIZE(sctx IN OUT typ_concatenate_impl) RETURN NUMBER IS: U" U: p# L1 \9 Y0 e# L( s
BEGIN
" H- e' k" g, B2 Xsctx := typ_concatenate_impl(‘’,‘,’);
% Z" Z. ~/ l9 C# X* w1 `! KRETURN ODCICONST.SUCCESS;
& D7 A9 l% D1 e6 DEND;
# K5 E/ i. L' i# r  g& o! |8 b( x-- 定义函数的功能,实现字符串拼接
' \8 l( |/ N: B& z" KMEMBER FUNCTION ODCIAGGREGATEITERATE(self IN OUT typ_concatenate_impl, value IN VARCHAR2) RETURN NUMBER IS
# C. O6 R4 z# u* v( t% @6 ~1 H0 k& r: bBEGIN
; a- B! a# `: S; {& s  c; Zself.retstr := self.retstr || value||self.SEPARATORFLAG;0 A) r/ u8 T0 P4 T/ Q2 d: r- U/ a  r
RETURN ODCICONST.SUCCESS;7 N1 o1 k' |" i# y4 U9 S% @9 @
END;
0 X) h' h; \9 h( m; y4 P-- 定义终止***函数的处理, 返回***函数处理的结果8 }6 g2 P7 Z$ L' ~3 T6 u1 Q- [7 N5 j
MEMBER FUNCTION ODCIAGGREGATETERMINATE(self IN typ_concatenate_impl, returnvalue OUT VARCHAR2, FLAGS IN NUMBER)3 T" g: [5 X# G3 y% H6 d0 V
RETURN NUMBER IS9 e# ^. u+ r& N) R
BEGIN
4 Q4 S# f' o- |0 j5 [. m# IIF returnvalue IS NOT NULL THEN
. [8 U, J+ G$ B0 E! Rreturnvalue := SUBSTR(self.retstr,1,LENGTH(self.retstr)-1);" H3 y0 l/ m9 j
ELSE
' M' Q% q2 e; P* ~: ?returnvalue := self.retstr;! c- e+ X, i6 b9 g5 ~9 [
END IF;1 W: d) L* t$ l' a! p+ U( B! q5 N
RETURN ODCICONST.SUCCESS;9 T; x0 G$ N6 \6 o# o* g
END;+ x$ n6 S7 G. t0 J. M/ `
-- 用来合并两个***函数的两个不同的指针对应的结果,此处默认即可
9 k$ Z  |; G2 K5 s8 H6 W0 hMEMBER FUNCTION ODCIAGGREGATEMERGE(self IN OUT typ_concatenate_impl, ctx2 IN typ_concatenate_impl) RETURN NUMBER IS
8 y9 L5 n, ]" I) ~0 u( C& {% o9 PBEGIN% [. ]: J" g6 `( d' S$ M
RETURN ODCICONST.SUCCESS;
& x2 p8 ^8 m% G: o: @  e/ N, IEND;( ~: }0 L) e( A" J' L
END;3 @+ w0 i4 G% W! O' r1 N( q
/' P  \' b! o5 @# T; F, @
-- 创建自定义函数) L7 p' d& \" _3 N: w
CREATE OR REPLACE FUNCTION f_concatenate_str(i_str VARCHAR2) RETURN VARCHAR2* ?% @: D8 U7 v: F( j5 k
AGGREGATE USING typ_concatenate_impl;
0 I# N: f3 L+ @9 o, W/
! R% |* Q, a0 X! i5 Z0 ?创建测试表和数据,并进行测试7 p- N! i6 m+ I& z4 N7 {1 M
CREATE TABLE TEST (ID NUMBER, NAME VARCHAR2(20));, |; F( M1 o' b: K1 E
INSERT INTO TEST VALUES (1, ‘AAA’);8 l0 J+ ^* P: z
INSERT INTO TEST VALUES (2, ‘BBB’);% e5 u/ l" k' B
INSERT INTO TEST VALUES (1, ‘ABC’);4 h0 I3 j5 }" K$ ?0 ~- T/ o) a
INSERT INTO TEST VALUES (3, ‘CCC’);
4 a+ M3 h( K+ j/ Q2 kINSERT INTO TEST VALUES (2, ‘DDD’);
, ~7 s# k2 C2 ?* f6 ]) dCOMMIT;5 C, f& c- {) z6 W; o5 A
查看执行后的结果,并与WMSYS.WM_CONCAT 函数执行效果对照。
# [4 X0 N+ \" U# ]( i* `% SSQL》 SELECT id,f_concatenate_str(name) name FROM test GROUP BY id;1 g  i6 A0 Y' c: r) L& K$ S9 G7 n7 j
ID NAME
9 l' x9 a0 h0 p) a: L% ~% q---------- ------------------------------------------------------------------
. x' w6 @: F' ^$ S6 _" V! r1 AAA,ABC,
* P7 t) ?$ H5 c( X" J2 BBB,DDD,* N+ R8 X9 m0 ]
3 CCC,
8 Y' N3 j7 o) g% cSQL》 SELECT id,wmsys.wm_concat(name) name FROM test GROUP BY id;
$ [. n% f! ?: cID NAME
3 h) J! h- U$ Z. e$ }---------- ------------------------------------------------------------------- k: o; i4 \: Y2 s4 E5 q' o6 {
1 AAA,ABC
1 Q2 m( s" N6 _- v" o# F0 S7 {+ ?2 BBB,DDD
% T# }% q- b, X2 m* ?3 CCC
. X* ?. s: B3 s2 b# S0 |: h& ]SQL》 SELECT id,f_concatenate_str(name) OVER (PARTITION BY id) name FROM test;6 F6 F( H) A" [4 F5 d! C' r
ID NAME) B8 \3 G4 S" m& `6 |
---------- ------------------------------------------------------------------
% k6 E0 m$ b3 W4 M5 J6 \1 Z1 AAA,ABC,
( w9 i! Y2 y: b9 ]" u$ ~! |1 AAA,ABC,
7 _' a$ V8 o, x0 x* g2 Q* ^/ h/ u: v2 DDD,BBB,% I: P8 h( w, t5 O8 p
2 DDD,BBB,4 P! M, d2 H: N
3 CCC,* Z6 N7 e6 u; u/ K5 \
SQL》 SELECT id,wmsys.wm_concat(name) OVER (PARTITION BY id) name FROM test;  b4 {% A8 L# H, o; d
ID NAME
9 k' T% G# h/ E# j; {---------- ------------------------------------------------------------------
. v5 ]! M# C, `- ~! S, Q1 AAA,ABC6 y9 X* |% t6 L% E6 F  H( l
1 AAA,ABC
' H: d) j: `3 k' B7 R1 T2 DDD,BBB
+ S6 l; u2 w7 a2 k+ ?% ^1 C7 n2 DDD,BBB
. n0 j9 r; E6 |2 U3 CCC6 I9 i+ K" Z) W% l+ f2 m
实际上在Oracle10g 版本中提供了一个未文档化的函数 wmsys.wm_concat() ,也可以实现字符串的***拼接;这两个函数异曲同工。- H5 n; p" P- ?3 I. q! q: R: |: W& R
这也说明Oracle 提供的***函数已足够强大,想发明不重复的轮子还是很困难的。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|Woexam.Com ( 湘ICP备18023104号 )

GMT+8, 2024-5-14 07:08 , Processed in 0.248336 second(s), 21 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表