Home > Enterprise >  LIMIT clause usage in PLSQL
LIMIT clause usage in PLSQL

Time:09-28

I have a procedure which is used for extracting data and then inserting them. My problem is that I am using BULK COLLECTION. My goal is that I want to every time extract for example 10,000 data then insert these 10,000 records. But in my script I can limit it with that value but it doesn't insert more. For instance I have 6 records and I used 4 with LIMIT clause. What I want is the procedure should first insert 4 record then extract remaining 2 records for example.

I have I can describe issue briefly. I am open to any fix advices in my scripts. Thank you from now.

I solved my problem added new version of script below, thank you everyone

create or replace procedure GPU_DATA_EXTRACTOR_TEST(pid_billdate DATE) is
v_cnt      NUMBER;
c_limit   CONSTANT PLS_INTEGER DEFAULT 4;

CURSOR c1 IS
SELECT DISTINCT intl_prod_id
      FROM apld_bill_rt abr,
           acct_bill ab
      WHERE abr.CHRG_TP = 'INSTALLMENT'
          AND abr.TAX_CATG_ID = 'NOTAX'
          AND abr.acct_bill_id = ab.acct_bill_id
          AND ab.bill_date = pid_billdate;

TYPE prod_ids_t IS TABLE OF apld_bill_rt.intl_prod_id%TYPE INDEX BY PLS_INTEGER;
l_prod_ids   prod_ids_t;
begin

   execute immediate 'truncate table GPU_INV_TEST';

   v_cnt := 0;
  OPEN c1;

  LOOP
     FETCH c1 BULK COLLECT INTO l_prod_ids LIMIT c_limit;
     
     EXIT WHEN l_prod_ids.COUNT = 0;

    FOR indx IN 1 .. l_prod_ids.COUNT
    loop
      INSERT INTO GPU_INV_TEST
         SELECT AB.ACCT_BILL_ID,
                AB.BILL_NO,
                AB.INV_ID,
                AB.BILL_DATE,
                ba2.bill_acct_id,
                ba1.bill_acct_id parent_bill_acct_id,
                AB.DUE_DATE,
                PG.CMPG_ID,
                ABR.NET_AMT,
                AB.DUE_AMT,
                P.PROD_NUM,
                pds.DST_ID,
                ABR.DESCR,
                p.intl_prod_id
           FROM apld_bill_rt abr,
                acct_bill ab,
                prod p,
                FCBSADM.PROD_DST pds,
                bill_acct_prod bap,
                bill_acct ba1,
                bill_acct ba2,
                prod_cmpg pg
          WHERE ab.intl_bill_acct_id = ba1.intl_bill_acct_id
                AND AB.ACCT_BILL_ID = ABR.ACCT_BILL_ID
                AND ba1.intl_bill_acct_id = ba2.parent_bill_acct_id
                AND ba2.intl_bill_acct_id = bap.intl_bill_acct_id
                AND bap.intl_prod_id = abr.intl_prod_id
                AND ABR.CHRG_TP = 'INSTALLMENT'
                AND bap.intl_prod_id = pds.intl_prod_id
                AND bap.intl_prod_id = p.intl_prod_id
                AND p.intl_prod_id = pg.intl_prod_id( )
                AND ABR.intl_prod_id = l_prod_ids(indx)
UNION
    SELECT AB.ACCT_BILL_ID,
                AB.BILL_NO,
                AB.INV_ID,
                AB.BILL_DATE,
                ba1.bill_acct_id,
                ba1.bill_acct_id parent_bill_acct_id,
                AB.DUE_DATE,
                PG.CMPG_ID,
                ABR.NET_AMT,
                AB.DUE_AMT,
                P.PROD_NUM,
                pds.DST_ID,
                ABR.DESCR,
                p.intl_prod_id
           FROM apld_bill_rt abr,
                acct_bill ab,
                prod p,
                FCBSADM.PROD_DST pds,
                bill_acct_prod bap,
                bill_acct ba1,
                prod_cmpg pg
          WHERE ab.intl_bill_acct_id = ba1.intl_bill_acct_id
                AND AB.ACCT_BILL_ID = ABR.ACCT_BILL_ID
                --AND ba1.intl_bill_acct_id = ba2.parent_bill_acct_id
                AND ba1.intl_bill_acct_id = bap.intl_bill_acct_id
                AND bap.intl_prod_id = abr.intl_prod_id
                AND ABR.CHRG_TP = 'INSTALLMENT'
                AND bap.intl_prod_id = pds.intl_prod_id
                AND bap.intl_prod_id = p.intl_prod_id
                AND p.intl_prod_id = pg.intl_prod_id( )
                AND ABR.intl_prod_id = l_prod_ids(indx);

      v_cnt := v_cnt   1;

      IF MOD (v_cnt, 4) = 0
      THEN
         COMMIT;
      END IF;

    end loop;
    COMMIT;
    END LOOP;
   CLOSE c1;
end;

CodePudding user response:

You need a LOOP in order to fetch multiple subsets of records. Example snippet:

...
loop
  FETCH c1 BULK COLLECT INTO l_prod_ids LIMIT c_limit;
  exit when l_prod_ids.count = 0;
  
  FOR indx IN 1 .. l_prod_ids.COUNT
    ...
end loop;
CLOSE c1;
...

Incidentally, executing thousands of individual INSERT statements is a recipe for poor performance. You should use the FORALL syntax (which is not a loop) to execute a set-based insert operation driving from your collection. Find out more.

You should also give consideration as to whether you ought to be using a collection at all, when you could just use a pure SQL INSERT INTO ... SELECT ... FROM statement. That would perform even better than a FORALL operation.

  • Related