Oracle 中 table 函数的应用浅析

表函数可接受查询语句或游标作为输入参数,并可输出多行数据。该函数可以平行执行,并可持续输出数据流,被称作管道式输出。应用表函数可将数据转换分阶段处理,并省去中间结果的存储和缓冲表。

1. 用游标传递数据

利用游标 REF CURSOR 可将数据集(多行记录)传递到PL/SQL函数:

SELECT *
 FROM TABLE (myfunction (CURSOR (SELECT *
         FROM mytab)));  

2. 利用两个实体化视图(或表)作为样板数据

CREATE MATERIALIZED VIEW sum_sales_country_mv
BUILD IMMEDIATE
REFRESH COMPLETE
ENABLE QUERY REWRITE
AS
SELECT SUBSTR (s.calendar_month_desc, 1, 4) YEAR, c.country_id country,
   SUM (sum_amount_sold) sum_amount_sold
 FROM sum_sales_month_mv s, customers c
 WHERE s.cust_id = c.cust_id
  AND c.country_id IN ('US', 'UK', 'FR', 'ES', 'JP', 'AU')
GROUP BY SUBSTR (s.calendar_month_desc, 1, 4), c.country_id
CREATE MATERIALIZED VIEW sum_es_gend_mv
BUILD DEFERRED
REFRESH FAST
ENABLE QUERY REWRITE
AS
SELECT SUBSTR (s.calendar_month_desc, 1, 4) YEAR,
   s.calendar_month_desc cal_month, c.cust_gender,
   SUM (sum_amount_sold) sum_amount_sold
 FROM sum_sales_month_mv s, customer c
 WHERE s.cust_id = c.cust_id
  AND c.country_id = 'ES'
  AND sunstr (s.calendar_month_desc, 1, 4) = '2000'
GROUP BY SUBSTR (s.calendar_month_desc, 1, 4),
   s.calendar_month_desc,
   c.cust_gender;

3. 定义对象类型和基于对象类型的表类型

定义对象类型并且为进一步引用做好准备。

(1)定义对象类型:TYPE sales_country_t

CREATE MATERIALIZED VIEW sum_es_gend_mv
BUILD DEFERRED
REFRESH FAST
ENABLE QUERY REWRITE
AS
SELECT SUBSTR (s.calendar_month_desc, 1, 4) YEAR,
   s.calendar_month_desc cal_month, c.cust_gender,
   SUM (sum_amount_sold) sum_amount_sold
 FROM sum_sales_month_mv s, customer c
 WHERE s.cust_id = c.cust_id
  AND c.country_id = 'ES'
  AND sunstr (s.calendar_month_desc, 1, 4) = '2000'
GROUP BY SUBSTR (s.calendar_month_desc, 1, 4),
   s.calendar_month_desc,
   c.cust_gender;

(2)定义表类型:TYPE SUM_SALES_COUNTRY_T_TAB

CREATE TYPE sum_sales_country_t_tab AS TABLE OF sales_country_t;

(3)定义对象类型:TYPE sales_gender_t

CREATE TYPE sales_gender_t AS OBJECT (
 YEAR    VARCHAR2 (4),
 country_id  CHAR (2),
 cust_gender  CHAR (1),
 sum_amount_sold NUMBER
);

(4)定义表类型:TYPE SUM_SALES_GENDER_T_TAB

CREATE TYPE sum_sales_gender_t_tab AS TABLE OF sales_gender_t;

(5)定义对象类型:TYPE sales_roll_t

CREATE TYPE sales_roll_t AS OBJECT (
 channel_desc  VARCHAR2 (20),
 country_id  CHAR (2),
 sum_amount_sold NUMBER
);

(6)定义表类型:TYPE SUM_SALES_ROLL_T_TAB

CREATE TYPE sum_sales_roll_t_tab AS TABLE OF sales_roll_t;

(7)检查一下建立的类型

SELECT object_name, object_type, status
 FROM user_objects
 WHERE object_type = 'TYPE';

4. 定义包:Create package and define REF CURSOR

CREATE OR REPLACE PACKAGE cursor_pkg
I TYPE sales_country_t_rec IS RECORD (
  YEAR    VARCHAR (4),
  country   CHAR (2),
  sum_amount_sold NUMBER
 );
 TYPE sales_gender_t_rec IS RECORD (
  YEAR    VARCHAR2 (4),
  country_id  CHAR (2),
  cust_gender  CHAR (1),
  sum_amount_sold NUMBER
 );
 TYPE sales_roll_t_rec IS RECORD (
  channel_desc  VARCHAR2 (20),
  country_id  CHAR (2),
  sum_amount_sold NUMBER
 );
 TYPE sales_country_t_rectab IS TABLE OF sales_country_t_rec;
 TYPE sales_roll_t_rectab IS TABLE OF sales_roll_t_rec;
 TYPE strong_refcur_t IS REF CURSOR
  RETURN sales_country_t_rec;
 TYPE row_refcur_t IS REF CURSOR
  RETURN sum_sales_country_mv%ROWTYPE;
 TYPE roll_refcur_t IS REF CURSOR
  RETURN sales_roll_t_rec;
 TYPE refcur_t IS REF CURSOR;
END corsor_pkg;

5. 定义表函数

(1)定义表函数:FUNCTION Table_Ref_Cur_Week

CREATE OR REPLACE FUNCTION table_ref_cur_week (cur CURSOR.refcur_t)
 RETURN sum_sales_country_t_tab
IS
 YEAR    VARCHAR (4);
 country   CHAR (2);
 sum_amount_sold NUMBER;
 objset   sum_sales_country_t_tab := sum_sales_country_t_tab ();
 i     NUMBER     := 0;
BEGIN
 LOOP
-- Fetch from cursor variable
  FETCH cur
  INTO YEAR, country, sum_amount_sold;
  EXIT WHEN cur%NOTFOUND;
      -- exit when last row is fetched
-- append to collection
  i := i + 1;
  objset.EXTEND;
  objset (i) := sales_country_t (YEAR, country, sum_amount_sold);
 END LOOP;
 CLOSE cur;
 RETURN objset;
END;
/

(2)定义表函数:FUNCTION Table_Ref_Cur_Strong

CREATE OR REPLACE FUNCTION table_ref_cur_strong (cur cursor_pkg.strong_refcur_t)
 RETURN sum_sales_country_t_tab PIPELINED
IS
 YEAR    VARCHAR (4);
 country   CHAR (2);
 sum_amount_sold NUMBER;
 i     NUMBER  := 0;
BEGIN
 LOOP
  FETCH cur
  INTO YEAR, country, sum_amount_sold;
  EXIT WHEN cur%NOTFOUND;     -- exit when last row fetched
  PIPE ROW (sales_country_t (YEAR, country, sum_amount_sold));
 END LOOP;
 CLOSE cur;
 RETURN;
END;
/

(3)定义表函数:FUNCTION Table_Ref_Cur_row

CREATE OR REPLACE FUNCTION table_ref_cur_row (cur cursor_pkg.row_refcur_t)
 RETURN sum_sales_country_t_tab PIPELINED
IS
 in_rec cur%ROWTYPE;
 out_rec sales_country_t := sales_country_t (NULL, NULL, NULL);
BEGIN
 LOOP
  FETCH cur
  INTO in_rec;
  EXIT WHEN cur%NOTFOUND;    -- exit when last row is fetched
  out_rec.YEAR := in_rec.YEAR;
  out_rec.country := in_rec.country;
  out_rec.sum_amount_sold := in_rec.sum_amount_sold;
  PIPE ROW (out_rec);
 END LOOP;
 CLOSE cur;
 RETURN;
END;
/

(4)定义表函数:FUNCTION Gender_Table_Ref_Cur_Week

CREATE OR REPLACE FUNCTION gender_table_ref_cur_week (cur cursor_pkg.refcur_t)
 RETURN sum_sales_gender_t_tab
IS
 YEAR    VARCHAR2 (4);
 country_id  CHAR (2);
 cust_gender  CHAR (1);
 sum_amount_sold NUMBER;
 objset   sum_sales_gender_t_tab := sum_sales_gender_t_tab ();
 i     NUMBER     := 0;
BEGIN
 LOOP
  FETCH cur
  INTO YEAR, country_id, cust_gender, sum_amount_sold;
  EXIT WHEN cur%NOTFOUND;    -- exit when last row is fetched
  i := i + 1;
  objset.EXTEND;
  objset (i) :=
   sum_sales_gender_t (YEAR, country_id, cust_gender, sum_amount_sold);
 END LOOP;
 CLOSE cur;
 RETURN objset;
END;
/

6. 调用表函数

下列 SQL 查询语句调用已被定义的表函数。

SELECT *
 FROM TABLE (table_ref_cur_week (CURSOR (SELECT *
           FROM sum_sales_country_mv)));
SELECT *
 FROM TABLE (table_ref_cur_strong (CURSOR (SELECT *
            FROM sum_sales_country_mv)));
SELECT *
 FROM TABLE (table_ref_cur_row (CURSOR (SELECT *
           FROM sum_sales_country_mv)));
SELECT *
 FROM TABLE (table_ref_cur_week (CURSOR (SELECT *
           FROM sum_sales_country_mv
           WHERE country = 'AU')));

以上所述是小编给大家介绍的Oracle 中 table 函数的应用浅析,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Oracle minus用法详解及应用实例

    Oracle minus用法 "minus"直接翻译为中文是"减"的意思,在Oracle中也是用来做减法操作的,只不过它不是传统意义上对数字的减法,而是对查询结果集的减法.A minus B就意味着将结果集A去除结果集B中所包含的所有记录后的结果,即在A中存在,而在B中不存在的记录.其算法跟Java中的Collection的removeAll()类似,即A minus B将只去除A跟B的交集部分,对于B中存在而A中不存在的记录不会做任何操作,也不会抛出异常. Ora

  • Oracle 删除用户和表空间详细介绍

    Oracle 删除用户和表空间 Oracle 使用时间长了, 新增了许多user 和tablespace. 需要清理一下 对于单个user和tablespace 来说, 可以使用如下命令来完成.  步骤一:  删除user drop user ×× cascade 说明: 删除了user,只是删除了该user下的schema objects,是不会删除相应的tablespace的. 步骤二: 删除tablespace DROP TABLESPACE tablespace_name INCLUDI

  • Oracle 11g Client客户端安装教程

    很多时候我们本机电脑不需要安装oracle数据库(因为oracle数据库过于庞大,个人电脑安装之后运行起来会比较慢),只要安装一个oracle客户端,然后通过配置PL/SQL即可以连接远程服务器上面的oracle数据库.但在安装客户端的时候会遇到一些问题,如何解决请看下面步骤 工具:win32_11gR2_client 方法/步骤: 安装包里点击setup.exe可执行程序,选择"运行时"点下一步 选择简体中文点下一步 选择要安装的路径点下一步 执行"先决条件检查"

  • oracle 11g配置 解决启动连接数据库出现的ora错误

    按照网上方法并结合实践,整理了一下(以后忘记了可以看看),oracle登录问题的解决办法: 常见的登录连接oracle数据库时遇到的问题ora-12560,01034,27101,00119,00132等,可以按照以下步骤检查和解决. Oracle11g数据库监听,数据库启动  1.添加监听程序(服务器端) 打开net manager 添加监听 添加监听位置(网络地址) 添加数据库服务(oracle主目录可以不填) 2.添加服务命名  3.测试 利用服务器端sqlplus工具E:\app\204

  • 使用PHP连接多种数据库的实现代码(mysql,access,sqlserver,Oracle)

    1.PHP连接MYSQL数据库的代码 <?php $mysql_server_name='localhost'; //改成自己的mysql数据库服务器 $mysql_username='root'; //改成自己的mysql数据库用户名 $mysql_password='12345678'; //改成自己的mysql数据库密码 $mysql_database='mycounter'; //改成自己的mysql数据库名 $conn=mysql_connect($mysql_server_name,

  • 给Oracle添加split和splitstr函数的方法

    最近项目中有很多需要做批量操作的需求,客户端把一组逗号分隔的ID字符串传给数据库,存储过程就需要把它们分割,然后逐个处理. 以往的处理方式有如下几种: 1.在存储过程内写循环,逐个分析字符串中的ID,然后逐个处理.缺点:循环一次处理一个,如果每次判断都很多,效率将很受影响.适合每次处理要做单独判断的情况. 2.使用临时表,先调用一个存储过程将ID拆分并插入到临时表中,然后结合临时表可以写SQL一次处理多笔.缺点:需要插临时表,效率不高,数据量越大影响越严重. 以前的项目用的最多的还是第2中方式,

  • 完美卸载Oracle数据库

    最近因为要写一个项目的接口,需要远程的连接oracle数据库,刚开始的时候因为我本地只装了MySQL,所以用就连接了本地MySQL,接口大体完事有在tomcat中测试了下,也能跑通,但是后来又要改数据库,所以就想安装一个本地的oracle测试一下,这一安装就是一个下午外带一个晚上啊,所以把这个血泪史分享一下.安装过oracle的同学相信都卸载过oracle(这句话听着挺有毛病,但是真正操作过的人就不会觉得奇怪了),基本上每次安装oracle都会出现这样或那样的问题,随意卸载oracle变得非常重

  • Oracle中转义字符的详细介绍

    最近工作中遇到一个需求,需要更新Oracle数据库中所有表的一个字段"flag"为"I",语句为: update table_name set flag = 'I' "I"作为字符串,所以语句中I需要加上单引号. 由于数据库中有多张表,我不想一条一条的语句写,希望能够通过sql语句直接生成所有的语句,所以写了如下sql: select 'update ' || table_name || ' set flag = 'I'' || ';' from

  • Oracle用户密码设为不过期的两种方法

    1.在SQL Plus下,以DBA身份登陆 用户名/密码@服务器SID as sysdba 方法一:(注意必须用双引号把后面的引上) C:/Documents and Settings/ssy>sqlplus sys/system@test as sysdba SQL*Plus: Release 9.2.0.1.0 - Production on 星期一 3月 17 18:01:41 2008 Copyright (c) 1982, 2002, Oracle Corporation. All r

  • Oracle 自定义split 函数实例详解

    Oracle 自定义split 函数 Oracle没有提供split函数,但可以自己建立一个函数实现此功能.比如"abc defg  hijkl   nmopqr     stuvw  xyz",分隔符是空格,但空格个数不定. 源代码: CREATE OR REPLACE TYPE ty_str_split IS TABLE OF VARCHAR2 (4000); CREATE OR REPLACE FUNCTION fn_var_split ( p_str IN VARCHAR2,

随机推荐