在Crystal Report 8中调用Oracle的procedure储存过程,并取得返回的类型为Sys_Refcursor数据表

Crystal Report 8非常易入门,通常只需要鼠标就可以完成报表的创建,但随着实习中对SQL语言和底层数据库的熟悉,我越来越对Crystal的“指指点点”的创建报表方式感到失望,对于存在大量表连接查询创建,SQL语言比CR(Crystal Report)的GUI界面要方便得多。

但Crystal Report 8中调用Oracle的存储过程从而直接取得数据表,并不像直接使用CR的GUI界面创建报表那样步骤明显,接下来将介绍如何在Crystal Report 8中调用Oracle Procedure的步骤,希望能对相关CR报表开发人员起到一点参考作用。

其实详细步骤在Bussiness Object的“Using Oracle Stored Procedures in Crystal Reports ”技术论文中已经有了,但我发现,对于Crystal Report 8和Oracle 9.2,并且在Oracle中程序员没有创建Package权限的情况下,具体做法仍旧有些差异:






  1. 从BI网站下载更新的CR到Oracle的数据库驱动,其实这个驱动也老的不行啦,不过恐怕CR 8内置的更古老。注意一下,XP以上的操作系统,反而倒要使用cror815.zip包中的Win9x.reg来导入注册表,因为从XP开始,C:\Windows而不是C:\WinNT才是Windows的系统目录,如果你把操作系统安装在D盘,请更改相应的reg注册表文件。
  2. 在Oracle中创建CR要调用的procedure,比如下面这个,注意ResultCur为输入输出类型,不能只申明为输出类型,即不能将IN OUT参数改为单单OUT型的,否则随后的CR8会无法显示这样的store procedure:
    procedure OperationStayTime
    <!---->create or replace procedure OperationStayTime(Cust      in varchar2,
                                                  StartDT   
    in varchar2,
                                                  EndDT     
    in varchar2,
                                                  ResultCur 
    in Out Sys_Refcursor) is
      
    CURSOR c_OPST IS
        
    SELECT CO.CONTAINERNAME,
                        CO.CUSTOMERLOTNUMBER,
                        WFSTP.SEQUENCE,
                        OP.OPERATIONNAME,
                        CO.DIERELEASEDATE,
                        CO.TARGETDEVICE,
                        HML1.TXNDATE TransDate,
                        HML2.TXNDATE LastTransDate, 






    -- to be modifyed in procedure

                        HML2.TXNDATE HML2TXNDATE,
                        CU.CUSTOMERNAME,
                        CDODEF.CDONAME,
                        PAK.PACKAGETYPENAME


    ||DI.DIMENSIONNAME||LD.LEADCOUNTNAME PDL,
                        PTL.PRODUCTIONLINENAME,
                        OP.DESCRIPTION,
                        AMKOP.AMKORWWOPERNAME
          



    FROM CONTAINER       CO,
               HISTORYMAINLINE HML1,
               PRODUCT         PT,
               HISTORYMAINLINE HML2,
               MOVEHISTORY     MH,
               CUSTOMER        CU,
               CDODEFINITION   CDODEF,
               DIMENSION       DI,
               PACKAGETYPE     PAK,
               LEADCOUNT       LD,
               PRODUCTIONLINE  PTL,
               CURRENTSTATUS   CUTSTS,
               OPERATION       OP,
               WORKFLOWSTEP    WFSTP,
               AMKORWWOPER     AMKOP
         














    WHERE CO.CONTAINERID = HML1.CONTAINERID
           
    AND CO.PRODUCTID = PT.PRODUCTID
           
    AND CO.CURRENTSTATUSID = CUTSTS.CURRENTSTATUSID
           
    AND HML1.CONTAINERID = HML2.CONTAINERID
           
    AND PT.CUSTOMERID = CU.CUSTOMERID
           
    AND HML1.TXNTYPE = CDODEF.CDODEFID
           
    AND PT.DIMENSIONID = DI.DIMENSIONID
           
    AND PT.PACKAGETYPEID = PAK.PACKAGETYPEID
           
    AND PT.LEADCOUNTID = LD.LEADCOUNTID
           
    AND CUTSTS.PRODUCTIONLINEID = PTL.PRODUCTIONLINEID
           
    AND HML2.OPERATIONID = OP.OPERATIONID
           
    AND HML2.WORKFLOWSTEPID = WFSTP.WORKFLOWSTEPID
           
    AND OP.AMKORWWOPERID = AMKOP.AMKORWWOPERID
           
    AND mh.historymainlineid = hml2.historymainlineid
           
    AND CDODEF.CDONAME = 'Ship'
           
    AND HML1.REVERSALSTATUS = 1
           
    AND HML2.REVERSALSTATUS = 1
           
    AND HML2.OPERATIONID <> '00060e08000013f1' AND -- Shipping

               HML2.OPERATIONID <> '00060e08000013f0' AND -- FP Packing

               HML2.OPERATIONID <> '00060e08000013ef' AND -- Schedule

               CU.CUSTOMERNAME = Cust
           
    and hml1.txndate >= to_date(nvl(StartDT, '2006/06/01 01:00:00'),
                                       
    'yyyy/mm/dd hh24:mi:ss')
           
    and hml1.txndate <= to_date(nvl(EndDT, '2006/06/01 01:00:00'),
                                       
    'yyyy/mm/dd hh24:mi:ss')
         
    ORDER BY CO.CONTAINERNAME, WFSTP.SEQUENCE;

      opst_rec TempOperationStayTime

    %ROWTYPE;

      l_LastTransDate opst_rec.lasttransdate

    %type;

    begin
      
    delete from tempOperationStayTime;

      

    FOR opst_rec IN c_OPST LOOP
        
    if l_LastTransDate is not null then
          opst_rec.lasttransdate :
    = l_LastTransDate;
        
    end if;
        l_LastTransDate :
    = opst_rec.hml2txndate;
      
        

    if opst_rec.containername is not null then
          
    INSERT INTO tempOperationStayTime VALUES opst_rec;
        
    end if;
      
      

    END LOOP;

      

    Open ResultCur for
        
    Select *
          
    from TempOperationStayTime
         
    ORDER BY CONTAINERNAME, SEQUENCE;

      

    return;

    end OperationStayTime;


  3. 在CR的DataExplorer中,选择More Data Sources->Oracle Server节点,在弹出的Oracle SQL对话框中分别输入User ID,Password,Server,这也是关键的一步,不能使用ODBE驱动,否则仍然不能在CR8中成功调用procedure。
    在Crystal Report 8中调用Oracle的procedure储存过程,并取得返回的类型为Sys_Refcursor数据表
  4. 选择刚刚添加的Server,按Options打开选项对话框,选中Show->Stored Procedures才能显示出各个储存过程,如果更改Options后Data Explorer窗口没有刷新(在CR8.0.5版本下,这肯定会发生),先收拢Server节点,再打开,CR就会按新设置刷新列表。
    在Crystal Report 8中调用Oracle的procedure储存过程,并取得返回的类型为Sys_Refcursor数据表
  5. 现在可以通过列表选择CR8需要调用的procedure,单击Add按钮添加要使用Oracle 存储过程。若你的储存过程有输入参数,单击Add后会要求你输入参数值,输入具体参数值,这些参数会成为Crystal Reports的Parameter Field的缺省参数,RESULTCUR是输出的数据表,不必填值。
    在Crystal Report 8中调用Oracle的procedure储存过程,并取得返回的类型为Sys_Refcursor数据表
  6. 完成后已经可以在Field Explorer上已经显示出存储过程返回的字段了,后面的步骤都是常规的CR8使用方法了……

 



丁丁 2007-02-02 14:45 发表评论

你可能感兴趣的:(oracle,sql,sql,server,XP,FP)