`
pengfeng
  • 浏览: 231729 次
  • 性别: Icon_minigender_1
  • 来自: 河南
社区版块
存档分类
最新评论

oracle管道化表函数

阅读更多

在我所做过和参与的大多数项目中,都会有用户提出的复杂的一些统计报表之内的功能要求,根据统计的复杂程度、效率及JAVA程序调用的方便性方面考虑,主要总结出以下几种方案:

1、SQL语句

该方案只能实现一些相对简单些的查询统计功能,语句嵌套多、写起来特别复杂,使程序的可读性变差,下面是实现一个按照上级机关统计下级各个公安机关管辖范围内对应的各个类别社会单位数量的统计功能的SQL:

select rpad(gajg_dm,12,'0'), 
  sum(decode(C01, 0, 0, C01)) as C01,
  sum(decode(C02, 0, 0, C02)) as C02,
  sum(decode(C03, 0, 0, C03)) as C03,
  sum(decode(C04, 0, 0, C04)) as C04,
  sum(decode(C05, 0, 0, C05)) as C05,
  sum(decode(C06, 0, 0, C06)) as C06,
  sum(decode(C07, 0, 0, C07)) as C07,
  sum(decode(C08, 0, 0, C08)) as C08,
  sum(decode(C09, 0, 0, C09)) as C09,
  sum(decode(C10, 0, 0, C10)) as C10,
  sum(decode(C11, 0, 0, C11)) as C11
  from
  (
    select substr(b.gajg_dm,0,decode(substr(b.gajg_dm,0,8),'41000030',8,'41000006',8,'41000061',8,'41000060',8,4)) gajg_dm,/*b.gajg_dm,*/ cslb_dm, 
      sum(decode(cslb_dm, '01', 1, 0)) as C01,
      sum(decode(cslb_dm, '02', 1, 0)) as C02,
      sum(decode(cslb_dm, '03', 1, 0)) as C03,
      sum(decode(cslb_dm, '04', 1, 0)) as C04,
      sum(decode(cslb_dm, '05', 1, 0)) as C05,
      sum(decode(cslb_dm, '06', 1, 0)) as C06,
      sum(decode(cslb_dm, '07', 1, 0)) as C07,
      sum(decode(cslb_dm, '08', 1, 0)) as C08,
      sum(decode(cslb_dm, '09', 1, 0)) as C09,
      sum(decode(cslb_dm, '10', 1, 0)) as C10,
      sum(decode(cslb_dm, '11', 1, 0)) as C11
      from yf_cs_jbxx a, dm_gajg b where b.gajg_dm=a.gajg_dm(+) and b.gajg_dm like '41%' --and b.gajg_pcs_bz<>'N' 
     --group by substr(b.gajg_dm,0,4), cslb_dm
     group by substr(b.gajg_dm,0,decode(substr(b.gajg_dm,0,8),'41000030',8,'41000006',8,'41000061',8,'41000060',8,4)),cslb_dm
   ) t group by rpad(gajg_dm,12,'0')--gajg_dm

在该SQL语句中,主要有三个步骤:

1)统计各个机关下各个类别的单位数量

2)对编码不规则机关进行decode和截位处理

3)对1中的统计结果进行行列转换

够复杂了吧,而且还很别扭,看着就晕。。。。更别说代码数据再发生点变化了

 

2、存储过程返回游标

对于该方案是被我们直接PASS掉的一种方案,主要考虑其性能太差,这里就不再啰嗦了

 

3、临时表(或中间表)

对于该方案主要分为两步完成统计:

1)通过存储过程或函数完成对数据的统计

2)将统计结果插入到临时表中

这样程序在执行统计时就要求先调用执行统计的存储过程,然后再查询临时表以取出存储过程产生的统计结果

 

呵呵,每个统计还要对应建一个临时表,看着就闲麻烦。。。

 

4、管道表函数

管道化表函数是我见过的最佳的实现统计的解决方案(当然是在我做的项目中,具体东西具体环境具体应用吗),这里给出两个实例和说明,供大家参考,但该方案同样有一个缺点,就是在PLSQL下调试极其不方面,但基本还能忍受

CREATE OR REPLACE PACKAGE pkg1 AS
  -- Purpose : 对表函数的应用实例
  TYPE ty_rec_user IS record (--定义一个record类型的TYPE
       id number(20),
       name varchar2(60)
  );
  TYPE out_rec_set is table of ty_rec_user;--定义一个嵌套表集合类型out_rec_set,作为表函数的返回类型
  --定义返回集合类型的管道表函数
  FUNCTION f1(x NUMBER) RETURN out_rec_set PIPELINED;
  
  --引用在外部自定义的object类型作为表函数的集合类型
  TYPE out_obj_set is table of TY_OBJ_USER;
  FUNCTION F_PIE_TEST(c NUMBER) RETURN out_obj_set PIPELINED;
END pkg1;


CREATE OR REPLACE PACKAGE BODY pkg1 AS
  -- Purpose : 对表函数的应用实例
FUNCTION f1(x NUMBER) RETURN out_rec_set PIPELINED IS
  user_rec ty_rec_user;
  BEGIN
    FOR i IN 1..x LOOP
      --user_rec:=ty_rec_user(i,'user'||i);--ty_rec_user定义为record类型时不能这样赋值,只有定义成obj时才可以
      user_rec.id:=i;
      user_rec.name:='user'||i;
      --PIPE ROW(1, 'user'||1);
      pipe row(user_rec);
    END LOOP;
    RETURN;
  END;
--使用在外部自定义的object类型表函数
FUNCTION F_PIE_TEST(c NUMBER) RETURN out_obj_set PIPELINED is
  user_ty_obj TY_OBJ_USER;
  BEGIN
     FOR i in 1..c LOOP
         user_ty_obj:=TY_OBJ_USER(i,'name'||i);
         PIPE ROW(user_ty_obj);
     END LOOP;
     RETURN;
  END;
END pkg1;

--外部自定义的object类型
create or replace type TY_OBJ_USER as object
(
  -- Purpose : 测试
  id number(20),
  name varchar2(60),
)

 表函数的调用:

select * from table(pkg1.f1(4))--直接在plsql中执行
select *  FROM  TABLE(CAST(pkg1.f1(4) AS out_rec_set))--java端程序调用

 看到这相信很多人已经开始感觉到爽了吧~~,特别是数据开发人员,不用再在数据端实现统计后还要给应用程序开发人员讲半天如何调用了,应用程序开发人员在调用复杂的统计时一个select语句就搞定,不用考虑什么游标啊、临时表这些乱七八糟的东西了,直接一个select就出来结果,和查询一个表一样的简单

 

欢迎大家提出更好的方案共同探讨~~

本文主要参考:http://blog.chinaunix.net/u1/57759/showart_458451.html

分享到:
评论
1 楼 MyDicta 2010-08-19  
楼主, oracle中管道函数可以动态传参么?

你上面写的函数:

select * from table(pkg1.f1(4))--直接在plsql中执行

其中
select id,name  from table(pkg1.f1(4)) where id=1; -- 正确

但 “4” 可以是基于一个查询的结果值么, 应该怎么写呢?

相关推荐

    Oracle中实现Split函数功能

    这个函数使用了 Oracle 的管道化函数(pipelined function)来返回拆分后的结果。函数内部使用了一个循环来拆分字符串,每次循环都会将拆分后的结果返回给调用者。 最后,我们可以使用这个函数来拆分字符串。例如,...

    Oracle 中 table 函数的应用浅析

    该函数可以平行执行,并可持续输出数据流,被称作管道式输出。应用表函数可将数据转换分阶段处理,并省去中间结果的存储和缓冲表。 1. 用游标传递数据 利用游标 REF CURSOR 可将数据集(多行记录)传递到PL/SQL函数...

    在Oracle的函数中,返回表类型的语句

    在Oracle数据库中,与SQL Server不同的是,不能直接在函数中声明和返回表变量。但是,Oracle提供了类似的功能,可以通过...通过管道化表函数或普通方式,你可以根据具体需求灵活选择合适的方法来构建返回表类型的函数。

    oracle spatial 用户指南

    6. **Network Data Model (NDM)**: Oracle Spatial的NDM用于处理网络数据,如道路、管道或电力线路。它支持网络分析,例如找出最短路径、服务区域分析等。 7. **Topology**: Oracle Spatial支持拓扑规则,确保空间...

    用Pipelined Table实现split函数的示例

    Oracle提供了一种特殊类型——Pipelined Table Function(管道表函数),它可以用于解决这类问题。本文档将详细介绍如何使用Pipelined Table Function来实现一个split函数,该函数可以将输入字符串根据给定的分隔符...

    Oracle 20071025_PLSQLTuning.pdf

    表函数和管道化表函数可以用于返回集合。这两种类型的函数在处理大量数据时非常有效,尤其是当结果集很大时。 ### 二、系统配置 除了编码实践之外,合理的系统配置也是提高 PL/SQL 性能的关键。例如,调整 Oracle ...

    Oracle - In Database Map-Reduce

    传统的Map-Reduce框架通常运行在独立的计算集群上,而Oracle数据库通过其独特的特性——**Pipeline Table Functions**(管道表函数)——提供了一种直接在数据库内部实现Map-Reduce的方式,从而实现了真正的“in-...

    Oracle内置包_reference

    DBMS_UTILITY包提供了一系列实用函数,如分析SQL语句(ANALYZE_STATEMENT)、格式化输出PL/SQL块(FORMAT_SOURCE)以及获取数据库版本信息(GET_VERSION)。这个包对于调试和优化PL/SQL代码非常有用。 二、DBMS_...

    创建Oracle函数的示例

    在本文中,我们将深入探讨如何使用PL/SQL创建Oracle函数,并介绍一些高级技术,如管道操作。 首先,创建Oracle函数的基本结构包括函数名、输入参数(如果有的话)、返回类型和函数体。以下是一个简单的示例: ```...

    剑破冰山 Oracle开发艺术

    Oracle数据库作为市场上占有率最高的商业数据库之一,以其强大的功能和智能化的管理工具,使得Oracle数据库管理(DBA)的工作日趋简化,同时也推动了Oracle开发人员的需求和人数的增加。本书旨在帮助读者掌握中高级...

    剑破冰山 Oracle开发艺术.part2.rar

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫谈、管道函数的学习与实战应用、巧用锁特性避免...

    Oracle内置包的使用方法.rar

    Oracle数据库系统提供了丰富的内置包,这些包包含了大量预定义的函数和过程,为数据库管理员和开发者提供了极大的便利。本文将详细介绍Oracle内置包的使用方法,包括它们的功能、调用方式以及示例应用。 1. **DBMS_...

    在Oracle运行操作系统命令

    `DBMS_PIPE`包提供了在Oracle进程中创建和管理管道的能力,允许两个或多个Oracle进程之间进行数据交换。这种机制类似于操作系统中的管道功能,但它是在Oracle环境下实现的,并具有不同的内部处理方式。 #### 实现...

    剑破冰山 Oracle开发艺术.part1.rar(共3part)

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫谈、管道函数的学习与实战应用、巧用锁特性避免...

    剑破冰山 Oracle开发艺术.part3.rar (共3part)

    此外还有大量案例:Where In List问题解析,数据库设计和大数据量处理、数据审核、号段选取应用、分析SQL执行计划的关注点、Oracle开发误区探索、提升PL/SQL开发性能漫谈、管道函数的学习与实战应用、巧用锁特性避免...

    oracle 学习包含SQL.TERADATA,UNIX

    SQL(结构化查询语言)是操作和查询数据库的标准语言,无论是Oracle还是其他数据库系统,掌握SQL都是必要的。Teradata则是一款大规模并行处理数据库,尤其适用于大数据处理和分析。而Unix操作系统以其稳定性和强大的...

    如何在Oracle8.1.6 Spatial 上编程

    在Oracle Spatial中,你可以存储、查询、分析和可视化地理信息。以下是对Oracle8.1.6 Spatial编程的一些关键知识点: 1. **Spatial 数据类型**:Oracle Spatial引入了几何数据类型,如SDO_GEOMETRY,用于存储点、线...

    ORACLE 10 g spatial的使用方法简介

    4. Geocoding:对于非结构化的地址数据,Oracle 10g Spatial提供了地理编码功能,可以将这些地址转换为精确的经纬度坐标。 5. 索引改进:R树索引被广泛采用,取代了旧的四叉树索引,提升了空间查询的效率。 6. 新...

    Oracle_Database10g_性能调整与优化-第10章_使用PLSQL提高性能

    管道表函数允许在 PL/SQL 中创建和返回复杂的结果集,这对于处理大量数据和复杂的业务逻辑特别有用。 #### 28. 使用条件编译限制调试命令 条件编译是一种在编译时根据不同的条件选择性地包含或排除代码的方法。...

Global site tag (gtag.js) - Google Analytics