views:

731

answers:

5

Dear All,

I am trying to use the following procedure as a datasource for my crystal report. The query works as I expected but the problem is I can't figure out how to fetch back the data from those dummy tables - IFS_PR_DUMMY_TAB and 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;

Please advise.

Regards, User

+1  A: 

The best way to solve your problem is to have your procedure return result sets. In Oracle we use REF CURSORS to achieve this. You don't need to populate the temporary tables any more, but we can use one of them to define the signature of the REF CURSOR.

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

This procedure returns two ref cursors.

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;
/

As a matter of interest, if your date_entered column is a DATE datatype then you shouldn't use the TO_CHAR() conversion. If you are looking to handle rows which have a time element there are more efficient ways of handling that.

Ref Cursors are explained in detail in the Oracle PL/SQL User's Guide. Find out more.

edit

I'm not a Crystal Reports person. Google only seems to throw out some pretty old documentation (like this). But the consensus seems to be that CR is pretty restricted when it comes to interacting with Oracle stored procedures.

Apparently Crystal Reports needs the parameters declared as IN OUT. Also it appears it can only handle one such ref cursor parameter. Furthermore the ref cursor needs to be the first argument in the procedure's signature. Finally, and to my mind completely incredibly, the "stored procedure cannot call another stored procedure." We are used to design patterns which state that calling programs shouldn't have to know anything about the internals of the called program, but here we seem to have the internal workings of a called program being determined by the sort of program which calls it. That's pretty lame.

So, anyway, the above solution won't work for Crystal Reports. The only solution is to break it up into two procedures, with signatures like this:

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 ...

These procedures could be bundled into a package (assuming CR can cope with that construct).

If the two procedure solution is not acceptable then I think you're left with David's approach: abandon stored procedures altogether, and just use raw SQL in the report.

APC
A: 

Your code sucks.

Firstly, why are you using explicit cursors? Why wouldn't you just insert the rows into the tables?

Secondly, why delete when you could truncate much faster?

Thirdly, to_char(date_entered,'MM/DD/YYYY')>=to_char(cdate,'MM/DD/YYYY') applies a function to a column (so an index can't be used and the optimiser cannot get a good estimate of cardinality), and it converts the dates to a stupid character format with the month in the leading position so that it does not even do a correct comparison! 02-november-2009 sorts greater than 01-march-2010 in your logic.

Fourthly, why on earth are you using a stored procedure for this? Just run the damn queries and Union All them together if you need to.

This reminds me of all of the crap I saw from offshore report developers for two years at my previous job. Complete incompetence.

David Aldridge
Please don't sugar coat it. Tell us how you really feel. haha :)
Dusty
A: 

Dear APC,

I have tried using reference cursors for the same, but for some strange reason whenever I try to select a procedure which uses more than ONE reference cursor - as a datasource for the report, it doesn't show up in the list of procedures in Crystal reports! So I limited myself to using explicit cursors for time being :(

Yes, I am dealing with a datetime format, may I also know what would be the more efficient ways of handling this? I am on Oracle 9i.

My current issue was/is -- how I could fetch back the data from these tables. I was advised to create another procedure which would call the above and then write a query joining the two tables, what type of join would give me the right result sans duplication?

I am doing my reading but since this will be my FIRST report, I appreciate everyone's input.

Thank you, Signil

signil
I have done a bit of research on Crystal Reports, and I have updated my response accordingly.
APC
A: 

Dear David,

Thank you for pointing out my mistakes. I will modify the procedure and use truncate as the turnaround time will reduce considerably.

You asked, why I am using a stored procedure for this. It is because I was asked to do so. I know we could create a view and join the queries but that's being done by someone else. So here I am, stuck with a procedure.

As for the to_char and use of explicit cursors - I have replied back APC regarding the same.

Thanx, Signil

signil
A: 

Dear APC,

Thanx a lot for bringing the documentation to my notice. I will try to get the desired result by hook or crook.

Thank you all again for feedback.

Regards, Signil

signil