Reputation: 2821
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?
Upvotes: 0
Views: 8883
Reputation: 146329
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);
Upvotes: 3