简体   繁体   中英

PL/sql stored procedure ref cursor as parameter

I need to pass multiple rows to a stored procedure. Can I use a ref cursor? because I have tried the following:

Inside my package I have:

TYPE FACT_VND_RECORD
IS
  RECORD
  (
    COD_NOMCPDT P6PCM2_PARMCMS.COD_NOMCPDT%TYPE,
    LIB_LIBNOMCPDT P6PCM2_PARMCMS.LIB_LIBNOMCPDT%TYPE,
    DHS_MAJ P6PCM2_PARMCMS.DHS_MAJ%TYPE,
    LIB_AUTH_MAJ P6PCM2_PARMCMS.LIB_AUTH_MAJ%TYPE );

TYPE FACT_VND_CURSOR
    IS
      REF
      CURSOR
        RETURN FACT_VND_RECORD;

and 2 procedures:

PROCEDURE REC_FACT_VND(
      P_IN_NUM_VND   IN OUT P6PCM2_PARMCMS.NUM_VND%TYPE,
      P_OUT_FACT_VND IN OUT FACT_VND_CURSOR,
      P_OUT_CODE_RET OUT INTEGER,
      P_OUT_MSG_ERR OUT VARCHAR2);

  PROCEDURE MAJ_FACT_VND(
      P_IN_NUM_VND   IN OUT P6PCM2_PARMCMS.NUM_VND%TYPE,
      P_IN_FACT_VND IN OUT FACT_VND_CURSOR,
      P_OUT_CODE_RET OUT INTEGER,
      P_OUT_MSG_ERR OUT VARCHAR2); 

Recieves the previously filled cursor and does something with the data.

I use these 2 calls; The first one works OK, I can see the data inside ref cursor C1 and then I try to use it.

C1 PACK_REC_FACT_VND.FACT_VND_CURSOR;
--other definitons
      PACK_REC_FACT_VND.REC_FACT_VND(NUM_VND,C1,COD_RET,MSG_ERR);
    PACK_REC_FACT_VND.MAJ_FACT_VND(NUM_VND,C1,COD_RET,MSG_ERR);

I can't iterate over the data because it is undefined: (Code from second procedure)

LIGNE_TAUX PACK_REC_FACT_VND.FACT_VND_RECORD;
    BEGIN
      DELETE FROM P6PCM2_PARMCMS WHERE NUM_VND=P_IN_NUM_VND;
      FOR LIGNE_TAUX IN P_IN_FACT_VND
      LOOP
        INSERT
        INTO P6PCM2_PARMCMS VALUES
          (
            P_IN_NUM_VND,   
LIGNE_TAUX.COD_NOMCPDT, 
LIGNE_TAUX.LIB_LIBNOMCPDT, 
LIGNE_TAUX.DHS_MAJ, 
LIGNE_TAUX.LIB_AUTH_MAJ);
      END LOOP;

Error(48,21): PLS-00221: 'P_IN_FACT_VND' is not a procedure or is undefined

Or should I switch to TABLE OF RECORD?

We can't use ref cursors like that; we need to use the explicit cursor syntax. Try this (warning: untested code:):

        LIGNE_TAUX PACK_REC_FACT_VND.FACT_VND_RECORD;
    BEGIN
      DELETE FROM P6PCM2_PARMCMS WHERE NUM_VND=P_IN_NUM_VND;

      LOOP
         fetch P_IN_FACT_VND   into LIGNE_TAUX; 
         exit when P_IN_FACT_VND%notfound;
        INSERT
        INTO P6PCM2_PARMCMS VALUES
          (
            P_IN_NUM_VND,   
            LIGNE_TAUX.COD_NOMCPDT, 
            LIGNE_TAUX.LIB_LIBNOMCPDT, 
            LIGNE_TAUX.DHS_MAJ, 
            LIGNE_TAUX.LIB_AUTH_MAJ);
      END LOOP;

  close P_IN_FACT_VND;

However, get better performance if you fetch the records into a collection. Something like this:

        type LIGNE_TAUX_NT is table of PACK_REC_FACT_VND.FACT_VND_RECORD;
        LIGNE_TAUX_COLL LIGNE_TAUX_NT;
    BEGIN
      DELETE FROM P6PCM2_PARMCMS WHERE NUM_VND=P_IN_NUM_VND;

      fetch P_IN_FACT_VND bulk collect  into LIGNE_TAUX_COLL; 
      close P_IN_FACT_VND;

      -- while we're at it why not use the more efficient FORALL syntax 
      -- to perform the inserts?


      forall idx in LIGNE_TAUX_COLL.first() .. LIGNE_TAUX_COLL.last()
            INSERT
           INTO P6PCM2_PARMCMS VALUES
              (
            P_IN_NUM_VND,   
            LIGNE_TAUX_COLL(idx).COD_NOMCPDT, 
            LIGNE_TAUX_COLL(idx).LIB_LIBNOMCPDT, 
            LIGNE_TAUX_COLL(idx).DHS_MAJ, 
            LIGNE_TAUX_COLL(idx).LIB_AUTH_MAJ);

Find out more .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM