我在第 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;