0

99 行目でこのエラーが発生しています。1,000 万から 3,000 万のレコードを処理する必要があるため、非常に効率的な方法で作業する必要があります。エラーは 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 に答える