Stored procedures 从具有多个游标的Jasper report调用Oracle包

Stored procedures 从具有多个游标的Jasper report调用Oracle包,stored-procedures,plsql,jasper-reports,package,Stored Procedures,Plsql,Jasper Reports,Package,我在Oracle中有一个软件包,用于后台处理客户信息。该软件包如下所示: 编辑 create or replace PACKAGE mfi_statement_spool AS PROCEDURE mfi_main_spool (fromdate IN DATE, todate IN DATE,c1 out SYS_REFCURSOR,c2 out SYS_REFCURSOR); FUNCTION mfi_cust_details (vforacid IN VARCH

我在Oracle中有一个软件包,用于后台处理客户信息。该软件包如下所示:

编辑

create or replace
PACKAGE        mfi_statement_spool
AS
   PROCEDURE mfi_main_spool (fromdate IN DATE, todate IN DATE,c1 out SYS_REFCURSOR,c2 out SYS_REFCURSOR);

   FUNCTION mfi_cust_details (vforacid IN VARCHAR2)
      RETURN VARCHAR2;

   FUNCTION mfi_citycountry (vcountrycode IN VARCHAR2, vcitycode IN VARCHAR2)
      RETURN VARCHAR2;
END mfi_statement_spool;
    /
我需要使用我这样声明的Main_Spool过程:

编辑完整的包体

CREATE OR REPLACE
PACKAGE BODY TBAADM.mfi_statement_spool
AS
  -- --------------------------------------------------------------------------
PROCEDURE mfi_main_spool(
    fromdate DATE,
    todate   DATE,
    c1 OUT SYS_REFCURSOR,
    c2 OUT SYS_REFCURSOR)
AS
  cramount  NUMBER;
  dramount  NUMBER;
  countcr   NUMBER;
  countdr   NUMBER;
  srl_num   NUMBER;
  ledgerbal NUMBER;
  c1 SYS_REFCURSOR;
  c2 SYS_REFCURSOR;
  opbal             NUMBER;
  vdocremarks       VARCHAR2 (100);
  vremarkscorporate VARCHAR2 (100);
  vremarksretail    VARCHAR2 (100);
  remarks           VARCHAR2 (100);
  endbal            NUMBER;
  curamount         NUMBER;
  totaltrans        NUMBER;
  sumtrans          NUMBER;
  vtranamt          VARCHAR2 (50);
  state1            VARCHAR2 (600);
  rnum              NUMBER;
  state2            VARCHAR2 (600);
  state3            VARCHAR2 (600);
  fuunclamt         NUMBER;
  state4            VARCHAR2 (600);
  balancebf         VARCHAR2 (50);
  ebal              VARCHAR2 (50);
  lbal              VARCHAR2 (50);
  vinstrnumcheck    VARCHAR2 (15);
  vinstrnum         VARCHAR2 (50);
  vpaart            VARCHAR2 (50);
  wfile_handle UTL_FILE.file_type;
  filename VARCHAR2(100);
  CURSOR c1
  IS
    SELECT foracid,
      acct_name,
      addr_1,
      addr_2,
      sol_desc,
      city_code,
      gam.FUTURE_UN_CLR_BAL_AMT
    FROM tbaadm.gam,
      tbaadm.sol
    WHERE gam.sol_id   = sol.sol_id
    AND schm_type     IN ('CAA','ODA','LAA')
    AND schm_code NOT IN ('CTSTF');
  CURSOR c2 (vforacid VARCHAR2)
  IS
    SELECT TRIM (foracid),
      tran_amt,
      part_tran_type,
      acct_name,
      gam.cust_id,
      clr_bal_amt,
      gam.acid,
      un_clr_bal_amt,
      acct_crncy_code,
      tran_date,
      htd.value_date,
      htd.instrmnt_num,
      htd.tran_particular
    FROM tbaadm.gam,
      tbaadm.htd
    WHERE gam.acid     = htd.acid
    AND foracid        = vforacid
    AND tran_date     >= fromdate
    AND tran_date     <= todate
    AND pstd_flg       = 'Y'
    AND htd.del_flg   != 'Y'
    AND acct_cls_flg  != 'Y'
    AND schm_type     IN ('CAA','ODA','LAA')
    AND schm_code NOT IN ('CTSTF')
    ORDER BY foracid,
      htd.pstd_date ;
BEGIN
  FOR i IN c1
  LOOP
    rnum         := 0;
    filename     := 'statement_' || TO_CHAR(i.foracid) || '.TXT';
    wfile_handle := UTL_FILE.fopen ('DIR_TEMP', filename, 'W', 32767);
    BEGIN
      SELECT NVL (SUM (tran_date_bal), 0)
      INTO opbal
      FROM tbaadm.gam,
        tbaadm.eab
      WHERE gam.acid  = eab.acid
      AND gam.foracid = i.foracid
      AND eod_date    =
        (SELECT MAX(eod_date)
        FROM tbaadm.eab
        WHERE eod_date < fromdate
        AND acid      IN
          (SELECT acid FROM tbaadm.gam WHERE foracid=i.foracid
          )
        );
    EXCEPTION
    WHEN NO_DATA_FOUND THEN
      opbal := 0;
    END;
    BEGIN
      IF opbal < 0 THEN
        SELECT REPLACE(concat(TO_CHAR(opbal,'9999999990D99') ,' DR'),'-')
        INTO balancebf
        FROM dual;
      ELSE
        SELECT concat(TO_CHAR(opbal,'9999999990D99') ,' CR') INTO balancebf FROM dual;
      END IF;
    END;
    BEGIN
      SELECT NVL (SUM (DECODE (part_tran_type, 'D', -1 * tran_amt, tran_amt ) ), 0 )
      INTO sumtrans
      FROM tbaadm.htd
      WHERE acid =
        (SELECT acid FROM tbaadm.gam WHERE foracid = i.foracid
        )
      AND pstd_flg   = 'Y'
      AND del_flg   != 'Y'
      AND tran_date >= fromdate
      AND tran_date <= todate;
    EXCEPTION
    WHEN NO_DATA_FOUND THEN
      sumtrans := 0;
    END;
    endbal := sumtrans + opbal;
    BEGIN
      IF endbal < 0 THEN
        SELECT REPLACE(concat(TO_CHAR(endbal,'9999999990D99') ,' DR'),'-')
        INTO ebal
        FROM dual;
      ELSE
        SELECT concat(TO_CHAR(endbal,'9999999990D99') ,' CR') INTO ebal FROM dual;
      END IF;
    END;
    BEGIN
      SELECT NVL (SUM (DECODE (part_tran_type, 'D', 1, 0)), 0),
        NVL (SUM (DECODE (part_tran_type, 'C', 1, 0)), 0)
      INTO countdr,
        countcr
      FROM tbaadm.htd
      WHERE acid IN
        (SELECT acid FROM tbaadm.gam WHERE foracid = i.foracid
        )
      AND tran_date >= fromdate
      AND tran_date <= todate
      AND pstd_flg   = 'Y'
      AND del_flg   != 'Y';
    EXCEPTION
    WHEN NO_DATA_FOUND THEN
      countcr := 0;
      countdr := 0;
    END;
    totaltrans := countcr + countdr;
    FOR j                IN c2 (i.foracid)
    LOOP
      rnum := rnum + 1;
      SELECT TO_CHAR (DECODE (j.part_tran_type, 'C', j.tran_amt, '0.00'),'9999999990D99')
        || '|'
        || TO_CHAR (DECODE (j.part_tran_type, 'D', j.tran_amt, '0.00'),'9999999990D99')
      INTO vtranamt
      FROM DUAL;
      SELECT DECODE (j.part_tran_type, 'D', -1 * j.tran_amt, j.tran_amt)
      INTO curamount
      FROM DUAL;
      opbal   := opbal + curamount;
      IF opbal < 0 THEN
        SELECT REPLACE(concat(TO_CHAR(opbal,'9999999990D99') ,' DR'),'-')
        INTO lbal
        FROM dual;
      ELSE
        SELECT concat(TO_CHAR(opbal,'9999999990D99') ,' CR') INTO lbal FROM dual;
      END IF;
      BEGIN
        BEGIN
          SELECT DISTINCT purgeremarks
          INTO vremarksretail
          FROM crmuser.accounts
          WHERE orgkey =
            (SELECT cif_id FROM tbaadm.cmg WHERE cmg.cust_id =j.cust_id
            )
          AND rownum < 2;
        EXCEPTION
        WHEN NO_DATA_FOUND THEN
          vremarksretail := NULL;
        END;
        IF (vremarksretail IS NULL) THEN
          BEGIN
            SELECT DISTINCT remarks
            INTO vremarkscorporate
            FROM crmuser.corporate
            WHERE corp_key =
              (SELECT cif_id FROM tbaadm.cmg WHERE cmg.cust_id =j.cust_id
              )
            AND rownum < 2;
          EXCEPTION
          WHEN NO_DATA_FOUND THEN
            vremarkscorporate := NULL;
          END;
          remarks := vremarkscorporate;
        ELSE
          remarks := vremarksretail;
        END IF;
      END;
      BEGIN
        SELECT DISTINCT docremarks
        INTO vdocremarks
        FROM crmuser.entitydocument
        WHERE core_cust_id = j.cust_id
        AND rownum         < 2;
      EXCEPTION
      WHEN NO_DATA_FOUND THEN
        vdocremarks := NULL;
      END;
      BEGIN
        SELECT SUBSTR (j.tran_particular, 1, 7) INTO vinstrnumcheck FROM DUAL;
      EXCEPTION
      WHEN NO_DATA_FOUND THEN
        vinstrnumcheck := NULL;
      END;
      IF (vinstrnumcheck = 'BY INST') THEN
        vpaart          := 'OUTWARD CLEARING KES';
      ELSE
        vpaart := j.tran_particular;
      END IF;
      IF (vinstrnumcheck = 'BY INST') THEN
        SELECT SUBSTR (j.tran_particular, 8, (INSTR (j.tran_particular, ':') - 8) )
        INTO vinstrnum
        FROM DUAL;
      ELSE
        vinstrnum := j.instrmnt_num;
      END IF;
      BEGIN
        SELECT FUTURE_UN_CLR_BAL_AMT
        INTO fuunclamt
        FROM tbaadm.gam g
        WHERE g.foracid=i.foracid;
      END;
      BEGIN
        UTL_FILE.put_line (wfile_handle, rnum || '|' || i.foracid || '|' || j.acct_crncy_code || '|' || j.tran_date || '|' || j.value_date || '|' || vinstrnum || '|' || vpaart || '|' || vtranamt || '|' || lbal || '|' || j.acct_name || '|' || mfi_cust_details (i.foracid) || '|' || ebal || '|' || countdr || '|' || countcr || '|' || j.un_clr_bal_amt || '|' || balancebf || '|' || fromdate || '|' || todate || '|' || todate || '|' || remarks || '|' || vdocremarks || '|' || fuunclamt );
      END;
    END LOOP;
    rnum := rnum - 1;
    UTL_FILE.fclose (wfile_handle);
  END LOOP;
END mfi_main_spool;
-- ---------------------------------------------------------------------------
FUNCTION mfi_cust_details(
    vforacid VARCHAR2)
  RETURN VARCHAR2
IS
  vcustdetails VARCHAR2 (300);
BEGIN
  BEGIN
    SELECT a.cust_title_code
      || '|'
      || a.cust_id
      || '|'
      || b.address_line1
      || '|'
      || b.address_line2
      || '|'
      || mfi_citycountry (b.country, b.city)
      || '|'
      || b.zip
    INTO vcustdetails
    FROM tbaadm.cmg a,
      crmuser.address b
    WHERE TRIM (a.cif_id)          = TRIM (b.orgkey)
    AND UPPER (b.addresscategory) IN ('MAILING', 'REGISTERED')
    AND cust_id                   IN
      (SELECT cust_id FROM gam WHERE foracid = vforacid
      );
  EXCEPTION
  WHEN NO_DATA_FOUND THEN
    vcustdetails := NULL || '|' || NULL || '|' || NULL || '|' || NULL || '|' || NULL || '|' || NULL || '|' || NULL;
  END;
  RETURN vcustdetails;
END mfi_cust_details;
FUNCTION mfi_citycountry(
    vcountrycode VARCHAR2,
    vcitycode    VARCHAR2)
  RETURN VARCHAR2
IS
  vcountry      VARCHAR2 (50);
  vcity         VARCHAR2 (50);
  vcity_country VARCHAR2 (100);
BEGIN
  BEGIN
    SELECT ref_desc
    INTO vcountry
    FROM tbaadm.rct
    WHERE ref_rec_type = '03'
    AND ref_code       = vcountrycode;
  EXCEPTION
  WHEN NO_DATA_FOUND THEN
    vcountry := NULL;
  END;
  BEGIN
    SELECT ref_desc
    INTO vcity
    FROM tbaadm.rct
    WHERE ref_rec_type = '01'
    AND ref_code       = vcitycode;
  EXCEPTION
  WHEN NO_DATA_FOUND THEN
    vcity := NULL;
  END;
  vcity_country := vcity || '|' || vcountry;
  RETURN vcity_country;
END mfi_citycountry;
-- -----------------------------------------------------------------------
END mfi_statement_spool;
/
因此,我可以将其与Jasper一起使用,但包体不会编译,并出现以下错误:

PLS-00323: subprogram or cursor 'MFI_MAIN_SPOOL' is declared in a package specification and must be defined in the package body
有什么事情我做得不对吗?


看来,程序在签名 包装规格与包装体不同。 这两个应该完全匹配。你可以这样试试。 它应该会起作用。谢谢

CREATE OR REPLACE PACKAGE TBAADM.mfi_statement_spool
AS
   PROCEDURE mfi_main_spool (fromdate IN DATE, 
todate IN DATE,
c1 out SYS_REFCURSOR,
c2 out SYS_REFCURSOR);

   FUNCTION mfi_cust_details (vforacid IN VARCHAR2)
      RETURN VARCHAR2;

   FUNCTION mfi_citycountry (vcountrycode IN VARCHAR2, vcitycode IN VARCHAR2)
      RETURN VARCHAR2;
END mfi_statement_spool;
/

CREATE OR REPLACE PACKAGE BODY TBAADM.mfi_statement_spool
AS
   PROCEDURE mfi_main_spool (fromdate DATE, todate DATE)
   AS 
Begin
/* Stuff you want to do */
end mfi_main_spool;
/* definition of other procedures and function. */
end mfi_statement_spool;

您必须首先更新软件包规范:

CREATE OR REPLACE PACKAGE mfi_statement_spool
AS
   PROCEDURE mfi_main_spool (fromdate IN DATE, todate IN DATE,c1 out SYS_REFCURSOR,c2 out SYS_REFCURSOR);

   FUNCTION mfi_cust_details (vforacid IN VARCHAR2)
      RETURN VARCHAR2;

   FUNCTION mfi_citycountry (vcountrycode IN VARCHAR2, vcitycode IN VARCHAR2)
      RETURN VARCHAR2;
END mfi_statement_spool;
/
之后,使用新参数更新包体:

CREATE OR REPLACE PACKAGE BODY mfi_statement_spool
AS
-- --------------------------------------------------------------------------
   PROCEDURE mfi_main_spool (fromdate DATE, todate DATE, c1 out SYS_REFCURSOR,c2 out SYS_REFCURSOR)
   AS
      cramount            NUMBER;
      dramount            NUMBER;
   BEGIN
     OPEN c1 for
       SELECT foracid,
         acct_name,
         addr_1,
         addr_2,
         sol_desc,
         city_code,
         gam.FUTURE_UN_CLR_BAL_AMT
       FROM tbaadm.gam,
         tbaadm.sol
       WHERE gam.sol_id   = sol.sol_id
         AND schm_type     IN ('CAA','ODA','LAA')
         AND schm_code NOT IN ('CTSTF');
     -- handle c2 the same way...
     LOOP
       FETCH c1 into v_foracid, v_acct_name, v_addr_1, ...;
       EXIT WHEN c1%NOTFOUND;
       -- do something with your variables here
     END LOOP;
     CLOSE c1;
     -- same for c2 again...
   END mfi_main_spool;

   FUNCTION mfi_cust_details (vforacid IN VARCHAR2) RETURN VARCHAR2 IS
   BEGIN
 NULL;
     -- do something here
   END mfi_cust_details;

   FUNCTION mfi_citycountry (vcountrycode IN VARCHAR2, vcitycode IN VARCHAR2) RETURN VARCHAR2 IS
   BEGIN
 NULL;
     -- do something here
   END mfi_citycountry;
    END;
         /
这样对我来说很好。

对于在包规范中定义的每个过程,在包体中必须有一个以相同方式定义的过程,这意味着它具有相同的名称,需要相同的参数,如果它是函数,则具有相同的返回类型,等等。
但是你可以在你的身体里有更多隐藏的程序和功能,而这些程序和功能是从包外无法访问的。它们不必在包规范中定义

有关
SYS\u REFCURSOR
的指南,请参见此处:
或者在这里:

从我得到的是,包有游标声明,而主体没有,但这就是给我的
错误(3,14):PLS-00323:子程序或游标“MFI_MAIN_SPOOL”在包规范中声明,必须在包主体中定义,但这正是我尝试过的,错误仍然存在。有关详细信息,请参阅我更新的问题。@stanley您的问题没有更新。请更新您的包装规格,而不仅仅是您的程序declaration@stanley我更新了我的答案,使它更清楚我的意思检查它在那里。我已经更改了包和包体,但错误仍然存在there@stanley再次更新它。这样对我来说很好。您是否在包体中定义了
c1
c2
?它们必须声明为正常变量,因为它们是
OUT
-参数?是的,我已声明为SYS\u REFCURSOR。这可能是个错误吗?不,系统应该没问题。我将对您的包和包体发布一个完整的概述。如果你的代码看起来像这样,你可能需要发布更多的代码,因为到目前为止,错误似乎不在你发布的部分中。请看,我已经发布了全部代码。完整的包体。如果您有一个
系统加油器
您不能将其与
光标c1为..
一起使用,您必须执行以下操作:
打开c1进行选择…
CREATE OR REPLACE PACKAGE BODY mfi_statement_spool
AS
-- --------------------------------------------------------------------------
   PROCEDURE mfi_main_spool (fromdate DATE, todate DATE, c1 out SYS_REFCURSOR,c2 out SYS_REFCURSOR)
   AS
      cramount            NUMBER;
      dramount            NUMBER;
   BEGIN
     OPEN c1 for
       SELECT foracid,
         acct_name,
         addr_1,
         addr_2,
         sol_desc,
         city_code,
         gam.FUTURE_UN_CLR_BAL_AMT
       FROM tbaadm.gam,
         tbaadm.sol
       WHERE gam.sol_id   = sol.sol_id
         AND schm_type     IN ('CAA','ODA','LAA')
         AND schm_code NOT IN ('CTSTF');
     -- handle c2 the same way...
     LOOP
       FETCH c1 into v_foracid, v_acct_name, v_addr_1, ...;
       EXIT WHEN c1%NOTFOUND;
       -- do something with your variables here
     END LOOP;
     CLOSE c1;
     -- same for c2 again...
   END mfi_main_spool;

   FUNCTION mfi_cust_details (vforacid IN VARCHAR2) RETURN VARCHAR2 IS
   BEGIN
 NULL;
     -- do something here
   END mfi_cust_details;

   FUNCTION mfi_citycountry (vcountrycode IN VARCHAR2, vcitycode IN VARCHAR2) RETURN VARCHAR2 IS
   BEGIN
 NULL;
     -- do something here
   END mfi_citycountry;
    END;
         /