-2

我是 Oracle 的新手,我被这个错误困住了。

这是我的过程:

CREATE OR REPLACE PROCEDURE PROC_UPD_TABLE1
AS
TYPE TY_CALC_REC IS RECORD(
SERIALNO     VARCHAR(50),
TOT_CHARGE   NUMBER(38,4),
RATE         NUMBER(38,4),
RATEPS       NUMBER(38,4),
STS          VARCHAR(50),
REMARKS      VARCHAR(50),
INFO         VARCHAR(50)
 );

 CV_GET_REFNO TY_CALC_REC;
CURSOR CUR_UPD_TBL1 IS SELECT T2.PRODUCTID, T2.ON_NET, T2.OFF_NET FROM TABLE2 T2;

CURSOR CUR_TRAN IS SELECT SERIALNO,
      (NVL(CHARGEAMOUNT1,0)+
       NVL(CHARGEAMOUNT2,0)+
       NVL(CHARGEAMOUNT3,0)+
       NVL(CHARGEAMOUNT4,0))/POWER(10,6) TOT_CHARGE,
       ROUND((((NVL(CHARGEAMOUNT1,0)+
       NVL(CHARGEAMOUNT2,0)+
       NVL(CHARGEAMOUNT3,0)+
       NVL(CHARGEAMOUNT4,0))/POWER(10,6))/CEIL(T1.CALLDURATION/60)),2) RATE,
       ROUND((((NVL(CHARGEAMOUNT1,0)+
       NVL(CHARGEAMOUNT2,0)+
       NVL(CHARGEAMOUNT3,0)+
       NVL(CHARGEAMOUNT4,0))/POWER(10,6))/T1.CALLDURATION),6) RATEPS,
       CASE WHEN (T1.ONNET =  ROUND((((NVL(CHARGEAMOUNT1,0)+
       NVL(CHARGEAMOUNT2,0)+
       NVL(CHARGEAMOUNT3,0)+
       NVL(CHARGEAMOUNT4,0))/POWER(10,6))/CEIL(T1.CALLDURATION/60)),2)) OR
       (T1.ONNET =  ROUND((((NVL(CHARGEAMOUNT1,0)+
       NVL(CHARGEAMOUNT2,0)+
       NVL(CHARGEAMOUNT3,0)+
       NVL(CHARGEAMOUNT4,0))/POWER(10,6))/T1.CALLDURATION),2))
        THEN 'ON-NET'
       WHEN (T1.OFFNET =  ROUND((((NVL(CHARGEAMOUNT1,0)+
       NVL(CHARGEAMOUNT2,0)+
       NVL(CHARGEAMOUNT3,0)+
       NVL(CHARGEAMOUNT4,0))/POWER(10,6))/CEIL(T1.CALLDURATION/60)),2)) OR
       (T1.OFFNET =  ROUND((((NVL(CHARGEAMOUNT1,0)+
       NVL(CHARGEAMOUNT2,0)+
       NVL(CHARGEAMOUNT3,0)+
       NVL(CHARGEAMOUNT4,0))/POWER(10,6))/T1.CALLDURATION),2)) THEN 'OFF-NET'
       ELSE 'CHECK' END STS,
       CASE WHEN T1.PRODUCTID <> NVL(T1.PRODUCTID1, T1.PRODUCTID) OR  T1.PRODUCTID <> NVL(T1.PRODUCTID2, T1.PRODUCTID) THEN
       'MULTIPLE PRODUCTID'    
       WHEN (T1.ONNET =  ROUND((((NVL(CHARGEAMOUNT1,0)+
       NVL(CHARGEAMOUNT2,0)+
       NVL(CHARGEAMOUNT3,0)+
       NVL(CHARGEAMOUNT4,0))/POWER(10,6))/CEIL(T1.CALLDURATION/60)),2)) OR
       (T1.ONNET =  ROUND((((NVL(CHARGEAMOUNT1,0)+
       NVL(CHARGEAMOUNT2,0)+
       NVL(CHARGEAMOUNT3,0)+
       NVL(CHARGEAMOUNT4,0))/POWER(10,6))/T1.CALLDURATION),2))
       OR (T1.OFFNET =  ROUND((((NVL(CHARGEAMOUNT1,0)+
       NVL(CHARGEAMOUNT2,0)+
       NVL(CHARGEAMOUNT3,0)+
       NVL(CHARGEAMOUNT4,0))/POWER(10,6))/CEIL(T1.CALLDURATION/60)),2)) OR
       (T1.OFFNET =  ROUND((((NVL(CHARGEAMOUNT1,0)+
       NVL(CHARGEAMOUNT2,0)+
       NVL(CHARGEAMOUNT3,0)+
       NVL(CHARGEAMOUNT4,0))/POWER(10,6))/T1.CALLDURATION),2)) THEN 'OKAY'
       WHEN
       ((ROUND((((NVL(CHARGEAMOUNT1,0)+
       NVL(CHARGEAMOUNT2,0)+
       NVL(CHARGEAMOUNT3,0)+
       NVL(CHARGEAMOUNT4,0))/POWER(10,6))/CEIL(T1.CALLDURATION/60)),2)  < T1.ONNET )   OR
       ( ROUND((((NVL(CHARGEAMOUNT1,0)+
       NVL(CHARGEAMOUNT2,0)+
       NVL(CHARGEAMOUNT3,0)+
       NVL(CHARGEAMOUNT4,0))/POWER(10,6))/T1.CALLDURATION),2)  < T1.ONNET ) 
       OR (ROUND((((NVL(CHARGEAMOUNT1,0)+
       NVL(CHARGEAMOUNT2,0)+
       NVL(CHARGEAMOUNT3,0)+
       NVL(CHARGEAMOUNT4,0))/POWER(10,6))/CEIL(T1.CALLDURATION/60)),2) < T1.OFFNET) OR
       ( ROUND((((NVL(CHARGEAMOUNT1,0)+
       NVL(CHARGEAMOUNT2,0)+
       NVL(CHARGEAMOUNT3,0)+
       NVL(CHARGEAMOUNT4,0))/POWER(10,6))/T1.CALLDURATION),2) < T1.OFFNET )) AND
       T1.CALLDURATION > T1.CHARGEDURATION THEN 'OKAY FREE'
       ELSE 'CHECK' END REMARKS,
       CASE WHEN(SELECT COUNT(1) FROM TABLE3 T3 WHERE (T3.NUM = SUBSTR(T1.CALLINGNUMBER,1,1))
  OR (T3.NUM = SUBSTR(T1.CALLINGNUMBER,1,2)) OR (T3.NUM = SUBSTR(T1.CALLINGNUMBER,1,3)) OR (T3.NUM = SUBSTR(T1.CALLINGNUMBER,1,4))) = 0 THEN 'FALSE'
  ELSE 'TRUE' END INFO
  FROM TABLE1 T1;
  V_NUM_LIMIT NUMBER := 50000;
BEGIN
 FOR J IN CUR_UPD_TBL1 LOOP

  UPDATE /*+NO_LOGGING*/ TABLE1 TB1 SET TB1.ONNET = J.ON_NET, TB1.OFFNET = J.OFF_NET WHERE TB1.PRODUCTID = J.PRODUCTID;
  COMMIT;
 END LOOP;
OPEN CUR_TRAN;
LOOP
FETCH CUR_TRAN BULK COLLECT INTO CV_GET_REFNO LIMIT V_NUM_LIMIT;
IF CV_GET_REFNO.SERIALNO.COUNT > 0 THEN
FORALL I IN 1.. CV_GET_REFNO.SERIALNO.COUNT
  UPDATE /*+ NO_LOGGING */ TABLE1 T SET T.STS = CV_GET_REFNO.STS(I),
  T.REMARKS = CV_GET_REFNO.REMARKS(I),
  T.RATEPS = CV_GET_REFNO.RATEPS(I),
  T.RATE = CV_GET_REFNO.RATE(I),
  T.CHARGE = CV_GET_REFNO.TOT_CHARGE(I),
  T.INFO = CV_GET_REFNO.INFO(I)
  WHERE T.SERIALNO = CV_GET_REFNO.SERIALNO(I);
  COMMIT;
END IF;
EXIT WHEN CUR_TRAN%NOTFOUND;
END LOOP;
 COMMIT;
END;

这就是我得到的错误:

PLS-00597: expression 'CV_GET_REFNO' in the INTO list is of wrong type  (LINE 99)                                                              PLS-00487: Invalid reference to variable 'SERIALNO' (LINE 98)
4

1 回答 1

1

您不能BULK COLLECT 与记录类型一起使用,而记录只能存储一行并BULK COLLECT允许您获取多行(在您的情况下为 v_num_limit)

你需要一个表类型:

    CREATE OR REPLACE PROCEDURE PROC_UPD_TABLE1
    AS
    TYPE TY_CALC_REC IS RECORD(
    SERIALNO     VARCHAR(50),
    TOT_CHARGE   NUMBER(38,4),
    RATE         NUMBER(38,4),
    RATEPS       NUMBER(38,4),
    STS          VARCHAR(50),
    REMARKS      VARCHAR(50),
    INFO         VARCHAR(50)
     );

     --
     -- CHANGE BEGIN
     --

     -- CV_GET_REFNO TY_CALC_REC;

     type ty_calc_rec_tab is table of ty_calc_rec;
     CV_GET_REFNO ty_calc_rec_tab;
     --
     -- CHANGE END
     --


     CURSOR CUR_UPD_TBL1 IS SELECT T2.PRODUCTID, T2.ON_NET, T2.OFF_NET FROM TABLE2 T2;
...

您可以像这样使用 CV_GET_REFNO :

LOOP
FETCH CUR_TRAN BULK COLLECT INTO CV_GET_REFNO LIMIT V_NUM_LIMIT;
IF CV_GET_REFNO.COUNT > 0 THEN

-- CHANGE BEGIN

FOR I IN 1.. CV_GET_REFNO.COUNT
LOOP
  UPDATE /*+ NO_LOGGING */ TABLE1 T SET T.STS = CV_GET_REFNO(I).STS,
  T.REMARKS = CV_GET_REFNO(I).REMARKS,
  T.RATEPS = CV_GET_REFNO(I).RATEPS,
  T.RATE = CV_GET_REFNO(I).RATE,
  T.CHARGE = CV_GET_REFNO(I).TOT_CHARGE,
  T.INFO = CV_GET_REFNO(I).INFO
  WHERE T.SERIALNO = CV_GET_REFNO(I).SERIALNO;
 END LOOP;

 -- CHANGE END

  COMMIT;

END IF;
EXIT WHEN CUR_TRAN%NOTFOUND;
END LOOP;
于 2013-09-11T12:34:07.613 回答