在PL/SQL中,如果要返回数据的多个行,必须通过返回一个REF CURSOR的游标,或者一个数据集合(如临时表或物理表)来完成,而REF CURSOR的局限于可以从查询中选择的数据,而数据集合的局限性在于必须先CREATE TABLE(无论是创建临时表还是物理表)来进行具体化,具体化后,会因为频繁删除表导致大量的碎片。
  Oracle 9i开始,引入了管道化表函数,解决了这种情况。
  管道化表函数是返回整个行的集合的函数,可以直接在SQL中进行查询,他就好像是真正的数据库表一样。他存在于内存中,比物理表速度要快几十倍。
  管道化表函数必须返回一个集合,在函数中PIPE ROW 语句被用来返回该集合的单个元素,该函数必须以一个空的RETURN语句结束,以表明他已经完成。一旦创建了该函数,就可以使用TABLE()操作符从SQL查询中来调用它。
  使用管道化表函数需要定义以下内容:
  1. 定义一个OBJECT类型的TYPE

CREATE TYPE TY_OBJ AS OBJECT ();

2. 定义一个TYPE继承了这个TY_OBJ;

CREATE TYPE TA_OBJ AS TABLE OF TY_OBJ;

3. 创建一个管道化函数

CREATE OR REPLACE FUNCTION FUN_NAME RETURN TA_OBJ PIPELINED
IS
BEGIN
……
PIPE ROW ();
EXCEPTION
END;

下面是一个管道化表函数的例子。

CREATE TYPE TY_NUMLIST AS OBJECT(
N1 NUMBER,
N2 VARCHAR2(50)
);
CREATE TYPE TA_NUMLIST AS TABLE OF TY_NUMLIST; CREATE OR REPLACE FUNCTION FN_NUM RETURN TA_NUMLIST PIPELINED
IS
FV_NUMLIST TY_NUMLIST; BEGIN
FOR x IN 1.. 20 LOOP
fv_numlist := ty_numlist(x, 'Row'||x);
pipe row (fv_numlist);
END LOOP;
return;
END;
--接下来可以查询结果了;
SELECT * FROM table(fn_num);

这个管道化函数是可以带参数的,比如:创建时,使用了id这个参数

CREATE FUNCTION MY_FUN(id number) RETURN TT PIPELINED;
--那么查询时,可以这样调用
SELECT * FROM table(mu_fun(11));

下面是一些比较复杂的用法:把一个查询的结果通过管道化函数来返回。
1. 创建TYPE

CREATE OR REPLACE TYPE ty_prov AS object
(
prov_id number(8),
prov_code varchar2(9),
eng_code varchar2(9),
prov_name varchar2(12)
)

2. 创建TYPE

CREATE OR REPLACE TYPE ta_prov AS TABLE OF ty_prov

3.创建管道化函数

CREATE OR REPLACE FUNCTION getProvMsg(pp_code varchar2) return ta_prov pipelined
IS fv_prov ty_prov; BEGIN
for x in (SELECT prov_id, prov_code, eng_nm, prov_name FROM bam_t01_province_def WHERE prov_code = pp_code) loop fv_prov := ty_prov(x.prov_id, x.prov_code, x.eng_nm, x.prov_name); pipe row (fv_prov); end loop;
return; EXCEPTION
when others THEN
raise_application_error(-20001,'getProvMsg : '||sqlerrm );
END;

4. 使用下面语句来查询

SQL> select * from table(getProvmsg('')) ;

   PROV_ID PROV_CODE ENG_CODE  PROV_NAME
---------- --------- --------- ------------
10100 100 BJ 北京

以上参考自:http://blog.csdn.net/jojo52013145/article/details/6758279

关于效率的小知识:
  对于物理表,他的数据存储在物理磁盘上,当数据第一次被READ时,会被load到db cache中,根据LRU算法来决定这些数据会否置换出内存。如果数据一直在内存中,他会被所有session共享,由于数据是机构化的,所以在内存中扫描的效率是最高的。
  对于临时表,它和它的索引都是创建在临时表空间上的,当在一个SESSION中第一次插入数据时,才开始在用户的默认临时表空间下分配临时数据段,不同的SESSION拥有不同的段,以保证不同会话不会相互影响。临时表的数据也是结构化的,第一次读取数据后,数据也会被CACHE到db cache中。
  TABLE()函数是9i的新特性,实际上是将一个存储在内存中的对象结构化后,使这个对象能以表的形式来查询。对象是以流的方式存储的,对流的结构化转换会导致效率下降。所以它的效率应该低于存在于内存中的物理表和临时表。(但应该高于第一次装载入内存的物理表和临时表)

关于对内存的影响:
  网上几乎没有资料提及这个TABLE()特性对SGA和PGA造成的严重影响。所以我们暂且忽略吧。或者有高手帮忙补充补充~!

from:封烨

Oracle 管道化表函数的更多相关文章

  1. 【转】oracle查询用户表,函数,储存过程,

    ◆Oracle查询用户表空间:select * from user_all_tables ◆Oracle查询所有函数和储存过程:select * from user_source ◆Oracle查询所 ...

  2. ORACLE 表函数实现

    1.创建表对象类型. 在Oracle中想要返回表对象,必须自定义一个表类型,如下所示: create or replace type t_table is table of number; 上面的类型 ...

  3. WPF根据Oracle数据库的表,生成CS文件小工具

    开发小工具的原因: 1.我们公司的开发是客户端用C#,服务端用Java,前后台在通讯交互的时候,会用到Oracle数据库的字段,因为服务器端有公司总经理开发的一个根据Oracle数据库的表生成的cla ...

  4. Oracle索引梳理系列(六)- Oracle索引种类之函数索引

    版权声明:本文发布于http://www.cnblogs.com/yumiko/,版权由Yumiko_sunny所有,欢迎转载.转载时,请在文章明显位置注明原文链接.若在未经作者同意的情况下,将本文内 ...

  5. Oracle中dual表的用途介绍

    导读]dual是一个虚拟表,用来构成select的语法规则,oracle保证dual里面永远只有一条记录.我们可以用它来做很多事情.     dual是一个虚拟表,用来构成select的语法规则,or ...

  6. 【转】Oracle中dual表的用途介绍

    原文:Oracle中dual表的用途介绍 [导读]dual是一个虚拟表,用来构成select的语法规则,oracle保证dual里面永远只有一条记录.我们可以用它来做很多事情. dual是一个虚拟表, ...

  7. 删除Oracle用户及表空间

    --转载自 https://blog.csdn.net/sunny05296/article/details/81126548--以sysdba用户登录,查找需要删除的用户conn / as sysd ...

  8. Oracle中的substr()函数 详解及应用

    注:本文来源于<Oracle中的substr()函数 详解及应用> 1)substr函数格式   (俗称:字符截取函数) 格式1: substr(string string, int a, ...

  9. oracle存储过程和存储函数&触发器

    oracle存储过程和存储函数 指存储在数据库中供所有用户程序调用的子程序叫存储过程,存储函数 存储过程和存储函数的相同点:完成特定功能的程序 存储过程和存储函数的区别:是否用return语句返回值 ...

随机推荐

  1. asp.net与Matlab类型转换(待补全)

    上上篇的博客已经提到如何配置环境,即如何在asp.net中调用matlab生成的dll文件.这篇博客打算做个笔记,那就是matlab和C#数据类型如何转换.随着需求的增加,我会不断增加新的类型转换. ...

  2. C#------DateTime自定义格式

    var text = Convert.ToString(DateTime.Now.ToString("yyyy/MM/dd"));

  3. mysql create db utf8 character

    create database if not exists wifi default character set utf8;

  4. mysql主从复制 转

    mysql服务器的主从配置,这样可以实现读写分离,也可以在主库挂掉后从备用库中恢复.需要两台机器,安装mysql,两台机器要在相通的局域网内,可以分布在不同的服务器上,也可以在一台服务器上启动多个服务 ...

  5. 10月21上午PHP基础

    新建的php文件必须要放在wamp安装目录下的www文件夹里.如果拿到别的地方,php无法运行,将显示错误. <?php?> //嵌入php的方式 <?php //嵌入php方式的开 ...

  6. 20145212 《Java程序设计》第2周学习总结

    20145212 <Java程序设计>第2周学习总结 教材学习内容总结 第二周主要学习了Java的基本语法,在第一周熟悉了Java基本操作的基础上我们可以自行的利用这些语法编译具有实用价值 ...

  7. HBase命令(三) -- 增删改查

    新增 //语法:put <table>,<rowkey>,<family:column>,<value>,<timestamp> //新增或 ...

  8. 通过mongodb客户端samus代码研究解决查询慢问题

    最近有项目需要用到mongodb,于是在网上下载了mongodb的源码,根据示例写了测试代码,但发现一个非常奇怪的问题:插入记录的速度比获取数据的速度还要快,而且最重要的问题是获取数据的速度无法让人接 ...

  9. C#数字格式化

    格式规范的完整形式:{index [,width][:formatstring]} index是此格式程序引用的格式字符串之后的参数,从零开始计数:width(可选) 是要设置格式的字段的宽度,wid ...

  10. 关于在windows上的wamp集成环境和xampp上安装mongo扩展

    今天来学习下mongodb,在装PHP扩展的时候本来是一个很轻松的事情,结果并不是我想想的那么简单. 我的集成环境是xampp的php版本是5.6的x86.我开启了安全模式,所以我需要mongo时ts ...