[Oracle Data Cartridge Interface] UserDefined Aggregation Functions

摘要:
但是,幸运的是,用户可以通过实现Oracle的ExtensibilityFramework中的ODCIAggregateinterface来创建自定义聚集函数,而且自定义的聚集函数跟内建的聚集函数用法上没有差别。ODCI是OracleDataCartridgeInterface几个单词的首字母缩写,关于OracleDataCartridge,可以参见这里。每个自定义的聚集函数需要实现4个ODCIAggregate接口函数,这些函数定义了任何一个聚集函数内部需要实现的操作,这些函数分别是initialization,iteration,merging和termination。

本文基本上是对Orace文档(http://download.oracle.com/docs/cd/B19306_01/appdev.102/b14289/dciaggfns.htm#sthref542) 的翻译。

Oracle提供了很多预定义好的聚集函数,比如Max(), Sum(), AVG(), 但是这些预定义的聚集函数基本上都是适应于标量数据(scalar data), 对于复杂的数据类型,比如说用户自定义的Object type, Clob等, 是不支持的。

但是,幸运的是, 用户可以通过实现Oracle的Extensibility Framework中的ODCIAggregate interface来创建自定义聚集函数,而且自定义的聚集函数跟内建的聚集函数用法上没有差别。

ODCI是Oracle Data Cartridge Interface 几个单词的首字母缩写, 关于Oracle Data Cartridge,可以参见这里

1. Overview of User-Defined Aggregate Functions

通过实现ODCIAggregate rountines来创建自定义的聚集函数。可以通过定义一个对象类型(Object Type),然后在这个类型内部实现ODCIAggregate 接口函数(routines), 可以用任何一种Oracle支持的语言来实现这些接口函数,比如C/C++, JAVA, PL/SQL等。在这个Object Type定义之后,相应的接口函数也都在该Object Type Body内部实现之后, 就可以通过CREATE FUNCTION语句来创建自定义的聚集函数了。

每个自定义的聚集函数需要实现4个ODCIAggregate 接口函数, 这些函数定义了任何一个聚集函数内部需要实现的操作,这些函数分别是 initialization, iteration, merging 和 termination。

(1)ODCIAggregateInitialize这个函数用来执行初始化操作(initialization). Oracle会调用这个函数来初始化自定义函数计算。 初始化的聚集环境(aggregation context)会以对象实例(object type instance)传回给oracle.

(2) ODCIAggregateIterate这个函数用来遍历需要处理的数据,被oracle重复调用。每次调用的时候,当前的aggreation context 和 新的(一组)值会作为传入参数。 这个函数会处理这些传入值,然后返回更新后的aggregation context. 这个函数对每一个NON-NULL的值都会被执行一次。NULL值不会被传递个聚集函数。

(3) ODCIAggregateMerge 这个函数用来把两个aggregation context整合在一起,一般用来并行计算中(当一个函数被设置成enable parallel 处理的时候)。

(4) ODCIAggregateTerminate这个函数是Oracle调用的最后一个函数。它接收aggregation context作为参数,返回最后的aggregate value.

Example: 自定义聚集函数是如何工作的

SELECT AVG(T.Sales)
FROM AnnualSales T
GROUP BY T.State;

为了完成求平均值的计算,AVG函数经历下面几个步骤:

(1) Initializes: 初始化Aggregation Context:

runningSum = 0; runningCount = 0;

(2) Iteratively 处理每个连续的输入,同时更新aggregation context:

runningSum += inputval; runningCount ++;

(3) 【这步是可选的】Merge 整合两个aggregation context 返回一个aggregation context. 如果需要这一步的话,它是在termination之前执行。

runningSum = runningSum1 + runningSum2;

runningCount = runningCount1 + runningCount2;

(4) Terminates 计算出最后的结果, 通过最后的aggregation context来返回最后的aggregated value.

return (runningSum / runningCount);

如果AVG是自定义的聚集函数的话,与之相对应的对象类型(object type)需要实现对应的ODCIAggregate的接口函数。变量runningSum 和 runningCount 是对象类型中的属性(attribute).

2. Creating a User-Defined Aggregate

创建一个自定义聚集函数分成两步: 如下面两个例子所示:

Example: 如何实现ODCIAggregate接口:

CREATE TYPE SpatialUnionRoutines(
   STATIC FUNCTION ODCIAggregateInitialize( ... ) ...,
   MEMBER FUNCTION ODCIAggregateIterate(...) ... ,
   MEMBER FUNCTION ODCIAggregateMerge(...) ...,
   MEMBER FUNCTION ODCIAggregateTerminate(...)
);
CREATE TYPE BODY SpatialUnionRoutines IS 
...
END;
 

Example:如何定义自定义聚集函数:

CREATE FUNCTION SpatialUnion(x Geometry) RETURN Geometry 
AGGREGATE USING SpatialUnionRoutines;

注意在定义函数的时候需要通过Aggregate Using语句来关联上对应的实现了ODCIAggregate接口的Object Type。

3. Using a User-Defined Aggregate

自定义的聚集函数可以像内置的聚集函数一样使用, 可以用在SELECT, ORDER BY, HAVING语句中。下面几个例子说明如何使用上面定义的自定义函数SpatialUnion

Example: 用在Select语句中

SELECT SpatialUnion(geometry)
FROM counties
GROUP BY state

Example: 用在Having语句中,

SELECT groupcol, MyUDAG(col)
FROM tab
GROUP BY groupcol
HAVING MyUDAG(col) > 100
ORDER BY MyUDAG(col);

Example: 其他

SELECT ..., MyUDAG(col)
FROM tab
GROUP BY ROLLUP(gcol1, gcol2)

自定义聚集函数可以跟All, Distinct一起使用, 亦可以用在Group by的扩展语句中,像ROLLUP, CUBE, grouping sets.

4. Evaluating User-Defined Aggregates in Parallel

跟内置的聚集函数一样,自定义的聚集函数也可以并行来处理, 如下图

Description of Figure 11-1 follows

需要注意的是, 自定义的聚集函数需要声明为parallel-enabled, 如下

CREATE FUNCTION MyUDAG(...) RETURN ...
PARALLEL_ENABLE AGGREGATE USING MyAggrRoutines;

5. User-Defined Aggregates and Analytic Functions

自定义的聚集函数可以被当做Analytic函数来用,

SELECT Account_number, Trans_date, Trans_amount,
   MyAVG (Trans_amount) OVER
      PARTITION BY Account_number ORDER BY Trans_date
      RANGE INTERVAL '7' DAY PRECEDING) AS mavg_7day
FROM Ledger;

6. Reusing the Aggregation Context for Analytic Functions

当一个自定义的聚集函数被用来做Analytic Function的时候,对每条记录对应的window都会计算一次aggregate。 一般的说来,每个连续的窗口包含大部分相同的数据集合。

可以通过实现ODCIAggregateDelete接口函数来让Oracle更有效地复用aggregation context.

7. An complete example for Creating and Using a User-Defined Aggregate Function

SecondMax()返回一组数里面第二大的那个值。

(1) 实现类型SecondMaxImpl,该类型包含了ODCIAggregate接口函数,

create type SecondMaxImpl as object
(
  max NUMBER, -- highest value seen so far 
  secmax NUMBER, -- second highest value seen so far
  static function ODCIAggregateInitialize(sctx IN OUT SecondMaxImpl) 
    return number,
  member function ODCIAggregateIterate(self IN OUT SecondMaxImpl, 
    value IN number) return number,
  member function ODCIAggregateTerminate(self IN SecondMaxImpl, 
    returnValue OUT number, flags IN number) return number,
  member function ODCIAggregateMerge(self IN OUT SecondMaxImpl, 
    ctx2 IN SecondMaxImpl) return number
);
/

(2). 实现类型SecondMaxImpl的body,

create or replace type body SecondMaxImpl is 
static function ODCIAggregateInitialize(sctx IN OUT SecondMaxImpl) 
return number is 
begin
  sctx := SecondMaxImpl(0, 0);
  return ODCIConst.Success;
end;
member function ODCIAggregateIterate(self IN OUT SecondMaxImpl, value IN number) return number is
begin
  if value > self.max then
    self.secmax := self.max;
    self.max := value;
  elsif value > self.secmax then
    self.secmax := value;
  end if;
  return ODCIConst.Success;
end;
member function ODCIAggregateTerminate(self IN SecondMaxImpl, 
    returnValue OUT number, flags IN number) return number is
begin
  returnValue := self.secmax;
  return ODCIConst.Success;
end;
member function ODCIAggregateMerge(self IN OUT SecondMaxImpl, ctx2 IN SecondMaxImpl) return number is
begin
  if ctx2.max > self.max then
    if ctx2.secmax > self.secmax then 
      self.secmax := ctx2.secmax;
    else
      self.secmax := self.max;
    end if;
    self.max := ctx2.max;
  elsif ctx2.max > self.secmax then
    self.secmax := ctx2.max;
  end if;
  return ODCIConst.Success;
end;
end;
/

(3). 创建自定义聚集函数SecondMax()

CREATE FUNCTION SecondMax (input NUMBER) RETURN NUMBER 
PARALLEL_ENABLE AGGREGATE USING SecondMaxImpl;

(4). 使用自定义聚集函数SecondMax()

SELECT SecondMax(salary), department_id
FROM employees
GROUP BY department_id
HAVING SecondMax(salary) > 9000;

免责声明:文章转载自《[Oracle Data Cartridge Interface] UserDefined Aggregation Functions》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Python爬虫之selenium高级功能Oracle用户密码过期问题解决下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

转://从一条巨慢SQL看基于Oracle的SQL优化

http://mp.weixin.qq.com/s/DkIPwbDKIjH2FMN13GkT4w 本次分享的内容是基于Oracle的SQL优化,以一条巨慢的SQL为例,从快速解读SQL执行计划、如何从执行计划中找到SQL执行慢的Root Cause、统计信息与cardinality问题、探索性能杀手Filter操作、如何进行逻辑重写让SQL起飞等多个维度进...

Oracle索引语句整理

转载:http://www.cnblogs.com/djcsch2001/articles/1823459.html 索引,索引的建立、修改、删除索引索引是关系数据库中用于存放每一条记录的一种对象,主要目的是加快数据的读取速度和完整性检查。建立索引是一项技术性要求高的工作。一般在数据库设计阶段的与数据库结构一道考虑。应用系统的性能直接与索引的合理直接有关。...

ORACLE 存储过程提高

1.SQLCODE和SQLERRM 2.%TYPE和%ROWTYPE的使用 3.sql%rowcount的作用 1.SQLCODE和SQLERRM  SQLCode:数据库操作的返回码,其中 0--成功; -1--失败; 100--没有检索到数据。 +1--用户自定义异常 sqlerrm函数返回指定错误代码的错误信息。  在一个内在的异常中,SQLC...

Oracle 数据库常用SQL语句(2)查询语句

一、SQL基础查询 1、select语句 格式:select 字段 from 表名; 2、where 用于限制查询的结果。3、查询条件 > < >= <= = !=4、与 或(AND,OR)5、在 不在(IN,NOT IN)练习:查询工号为1,9,11,16且工资低于1000的员工。6、在 [a,b] (between val1 a...

Oracle常用函数汇总

在Oracle OCP考试中,相当一部分知识点涉及到对于Oracle常见函数的考查。尽管Oracle官方文档SQL Language Reference中Functions一章内列举了所有Oracle自带函数,但如果要系统的看一遍,还是要花费相当的精力,更何况还是英文呢。如果碰到一个不熟悉的,就查一下,不经常用,又很容易遗忘。下面就对Oracle常见函数做...

Oracle数据库的函数,存储过程,程序包,游标,触发器

Oracle自定义函数 函数的主要特性是它必须返回一个值。创建函数时通过 RETURN 子句指定函数返回值的数据类型。函数的一些限制:● 函数只能带有 IN 参数,不能带有 IN OUT 或 OUT 参数。● 形式参数必须只使用数据库类型,不能使用 PL/SQL 类型。● 函数的返回类型必须是数据库类型 Create function 函数名称 retur...