一 概述:

1、管道函数即是能够返回行集合(能够使嵌套表nested table 或数组 varray)的函数,我们能够像查询物理表一样查询它或者将其

 赋值给集合变量。

2、管道函数为并行运行,在普通的函数中使用dbms_output输出的信息,须要在server运行完整个函数后一次性的返回给client。假设须要在client

实时的输出函数运行过程中的一些信息,在oracle9i以后能够使用管道函数(pipeline function)。

3、keywordPIPELINED表明这是一个oracle管道函数,oracle管道函数的返回值类型必须为集合,在函数中,PIPE ROW语句被用来返回该集合的单个元

素,函数以一个空的RETURN 语句结束,以表明它已经完毕。

4、因为管道函数的并发多管道流式设计以及实时返回查询结果而去除了中间环节因此能够带来可观的性能提升。

二、怎样编写管道函数:

        例1:
CREATE OR REPLACE PACKAGE pkg1 AS
TYPE numset_t IS TABLE NUMBER;
FUNCTION f1(x NUMBER) RETURN numset_t PIPELINED;
END pkg1;
CREATE OR REPLACE PACKAGE BODY pkg1 AS
FUNCTION f1(x NUMBER) RETURN numset_t PIPELINED IS
BEGIN
FOR i IN 1..x LOOP
PIPE ROW(i);
END LOOP;
RETURN;
END;
END pkg1;
SELECT * FROM TABLE(pkg1.f1(5));

COLUMN_VALUE

------------------------

           1

           2

           3

           4

           5

三 管道函数用于数据转换:


例2:管道函数能够和常规函数一样接收不论什么參数,以下的管道函数中參数为ref cursor。

CREATE OR REPLACE PACKAGE refcur_pkg IS
TYPE refcur_t IS REF CURSOR RETURN emp%ROWTYPE;
TYPE outrec_typ IS RECORD (
var_num NUMBER(6),
var_char1 VARCHAR2(30),
var_char2 VARCHAR2(30));
TYPE outrecset IS TABLE OF outrec_typ;
FUNCTION f_trans(p refcur_t)
RETURN outrecset PIPELINED;
END refcur_pkg;
CREATE OR REPLACE PACKAGE BODY refcur_pkg IS
FUNCTION f_trans(p refcur_t)
RETURN outrecset PIPELINED IS
out_rec outrec_typ;
in_rec p%ROWTYPE;
BEGIN
LOOP
FETCH p INTO in_rec;
EXIT WHEN p%NOTFOUND;
-- first row
out_rec.var_num := in_rec.empno;
out_rec.var_char1 := in_rec.ename;
out_rec.var_char2 := in_rec.mgr;
PIPE ROW(out_rec);
-- second row
out_rec.var_num := in_rec.deptno;
out_rec.var_char1 := in_rec.deptno;
out_rec.var_char2 := in_rec.job;
PIPE ROW(out_rec);
END LOOP;
CLOSE p;
RETURN;
END;
END refcur_pkg;
SELECT * FROM TABLE(
refcur_pkg.f_trans(CURSOR(SELECT * FROM emp WHERE empno=7782)));

VAR_NUM       VAR_CHAR1           VAR_CHAR2

---------- ------------------------------ ------------------------------

      7782       CLARK                          7839

        10         10                             MANAGER



四 使用方法扩展:

1、表函数间传递数据:
SELECT * FROM TABLE(f(CURSOR(SELECT * FROM TABLE(g()))));

2、使用游标变量接收管道函数返回的结果:
OPEN c FOR SELECT * FROM TABLE(f(...));

3、使用多个游标变量入參:

例3:
-- Define the ref cursor types
CREATE PACKAGE refcur_pkg IS
TYPE refcur_t1 IS REF CURSOR RETURN employees%ROWTYPE;
TYPE refcur_t2 IS REF CURSOR RETURN departments%ROWTYPE;
TYPE outrec_typ IS RECORD (
var_num NUMBER(6),
var_char1 VARCHAR2(30),
var_char2 VARCHAR2(30));
TYPE outrecset IS TABLE OF outrec_typ;
FUNCTION g_trans(p1 refcur_t1, p2 refcur_t2)
RETURN outrecset PIPELINED;
END refcur_pkg;
/ CREATE PACKAGE BODY refcur_pkg IS
FUNCTION g_trans(p1 refcur_t1, p2 refcur_t2)
RETURN outrecset PIPELINED IS
out_rec outrec_typ;
in_rec1 p1%ROWTYPE;
in_rec2 p2%ROWTYPE;
BEGIN
LOOP
FETCH p2 INTO in_rec2;
EXIT WHEN p2%NOTFOUND;
END LOOP;
CLOSE p2;
LOOP
FETCH p1 INTO in_rec1;
EXIT WHEN p1%NOTFOUND;
-- first row
out_rec.var_num := in_rec1.employee_id;
out_rec.var_char1 := in_rec1.first_name;
out_rec.var_char2 := in_rec1.last_name;
PIPE ROW(out_rec);
-- second row
out_rec.var_num := in_rec2.department_id;
out_rec.var_char1 := in_rec2.department_name;
out_rec.var_char2 := TO_CHAR(in_rec2.location_id);
PIPE ROW(out_rec);
END LOOP;
CLOSE p1;
RETURN;
END;
END refcur_pkg;
/ -- SELECT query using the g_trans table function
SELECT * FROM TABLE(refcur_pkg.g_trans(
CURSOR(SELECT * FROM employees WHERE department_id = 60),
CURSOR(SELECT * FROM departments WHERE department_id = 60)));


4、管道函数作为聚合函数使用:

例4:
CREATE TABLE gradereport (student VARCHAR2(30), subject VARCHAR2(30),
weight NUMBER, grade NUMBER);
INSERT INTO gradereport VALUES('Mark', 'Physics', 4, 4);
INSERT INTO gradereport VALUES('Mark','Chemistry', 4, 3);
INSERT INTO gradereport VALUES('Mark','Maths', 3, 3);
INSERT INTO gradereport VALUES('Mark','Economics', 3, 4); CREATE PACKAGE pkg_gpa IS
TYPE gpa IS TABLE OF NUMBER;
FUNCTION weighted_average(input_values SYS_REFCURSOR)
RETURN gpa PIPELINED;
END pkg_gpa;
/
CREATE PACKAGE BODY pkg_gpa IS
FUNCTION weighted_average(input_values SYS_REFCURSOR)
RETURN gpa PIPELINED IS
grade NUMBER;
total NUMBER := 0;
total_weight NUMBER := 0;
weight NUMBER := 0;
BEGIN
-- The function accepts a ref cursor and loops through all the input rows
LOOP
FETCH input_values INTO weight, grade;
EXIT WHEN input_values%NOTFOUND;
-- Accumulate the weighted average
total_weight := total_weight + weight;
total := total + grade*weight;
END LOOP;
PIPE ROW (total / total_weight);
RETURN; -- the function returns a single result
END;
END pkg_gpa;
/
-- the query result comes back as a nested table with a single row
-- COLUMN_VALUE is a keyword that returns the contents of a nested table
SELECT w.column_value "weighted result" FROM TABLE(
pkg_gpa.weighted_average(CURSOR(SELECT weight, grade FROM gradereport))) w;


5、在管道函数中进行DML操作,我们使用自治事务使管道函数作为独立事务处理:

CREATE FUNCTION f(p SYS_REFCURSOR)

  RETURN CollType PIPELINED IS

    PRAGMA AUTONOMOUS_TRANSACTION;

BEGIN 
NULL; 
END;

/

6、对管道函数进行DML操作:


实际上我们无法直接对管道函数进行DML操作,比例如以下面语句都会失败:


UPDATE F(CURSOR(SELECT * FROM tab)) SET col = value;

  INSERT INTO f(...) VALUES ('any', 'thing');



官方给出的方案是创建一个基于管道函数的VIEW,然后在这个VIEW上创建对应的instead of 触发器。以下给出操作实例:


CREATE OR REPLACE VIEW V_F_TRANS AS
SELECT x.var_num, x.var_char1, x.var_char2
FROM TABLE(refcur_pkg.f_trans(CURSOR (SELECT *
FROM emp))) x;
CREATE OR REPLACE TRIGGER tri_f_trans
INSTEAD OF INSERT ON v_f_trans
FOR EACH ROW
BEGIN
dbms_output.put_line('Trigger of a pipelined funtion based view was on fire!');
END;

SCOTT@orcl> insert into v_f_trans values(102, 'abc','def');

Trigger of a pipelined funtion based view was on fire!



























---------------------------------------
By    Dylan.





Oracle管道函数(Pipelined Table Function)介绍的更多相关文章

  1. Oracle管道函数(Pipelined Table Function)实现的实例

    1. 简单的例子(返回单列的表) 1>创建一个表类型 create or replace type t_table is table of number; 2>创建函数返回上面定义的类型 ...

  2. oracle管道函数的用法

    oracle管道函数是一类特殊的函数,oracle管道函数返回值类型必须为集合,下面将介绍oracle管道函数的语法. 在普通的函数中,使用dbms_output输出的信息,需要在服务器执行完整个函数 ...

  3. oracle管道函数的用法(一行拆为多行)

    oracle管道函数是一类特殊的函数,oracle管道函数返回值类型必须为集合 如果需要在客户端实时的输出函数执行过程中的一些信息,在oracle9i以后可以使用管道函数(pipeline funct ...

  4. 管道函数(pipelined function)简单使用示例

    -----------------------------Cryking原创------------------------------ -----------------------转载请注明出处, ...

  5. Oracle管道函数示例

    Oracle的管道函数需要定义下面的三样: Record/Object Type:定义一个Record或Object类型的变量,这个变量用于表示返回结果集的一行数据,有点像C#中的DataRow类. ...

  6. ABAP CDS Table Function介绍与示例

    Core data services(以下简称CDS)可以指两样东西,一个是HANA CDS,一个是ABAP CDS. 如我们所知,HANA CDS只支持HANA数据库,ABAP CDS理论上支持多种 ...

  7. Oracle Pipelined Table Functions简介

    转自: http://www.linuxidc.com/Linux/2011-05/35797.htm //概况   //基本上,当你希望一个PLSQL(或者java或者c)程序作为数据源,而不是表, ...

  8. R语言(自定义函数、循环语句、管道函数)

    学习R语言半年多了,以前比较注重统计方法上的学习,但是最近感觉一些基础知识也很重要.去年的参考资料是<R语言实战>,今年主要是看视频.推荐网易云课堂里的教程,很多资料都是很良心的~ 目前学 ...

  9. 浅谈Oracle函数返回Table集合

    在调用Oracle函数时为了让PL/SQL 函数返回数据的多个行,必须通过返回一个 REF CURSOR 或一个数据集合来完成.REF CURSOR 的这种情况局限于可以从查询中选择的数据,而整个集合 ...

随机推荐

  1. 通过Qt样式表定制程序外观(比较通俗易懂)

    1. 何为Qt样式表[喝小酒的网摘]http://blog.hehehehehe.cn/a/10270.htm2. 样式表语法基础3. 方箱模型4. 前景与背景5. 创建可缩放样式6. 控制大小7. ...

  2. QT学习 之 QwtPlot(数学绘图)

    QT对于统计图像.函数图像等的绘制是没有相关组件的帮助的,只有利用手工绘制图片. QwtPlot是用来绘制二维图像的widget,继承自QFrame 和 QwtPlotDict.不过严格的说来,它只是 ...

  3. wchar_t是内置还是别名(亲测有效:wchar_t在windows下是16位整数的别名,在linux等平台下是32位整数的别名。MSVC2008开始默认是/Zc:wchar_t)

    接前一篇C++ ABI之名字改编(以Qt为例),继续看看C++名字改编相关的问题. 问题 MSVC 有一对选项/Zc:wchar_t- 与 /Zc:wchar_t控制wchar_t 于是 wchar_ ...

  4. elk 架构

  5. Niagara技术文档汇总

    Niagara技术文档汇总http://wenku.baidu.com/view/ccdd4e2c3169a4517723a38f.html Niagara讲解要点http://wenku.baidu ...

  6. ZOJ 1825 compoud words

    题目大意:输入一串递增的单词序列,需要找出符合条件的单词递增输出,条件是:将一个单词拆成左右两个单词后,能在输入中找到这两个单词.例如单词 alien,可以拆成 a 和 lien,而输入中刚好同时有a ...

  7. Python 連接 MySQL

    Python 連接 MySQL MySQL 是十分流行的開源資料庫系統,很多網站也是使用 MySQL 作為後台資料儲存,而 Python 要連接 MySQL 可以使用 MySQL 模組.MySQLdb ...

  8. PIGS(最大流)

    PIGS Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 18742   Accepted: 8511 Description ...

  9. 自己动手为PHP7添加新的语法特性

    好文章! nikic介绍了如何向PHP添加新的语法特性,原文写的非常精彩,具体是添加in语法功能,使最终实现: <?php $words = ['hello', 'world', 'foo', ...

  10. 分享,iOS国家手机区号代码.plist

    APP注册需要手机号码的时候,如果有在其他国家的时候需要填写手机区号 一份有国家名字和区号的plist 参照微信注册的时候 格式是 <Array> <Array> <Ar ...