ITPUB论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

返回列表 发新帖
更多
查看: 3710|回复: 5

Oracle Pipelined Table Functions(转) [复制链接]

版主

版主

精华贴数
6
技术积分
8914
社区积分
347
注册时间
2006-2-22
论坛徽章:
46
ITPUB十周年纪念徽章
日期:2011-11-01 16:21:152010新春纪念徽章
日期:2010-03-01 11:21:022010新春纪念徽章
日期:2010-01-04 08:33:08祖国60周年纪念徽章
日期:2009-10-09 08:28:002009日食纪念
日期:2009-07-22 09:30:00生肖徽章2007版:鼠
日期:2009-06-16 16:00:25生肖徽章2007版:羊
日期:2009-03-10 21:16:04生肖徽章2007版:牛
日期:2009-03-02 15:43:25生肖徽章2007版:鸡
日期:2009-03-02 15:40:49生肖徽章2007版:龙
日期:2009-02-27 19:33:162010数据库技术大会纪念徽章
日期:2010-05-13 10:04:272010系统架构师大会纪念
日期:2010-09-03 16:39:57
发表于 2006-8-8 11:10:50 |显示全部楼层
zhouwf0726 | 25 七月, 2006 12:59

Oracle Pipelined Table FunctionsOverview

Basically, when you would like a PLSQL (or java or c) routine to be the «source»
of data -- instead of a table -- you would use a pipelined function.

PIPELINED functions will operate like a table.

A PL/SQL function may be used in a data warehouse database to transform large amounts of data. This might also involve massaging the data in a series of transformations, each performed by different functions. Prior to Oracle Database 9, large transformations required either significant memory overhead, or storing the data in intermediate tables between each stage of the transformation. The loading process caused immense performance degradations in both cases.

Using PL/SQL table functions can significantly lower the over-head of doing such transformations. PL/SQL table functions accept and return multiple rows, delivering them as they are ready rather than all at once, and can be made to execute as parallel operations.

Simple Example - Generating Some Random Data

How could you create six unique random numbers between 1 and 49 with one SQL statement?

We would generate the set of numbers to pick from (see the innermost query that follows); any table with 49 or more records would do it. First the quick-and-dirty solution without a pipelined function.

select r
from (select r
from (select rownum r
from all_objects
where rownum < 50)
order by dbms_random.value)
where rownum <= 6;

R
----------
10
2
19
34
12
21

That query works by generating the numbers 1 .. 49, using the inline view. We wrap that innermost query as an inline view and sort it by a random value, using DBMS_RANDOM.VALUE. We wrap that result set in yet another inline view and just take the first six rows. If we run that query over and over, we'll get a different set of six rows each time.

This sort of question comes up frequently—maybe not about how to generate a set of six random numbers but rather, "how can we get N rows?" For example, we'd like the inclusive set of all dates between 25-FEB-2004 and 10-MAR-2004. The question becomes how to do this without a "real" table, and the answer lies in Oracle9i/10g with its PIPELINED function capability. We can write a PL/SQL function that will operate like a table. We need to start with a SQL collection type; this describes what the PIPELINED function will return. In this case, we are choosing a table of numbers; the virtual table we are creating will simply return the numbers 1, 2, 3, ... N:

create type array
as table of number
/

Type created.

Next, we create the actual PIPELINED function. This function will accept an input to limit the number of rows returned. If no input is provided, this function will just keep generating rows for a very long time (so be careful and make sure to use ROWNUM or some other limit in the query itself!). The PIPELINED keyword on line 4 allows this function to work as if it were a table:

create function
gen_numbers(n in number default null)
return array
PIPELINED
as
begin
for i in 1 .. nvl(n,999999999)
loop
pipe row(i);
end loop;
return;
end;
/

Function created.

Suppose we needed three rows for something. We can now do that in one of two ways:

select * from TABLE(gen_numbers(3));

COLUMN_VALUE
------------
1
2
3

or

select * from TABLE(gen_numbers)
where rownum <= 3;

COLUMN_VALUE
------------
1
2
3

Now we are ready to re-answer the original question, using the following functionality:

select *
from (
select *
from (select * from table(gen_numbers(49)))
order by dbms_random.random
)
where rownum <= 6
/

COLUMN_VALUE
------------
47
42
40
15
48
23

We can use this virtual table functionality for many things, such as generating that range of dates:

select to_date('25-feb-2004')+
column_value-1
from TABLE(gen_numbers(15))
/

TO_DATE('
---------
25-FEB-04
26-FEB-04
27-FEB-04
28-FEB-04
29-FEB-04
01-MAR-04
02-MAR-04
03-MAR-04
04-MAR-04
05-MAR-04
06-MAR-04
07-MAR-04
08-MAR-04
09-MAR-04
10-MAR-04

Note the name of the column we used: COLUMN_VALUE. That is the default name for the column coming back from the PIPELINED function.

Typical Pipelined Example

This are the typical steps to perform when using PL/SQL Table Functions:

The producer function must use the PIPELINED keyword in its declaration.

The producer function must use an OUT parameter that is a record, corresponding to a row in the result set.

Once each output record is completed, it is sent to the consumer function through the use of the PIPE ROW keyword.

The producer function must end with a RETURN statement that does not specify any return value.

The consumer function or SQL statement then must use the TABLE keyword to treat the resulting rows from the PIPELINE function like a regular table.
The first step is to define the format of the rows that are going to be returned. In this case here, we're going to return a INT, DATE followed by a VARCHAR2(25).

CREATE OR REPLACE TYPE myObjectFormat
AS OBJECT
(
A INT,
B DATE,
C VARCHAR2(25)
)
/

Next a collection type for the type previously defined must be created.

CREATE OR REPLACE TYPE myTableType
AS TABLE OF myObjectFormat
/

Finally, the producer function is packaged in a package. It is a pipelined function as indicated by the keyword pipelined.

CREATE OR REPLACE PACKAGE myDemoPack
AS
FUNCTION prodFunc RETURN myTableType PIPELINED;
END;
/

CREATE OR REPLACE PACKAGE BODY myDemoPack AS
FUNCTION prodFunc RETURN myTableType PIPELINED IS
BEGIN
FOR i in 1 .. 5
LOOP
PIPE ROW (myObjectFormat(i,SYSDATE+i,'Row '||i));
END LOOP;
RETURN;
END;
END;
/

Test It:

ALTER SESSION SET NLS_DATE_FORMAT='dd.mm.yyyy';
SELECT * FROM TABLE(myDemoPack.prodFunc());

A B C
---------- ---------- ---------
1 31.05.2004 Row 1
2 01.06.2004 Row 2
3 02.06.2004 Row 3
4 03.06.2004 Row 4
5 04.06.2004 Row 5

Conclusion

Pipelined functions are useful if there is a need for a data source other than a table in a select statement.

http://zhouwf0726.itpub.net/post/9689/158239

注册会员

高级会员

精华贴数
1
技术积分
10851
社区积分
52
注册时间
2006-7-30
论坛徽章:
24
生肖徽章:狗
日期:2006-09-07 10:14:43数据库板块每日发贴之星
日期:2008-07-26 01:02:20生肖徽章2007版:兔
日期:2008-10-13 11:10:112008北京奥运纪念徽章:铁人三项
日期:2008-10-24 13:27:21开发板块每日发贴之星
日期:2008-12-27 01:01:09生肖徽章2007版:马
日期:2009-11-18 10:45:032010新春纪念徽章
日期:2010-03-01 11:21:02ITPUB9周年纪念徽章
日期:2010-10-08 09:28:51ERP板块每日发贴之星
日期:2011-05-18 01:01:012012新春纪念徽章
日期:2012-01-04 11:51:22数据库板块每日发贴之星
日期:2008-02-29 01:04:112008新春纪念徽章
日期:2008-02-13 12:43:03
发表于 2007-2-2 10:51:51 |显示全部楼层
好帖,学习了!

使用道具 举报

注册会员

嗜血者

精华贴数
0
技术积分
1023
社区积分
618
注册时间
2006-12-22
论坛徽章:
3
ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44
发表于 2007-7-12 13:36:38 |显示全部楼层
xiexie

使用道具 举报

注册会员

咸&鱼

精华贴数
1
技术积分
2530
社区积分
46
注册时间
2007-3-23
论坛徽章:
8
会员2007贡献徽章
日期:2007-09-26 18:42:10ITPUB新首页上线纪念徽章
日期:2007-10-20 08:38:44生肖徽章2007版:鸡
日期:2008-01-02 17:35:53生肖徽章2007版:猴
日期:2008-01-02 17:35:53生肖徽章2007版:鼠
日期:2008-01-02 17:35:532008新春纪念徽章
日期:2008-02-13 12:43:032009新春纪念徽章
日期:2009-01-04 14:52:28ITPUB十周年纪念徽章
日期:2011-11-01 16:23:26
发表于 2007-7-29 10:04:01 |显示全部楼层
周老师,好例子,收藏了。

使用道具 举报

注册会员

初级会员

精华贴数
0
技术积分
87
社区积分
1
注册时间
2007-9-27
论坛徽章:
0
发表于 2008-12-25 16:55:02 |显示全部楼层
好帖﹗學習了

使用道具 举报

精华贴数
0
技术积分
742
社区积分
19
注册时间
2010-10-25
论坛徽章:
4
2011新春纪念徽章
日期:2011-02-18 11:43:32ITPUB十周年纪念徽章
日期:2011-11-01 16:26:292012新春纪念徽章
日期:2012-01-04 11:57:362012新春纪念徽章
日期:2012-02-07 09:59:35
发表于 2011-11-18 16:39:49 |显示全部楼层
学习了
oracle,mysql,mongodb都需要使用

使用道具 举报

相关内容推荐
您需要登录后才可以回帖 登录 | 注册

TOP技术积分榜 社区积分榜 徽章 电子杂志 团队 统计 邮箱 虎吧 老博客 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档 | IT博客
CopyRight 1999-2011 itpub.net All Right Reserved. 北京皓辰网域网络信息技术有限公司版权所有 联系我们 网站律师 隐私政策 知识产权声明
京ICP证:060528号 北京市公安局海淀分局网监中心备案编号:1101082001 广播电视节目制作经营许可证:编号(京)字第1149号
  
回顶部