0

我在第 99 行收到此错误,我需要处理 10-30 百万条记录,因此我需要非常有效的工作方式。我猜这个错误是因为 BULK COLLECT INTO 但我不知道如何解决这个问题。

这是我的程序:

CREATE OR REPLACE PROCEDURE PROC_UPD_TABLE1
AS
TYPE TY_CALC_REC IS RECORD(
SERIALNO     DBMS_SQL.VARCHAR2_TABLE,
TOT_CHARGE   DBMS_SQL.NUMBER_TABLE,
RATE         DBMS_SQL.NUMBER_TABLE,
RATEPS       DBMS_SQL.NUMBER_TABLE,
STS          DBMS_SQL.VARCHAR2_TABLE,
REMARKS      DBMS_SQL.VARCHAR2_TABLE,
INFO         DBMS_SQL.VARCHAR2_TABLE
 );
  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;
4

1 回答 1

0

您在此处有收集记录,因此在批量收集期间将其作为批量收集指向 Record.collection。

FETCH CUR_TRAN BULK COLLECT INTO CV_GET_REFNO.SERIALNO, CV_GET_REFNO.TOT_CHARGE,{其他方式相同}

注意:忽略我之前的回答,不要使用我之前提到的表类型声明。我没有注意到您在记录类型中使用 DBMS_SQL。

于 2013-09-12T07:23:51.837 回答