简体   繁体   English

SQL光标何时加载数据?

[英]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 . 我从远程源表Source_Product读取数据,并最初插入到临时表VW_PRODUCT After that I insert or update my PRODUCT table. 之后,我插入或更新PRODUCT表。

My questions are. 我的问题是。

1) When does the product_cursor load the data? 1) product_cursor何时加载数据? Is it when we try to read the cursor in the for loop? 是当我们尝试在for循环中读取游标时? or when ever declare the cursor it loads the data? 还是在声明游标时加载数据?

2) This script runs daily. 2)该脚本每天运行。 If the product_cursor runs as soon as it declare, then VW_PRODUCT has previous day data. 如果product_cursor在声明后VW_PRODUCT运行,则VW_PRODUCT具有前一天的数据。 Because still the today data is not inserted to VW_PRODUCT table ( insert query is available after the cursor declaration). 因为仍然没有将今天的数据插入到VW_PRODUCT表中(在游标声明之后可以使用插入查询)。 So the product_cursor will not have any record after minus . 因此product_cursorminus之后将没有任何记录。 Because ysterday_data minus ysterday_data is zero. 因为ysterday_data minus ysterday_data为零。 So how can it update or insert the latest data to PRODUCT according to below script? 那么如何根据以下脚本将最新数据更新或插入PRODUCT

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;
/

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. 当您实际使用游标时,它是FETCH语句。 The FETCH statement retrieves rows from the result set and places them into an area in the memory. FETCH语句从结果集中检索行,并将其放入内存中的某个区域。 You could fetch the rows one at a time, several at a time, or all at once. 您可以一次获取一行,一次获取几行,也可以一次获取全部。

The FETCH statement performs the following operations: FETCH语句执行以下操作:

  • Reads the data for the current row in the result set into the output PL/SQL variables. 将结果集中当前行的数据读取到输出PL / SQL变量中。
  • Moves the pointer to the next row in the result set. 将指针移动到结果集中的下一行。

Take a look at working with cursors . 看一下使用游标

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM