Oracle管道函数(Pipelined Table Function)介绍

一 概述:

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;

[email protected]> 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)介绍

时间: 2024-10-11 05:07:41

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

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

1. 简单的例子(返回单列的表) 1>创建一个表类型 create or replace type t_table is table of number; 2>创建函数返回上面定义的类型 create or replace function f_pipe(s number) return t_table pipelined as v_number number; begin for i in 1..s loop v_number := i; pipe row(v_number); end lo

oracle管道函数的用法

oracle管道函数是一类特殊的函数,oracle管道函数返回值类型必须为集合,下面将介绍oracle管道函数的语法. 在普通的函数中,使用dbms_output输出的信息,需要在服务器执行完整个函数后一次性的返回给客户端.如果需要在客户端实时的输出函数执行过程中的一些信息,在oracle9i以后可以使用管道函数(pipeline function). 关键字PIPELINED表明这是一个oracle管道函数,oracle管道函数的返回值类型必须为集合,在函数中,PIPE ROW语句被用来返回该

在Oracle/SQL Service中通过Function返回Table

本函数用途:返回一个Table 在Oracle中实现,范例: 1 --在Types中: 2 create or replace type objTable as object 3 ( 4 s_usercode varchar2(32767), 5 s_username varchar2(32767) 6 ); 7 8 CREATE OR REPLACE TYPE tabTemp AS TABLE OF objtable; 9 10 11 --在Function中: 12 --使用Pipeline

浅谈Oracle函数返回Table集合

在调用Oracle函数时为了让PL/SQL 函数返回数据的多个行,必须通过返回一个 REF CURSOR 或一个数据集合来完成.REF CURSOR 的这种情况局限于可以从查询中选择的数据,而整个集合在可以返回前,必须进行具体化. 9i 通过引入Oracle函数中的管道化表函数纠正了后一种情况.表函数是返回整个行的集(通常作为一个集合)的函数,可以直接从 SQL 语句中进行查询,就好像它是一个真正的数据库表一样.管道化表函数与之相似,但是它像在构建时一样返回数据,而不是一次全部返回.管道化表函数

Oracle DETERMINISTIC函数、PARALLEL_ENABLE函数、PIPELINED函数、RESULT_CACHE函数

1.DETERMINISTIC函数 -- Create deterministic PV function. CREATE OR REPLACE FUNCTION pv ( future_value NUMBER , periods NUMBER , interest NUMBER ) RETURN NUMBER DETERMINISTIC IS BEGIN RETURN future_value / ((1 + interest/100)**periods); END pv; 2.PARALL

Oracle Table Function

Oracle Table Function在Oracle9i时引入,完美的兼容了view和存储过程的优点: 应用举例: 1.Table()函数: set feedback off create or replace type type_int_date_varchar2 as object (i integer, d date, v varchar2(99)) / create or replace type table_int_date_varchar2 as table of type_in

Oracle to_date()函数的用法介绍

to_date()是Oracle数据库函数的代表函数之一,下文对Oracle to_date()函数的几种用法作了详细的介绍说明,需要的朋友可以参考下 在Oracle数据库中,Oracle to_date()函数是我们经常使用的函数,下面就为您详细介绍Oracle to_date()函数的用法,希望可以对您有所启迪. to_date()与24小时制表示法及mm分钟的显示: 一.在使用Oracle的to_date函数来做日期转换时,很多Java程序员也许会直接的采用"yyyy-MM-dd HH:m

oracle REPLACE 函数 介绍

oracle REPLACE 函数是用另外一个值来替代串中的某个值. 例如,可以用一个匹配数字来替代字母的每一次出现.REPLACE 的格式如下所示: REPLACE ( char, search_string [, replace_string]) 如果没有指定replace_string 变量的值,那么当发现search_string 变量的值时,就将其删除.输入可以为任何字符数据类型——CHAR.VARCHAR2.NCHAR.NVARCHAR2.CLOB或NCLOB. 下面是 使用repl

JS特殊函数(Function()构造函数、函数直接量)区别介绍

函数定义 函数是由这样的方式进行声明的:关键字 function.函数名.一组参数,以及置于括号中的待执行代码. 函数的构造语法有这三种: 1.function functionName(arg0, arg1, ... argN) { statements }//function语句 2.var function_name = new Function(arg1, arg2, ..., argN, function_body);//Function()构造函数 3.var func = func