ever alian
ever alian

Reputation: 1060

When is the SQL cursor loads the data?

I have following script to update local table, by reading a remote source table. Script is running fine without any error. This post is to clarify properly about, How the cursor works.

I read data from remote source table Source_Product and initially insert into temp table VW_PRODUCT. After that I insert or update my PRODUCT table.

My questions are.

1) When does the product_cursor load the data? Is it when we try to read the cursor in the for loop? or when ever declare the cursor it loads the data?

2) This script runs daily. If the product_cursor runs as soon as it declare, then VW_PRODUCT has previous day data. Because still the today data is not inserted to VW_PRODUCT table ( insert query is available after the cursor declaration). So the product_cursor will not have any record after minus. Because ysterday_data minus ysterday_data is zero. So how can it update or insert the latest data to PRODUCT according to below script?

SET serveroutput ON SIZE 1000000;

DECLARE
   CURSOR product_cursor
   IS
        SELECT V.PRODUCTID,
               V.PACKAGEID'
               V.ENDDATE               
          FROM VW_PRODUCT V
        MINUS
        SELECT E.PRODUCTID,
               E.PACKAGEID,
               E.ENDDATE               
          FROM PRODUCT E;

   /*The delete data*/
   CURSOR product_cursor_del
   IS
        SELECT E.PRODUCTID FROM PRODUCT E WHERE (E.ENDDATE > SYSDATE OR E.ENDDATE IS NULL)
        MINUS
        SELECT V.PRODUCTID FROM VW_PRODUCT V;

   /* Variable Declaration*/
   v_total           NUMBER (10);
   v_inserted        NUMBER (10);
   v_updated         NUMBER (10);
   v_deleted         NUMBER (10);
   v_rows_inserted   NUMBER (10);
   v_productid       PRODUCT.PRODUCTID%TYPE;
   v_count           NUMBER (10);
   v_commit_point    NUMBER        := 25;
BEGIN
   v_total := 0;
   v_count := 0;
   v_inserted := 0;
   v_updated := 0;
   v_deleted := 0;
   v_rows_inserted := 0;

   EXECUTE IMMEDIATE 'TRUNCATE TABLE VW_PRODUCT';
   INSERT INTO VW_PRODUCT
      SELECT * FROM Source_Product;

   SELECT COUNT (*)
     INTO v_rows_inserted
     FROM VW_PRODUCT;

   COMMIT;

    /*delete data*/
   FOR product_rec IN product_cursor_del
   LOOP
      BEGIN
         v_total := v_total + 1;

         update product set enddate = sysdate
               WHERE productid = product_rec.productid and enddate is null;

         v_deleted := v_deleted + 1;
         v_count := v_count + 1;

         IF (v_count >= v_commit_point)
         THEN
            COMMIT;
            v_count := 0;
         END IF;
      EXCEPTION
         WHEN OTHERS
         THEN
            BEGIN
               DBMS_OUTPUT.put_line (   'Exception with product: ' );

            END;
      END;
   END LOOP;

   FOR product_rec IN product_cursor
   LOOP
      BEGIN
         v_total := v_total + 1;

        SELECT productid
            INTO v_productid
          FROM product
         WHERE productid = product_rec.productid;

        update PRODUCT
           set PACKAGEID        = product_rec.PACKAGEID,        
               ENDDATE          = product_rec.ENDDATE          
         WHERE PRODUCTID = product_rec.PRODUCTID;
         v_updated := v_updated + 1;
      EXCEPTION
         WHEN NO_DATA_FOUND
         THEN
           INSERT INTO PRODUCT
             (PRODUCTID,PACKAGEID,ENDDATE)
           VALUES
             (product_rec.PRODUCTID,
             product_rec.PACKAGEID,
             product_rec.ENDDATE);

            v_inserted := v_inserted + 1;
            v_count := v_count + 1;

            IF (v_count >= v_commit_point)
            THEN
               COMMIT;
               v_count := 0;
            END IF;
         WHEN OTHERS
         THEN
            raise_application_error ('Error );
      END;
   END LOOP;
  IF (v_total >= 1)
  THEN
    COMMIT;
  END IF;
END;
/

Upvotes: 1

Views: 944

Answers (1)

Lalit Kumar B
Lalit Kumar B

Reputation: 49082

In a nutshell, to answer your basic questions,

  1. A cursor doesn't store any result set, it is a pointer used to fetch rows from a result set.
  2. Memory is not consumed at declare stage.
  3. It is the FETCH statement when you are actually using the cursor. The FETCH statement retrieves rows from the result set and places them into an area in the memory. You could fetch the rows one at a time, several at a time, or all at once.

The FETCH statement performs the following operations:

  • Reads the data for the current row in the result set into the output PL/SQL variables.
  • Moves the pointer to the next row in the result set.

Take a look at working with cursors.

Upvotes: 1

Related Questions