PL / SQL程序和水晶报告

时间:2009-11-26 12:06:56

标签: oracle crystal-reports plsql

我正在尝试使用以下过程作为我的水晶报告的数据源。该查询按预期工作,但问题是我无法弄清楚如何从这些虚拟表中获取数据 - IFS_PR_DUMMY_TAB和IFS_PR_DUMMY2_TAB

CREATE OR REPLACE procedure dummy9_IFS_FR2_Sales (cdate IN date)

as

acontract customer_order.contract%type;
ashowroom customer_order.district_code%type;
aorderno customer_order.order_no%type;
amount number(10);

bcontract customer_order.contract%type;
bshowroom customer_order.district_code%type;
borderno customer_order.order_no%type;
bamount number(10);

CURSOR c2 IS
select  contract, district_code ,count(order_no),
SUM(CUSTOMER_ORDER_API.Get_Total_Sale_Price__(order_no))
from CUSTOMER_ORDER
where order_no IN (select distinct order_no from customer_order_line where state IN ('Released') )  AND state IN ('Released') and to_char(date_entered,'MM/DD/YYYY')>=to_char(cdate,'MM/DD/YYYY')
and contract IN
('CERA','SAN','WOD','QEM','PIP','COT','KIT','MAR','PROJ')
group by contract,district_code, date_entered ; 

CURSOR c2 IS
select  contract, district_code ,count(order_no),
SUM(CUSTOMER_ORDER_API.Get_Total_Sale_Price__(order_no))
from CUSTOMER_ORDER
where order_no IN (select distinct order_no from customer_order_line where state IN ('Reserved') )  AND state IN ('Reserved') and to_char(date_entered,'MM/DD/YYYY')>=to_char(cdate,'MM/DD/YYYY')
and contract IN
('CERA','SAN','WOD','QEM','PIP','COT','KIT','MAR','PROJ')
group by contract,district_code, date_entered ; 

begin

--For Released Orders

  OPEN c1;

  DELETE FROM IFS_PR_DUMMY_TAB;

  loop
      fetch c1 into acontract, ashowroom, aorderno, amount;
      exit when c1%notfound;

Insert into IFS_PR_DUMMY_TAB
(DCONTRACT ,DSHOWROOM ,DORDERNO,DAMOUNT) values (acontract,ashowroom,aorderno,amount);

end loop;
close c1;

--For Reserved Orders

 OPEN c2;

 DELETE FROM IFS_PR_DUMMY2_TAB;

loop

      fetch c2 into bcontract, bshowroom, borderno, bamount;
      exit when c2%notfound;

Insert into IFS_PR_DUMMY2_TAB
(ECONTRACT ,ESHOWROOM ,EORDERNO,EAMOUNT) values (bcontract,bshowroom,borderno,bamount);

end loop;
close c2; 

end;

2 个答案:

答案 0 :(得分:1)

解决问题的最佳方法是让程序返回结果集。在Oracle中,我们使用REF CURSORS来实现这一目标。您不需要再填充临时表,但我们可以使用其中一个来定义REF CURSOR的签名。

create or replace package report_records as
    type order_recs is ref cursor 
        return IFS_PR_DUMMY_TAB%rowtype;
end;
/

此过程返回两个ref游标。

create or replace procedure dummy9_ifs_fr2_sales 
    (cdate in date
     , c_released_orders in out report_records.order_recs
     , c_reserved_orders in out report_records.order_recs
     )

begin
    open c_released_orders for
        select  contract
               , district_code 
               ,count(order_no)
               ,sum(customer_order_api.get_total_sale_price__(order_no))
        from customer_order
        where order_no 
        in (select distinct order_no 
               from customer_order_line 
               where state in ('Released') )  
        AND state in ('Released') 
        and to_char(date_entered,'MM/DD/YYYY')>=to_char(cdate,'MM/DD/YYYY')
        and contract in ('CERA','SAN','WOD','QEM','PIP','COT','KIT','MAR','PROJ')
        group by contract,district_code, date_entered ; 
    open c_released_orders for
        select  contract
                 , district_code 
                 ,count(order_no)
                 ,sum(customer_order_api.get_total_sale_price__(order_no))
        from customer_order
        where order_no in (select distinct order_no 
                              from customer_order_line 
                              where state in ('Reserved') )
        AND state in ('Reserved') 
        and to_char(date_entered,'MM/DD/YYYY')>=to_char(cdate,'MM/DD/YYYY')
        and contract in ('CERA','SAN','WOD','QEM','PIP','COT','KIT','MAR','PROJ')
        group by contract,district_code, date_entered ; 
end;
/

感兴趣的是,如果您的date_entered列是DATE数据类型,则不应使用TO_CHAR()转换。如果您希望处理具有时间元素的行,则可以采用更有效的方法来处理它。

参考游标在“Oracle PL / SQL用户指南”中有详细说明。 Find out more.

修改

我不是Crystal Reports的人。谷歌似乎只抛出一些非常古老的文档(如this)。但是,在与Oracle存储过程进行交互时,CR似乎非常受限制。

显然Crystal Reports需要声明为IN OUT的参数。此外,它似乎只能处理一个这样的引用游标参数。此外,ref cursor必须是过程签名中的 first 参数。最后,令我难以置信的是,“存储过程不能调用另一个存储过程”。我们习惯于设计模式,声明调用程序不应该知道被调用程序内部的任何内容,但是在这里我们似乎有被调用程序的内部工作由调用它的程序类型决定。那太蹩脚了。

因此,无论如何,上述解决方案对Crystal Reports不起作用。唯一的解决方案是将其分解为两个程序,签名如下:

create or replace procedure dummy9_ifs_fr2_sales_released 
    (c_released_orders in out report_records.order_recs
     , cdate in date
     )
 as ... 

create or replace procedure dummy9_ifs_fr2_sales_reserved 
    (c_reserved_orders in out report_records.order_recs
     , cdate in date
     )
as ...

这些程序可以捆绑到一个包中(假设CR可以处理该结构)。

如果两个程序解决方案都不可接受,那么我认为你已经离开了David的方法:完全放弃存储过程,只在报告中使用原始SQL。

答案 1 :(得分:-2)

你的代码太糟糕了。

首先,为什么使用显式游标?为什么不将行插入表中?

其次,为什么删除时可以更快地截断?

第三,to_char(date_entered,'MM/DD/YYYY')>=to_char(cdate,'MM/DD/YYYY')将一个函数应用于列(因此无法使用索引而优化器无法获得对基数的良好估计),它将日期转换为一个愚蠢的字符格式,月份处于领先位置,因此它甚至没有进行正确的比较!在你的逻辑中,02年11月至2009年的排序大于01-march-2010。

第四,为什么你在使用存储过程呢?如果需要的话,只需运行该死的查询和联盟所有它们。

这让我想起了我在离岸报告开发人员看到我上一份工作两年的所有废话。完全无能。