• 【Oracle-PLsql】使用存储过程,利用table集合类型开发复杂业务报表


    在一般的项目中,都需要开发一些报表,少则几个字段,多则几十个字段,需要关联的表可能多达十几、几十张表,如果想要使用一个SQL语句将这几十张表关联起来

    查询所需要的字段,当你听到这里的时候,你的脑子可能已经晕掉了,这得多麻烦啊,不光多麻烦,你甚至可能还写不出来,即使你写出来了,也肯定是bug一堆。等你过

    接个月再来看看这段SQL,估计已经看不明白了。等到后人来维护你这段SQL的时候,他估计会咬牙切齿,恨不得要把这段代码的作者撕个粉碎。

    那么接下来,就给大家介绍一个Oracle的功能,使用table集合类型返回结果集,顾名思义你就可以把它看成是一个表,本来结果集也可以看成是一张表嘛。话不多说,直接来看代码。

    1.首先定义一个type,包括返回结果集所需要显示的字段。

    [sql] view plain copy
     
    1. CREATE OR REPLACE TYPE query_rpt_test force is object  
    2. (  
    3.       full_name varchar2(200),  
    4.       birth_date date,  
    5.       gender  varchar2(200)  
    6. )  


    2.接着定义table类型

    [sql] view plain copy
     
    1. CREATE OR REPLACE TYPE t_query_rpt_test is table of query_rpt_test  


    3.然后定义package

    [sql] view plain copy
     
    1. create or replace package PKG_REPORT_QUERY_TEST is  
    2.   
    3.   
    4.   --定义取数的function,传入参数分别是开始日期和截止日期  
    5.   function f_get_query_report(i_begin_date date, i_end_date date)  
    6.     --返回类型为t_query_rpt_test  
    7.     return t_query_rpt_test;  
    8.   
    9. end PKG_REPORT_QUERY_TEST;  


    4.定义package body

    [sql] view plain copy
     
    1. create or replace package body PKG_REPORT_QUERY_TEST is  
    2.   
    3.   --定义取数的function,传入参数分别是开始日期和截止日期  
    4.   function f_get_query_report(i_begin_date date, i_end_date date)  
    5.     return t_query_rpt_test as  
    6.     --返回类型为t_query_rpt_test  
    7.     m_table t_query_rpt_test;  
    8.     
    9.     --结果集行数初始值  
    10.     m_row_num number := 0;  
    11.     
    12.     --一些变量的定义  
    13.     n_list_id   number;  
    14.     v_full_name varchar2(200);  
    15.     v_birthday  date;  
    16.     v_gender    varchar2(20);  
    17.     
    18.     --游标的定义  
    19.     --这边的业务逻辑要看的该商品的购买者的姓名,生日和性别  
    20.     --此处举例比较简单,只有t_product和t_customer两张表的关联关系,完全可以两者表关联起来放在同一个cursor中,  
    21.     --这边先查询出在该区间段内的所有商品信息的主键List_id  
    22.     cursor c_product is  
    23.       select p.list_id  
    24.         from t_product p  
    25.        where p.buy_date >= i_begin_date  
    26.          and p.buy_date <= i_end_date;  
    27.     
    28.   begin  
    29.     --结果集初始化  
    30.     m_table := t_query_rpt_test();  
    31.     
    32.     --打开游标  
    33.     open c_product;  
    34.     loop  
    35.       --循环遍历游标内的每一个数据  
    36.       fetch c_product  
    37.         into n_list_id;  
    38.       exit when c_product%notfound;  
    39.           
    40.         --以下就是每个字段的取数逻辑了,除此之外,整个package的function格式都是固定的。  
    41.       --根据遍历的数据n_list_id在t_customer中查询客户信息  
    42.       select c.full_name, c.birthday, c.gender  
    43.         into v_full_name, v_birthday, v_gender  
    44.         from t_customer c  
    45.        where c.product_id = n_list_id;  
    46.       
    47.       --扩充结果集  
    48.       m_table.extend;  
    49.       --结果集行数自增1  
    50.       m_row_num := m_row_num + 1;  
    51.       --设置结果集中每个字段的值  
    52.       m_table(m_row_num) := query_rpt_test(v_full_name,  
    53.                                            v_birthday,  
    54.                                            v_gender);  
    55.     end loop;  
    56.     --循环结束,关闭游标  
    57.     close c_policy;  
    58.     --返回结果集  
    59.     return m_table;  
    60.   end f_get_query_report;  
    61.   
    62. end PKG_REPORT_QUERY_TEST;  



    
    

    好了,整个代码都编写完成了,那么我们如何来使用呢,直接编写如下语句就能返回一个结果集了。

    [sql] view plain copy
     
    1. select * from table(PKG_REPORT_QUERY_TEST.f_get_query_report(to_date('2013-01-01','yyyy-MM-dd'),to_date('2013-01-01','yyyy-MM-dd')));  

    这样的话在Java中使用也非常方便,就不用再在java代码中写一大堆SQL了。

    OK,总结一下,整个开发流程就是:

    1.定义cursor。cursor的作用只需要查询最精简最有用的信息,至于其他,通通放到取数逻辑中去。

    2.打开cursor,根据cursor中的值进行相应的取数逻辑。

    3.结果集的扩充,自增1,然后设置结果集的值。

    4.最后当然要有返回值:结果集。

    很明显,优点就是:简单方便,便于维护,以后只需要在type类型中增加相应的字段,在package中增加相应的取数逻辑,最后设上值即可。

    转自:http://blog.csdn.net/andn_pan/article/details/16946365

  • 相关阅读:
    【POJ 1958】 Strange Towers of Hanoi
    【HNOI 2003】 激光炸弹
    【POJ 3263】 Tallest Cow
    【POJ 2689】 Prime Distance
    【POJ 2777】 Count Color
    【POJ 1995】 Raising Modulo Numbers
    【POJ 1845】 Sumdiv
    6月16日省中集训题解
    【TJOI 2018】数学计算
    【POJ 1275】 Cashier Employment
  • 原文地址:https://www.cnblogs.com/beijingstruggle/p/7206917.html
Copyright © 2020-2023  润新知