zoukankan      html  css  js  c++  java
  • Oracle 遍历游标的四种方式(for、fetch、while、BULK COLLECT)

    1.情景展示

      Oracle 遍历游标的三种方式(for、fetch、while、bulk collect+forall)

    2.问题分析

      我们可以把游标想象成一张表,想要遍历游标,就要取到游标的每行数据,所以问题的关键就成了:如何取到行数据?

    3.解决方案

      方式一:FOR 循环(推荐使用)

      变形一:遍历显式游标

    /* 如果是在存储过程外使用显式游标,需要使用DECLARE关键字 */
    DECLARE
      /*创建游标*/
      CURSOR CUR_FIRST_INDEX IS
        SELECT A.ID        A_ID, --一级指标ID
               A.INDEXNAME A_INDEXNAME --一级指标名称
          FROM INDEX_A A
         ORDER BY A_ID;
      /*定义游标变量,该变量的类型为基于游标CUR_FIRST_INDEX的行记录*/
      ROW_CUR_FIRST_INDEX CUR_FIRST_INDEX%ROWTYPE;
    /*游标处理*/
    BEGIN
      /*遍历显式游标*/
      --FOR 循环
      FOR ROW_CUR_FIRST_INDEX IN CUR_FIRST_INDEX LOOP
        --循环体
        DBMS_OUTPUT.PUT_LINE('{"ID":"' || ROW_CUR_FIRST_INDEX.A_ID || '","名称":"' || ROW_CUR_FIRST_INDEX.A_INDEXNAME || '"}');
      END LOOP;
    END;  

      执行,输出结果

      变形二:遍历隐式游标(推荐使用)

      关于隐式游标的补充:20200519

      for循环遍历游标,其实又可以分为两种方式,一种是显式游标的遍历,另一种是隐式游标的遍历。

    /* 如果是在存储过程外使用隐式游标,如果用不到变量无需声明DECLARE关键字 */
    /*游标处理*/
    BEGIN
      /*遍历隐式游标*/
      --FOR 循环
      FOR ROW_CUR_FIRST_INDEX IN (SELECT A.ID        A_ID, --一级指标ID
                                         A.INDEXNAME A_INDEXNAME --一级指标名称
                                    FROM INDEX_A A
                                   ORDER BY A_ID) LOOP
        --循环体
        DBMS_OUTPUT.PUT_LINE('{"ID":"' || ROW_CUR_FIRST_INDEX.A_ID || '","名称":"' || ROW_CUR_FIRST_INDEX.A_INDEXNAME || '"}');
      END LOOP;
    END;
    

      隐式游标相较于显式游标用法更加简单,无需声明直接调用即可。    

      方式二:FETCH 循环

    /*游标声明代码和方式一一致,此处省略,直接展示游标处理代码*/
    BEGIN
      /*遍历游标*/
      --FETCH 循环
      OPEN CUR_FIRST_INDEX; --必须要明确的打开和关闭游标
      LOOP
        FETCH CUR_FIRST_INDEX INTO ROW_CUR_FIRST_INDEX;
        EXIT WHEN CUR_FIRST_INDEX%NOTFOUND;
        --循环体
        DBMS_OUTPUT.PUT_LINE('{"ID":"' || ROW_CUR_FIRST_INDEX.A_ID || '","名称":"' || ROW_CUR_FIRST_INDEX.A_INDEXNAME || '"}');
      END LOOP;
      CLOSE CUR_FIRST_INDEX;
    END;
    

      

      方式三:WHILE 循环

    /*游标声明代码和方式一一致,此处省略,直接展示游标处理代码*/
    BEGIN
      /*遍历游标*/
      OPEN CUR_FIRST_INDEX; --必须要明确的打开和关闭游标 
      FETCH CUR_FIRST_INDEX
        INTO ROW_CUR_FIRST_INDEX;
      WHILE CUR_FIRST_INDEX%FOUND LOOP
        --循环体 
        DBMS_OUTPUT.PUT_LINE('{"ID":"' || ROW_CUR_FIRST_INDEX.A_ID || '","名称":"' || ROW_CUR_FIRST_INDEX.A_INDEXNAME || '"}');
        FETCH CUR_FIRST_INDEX
          INTO ROW_CUR_FIRST_INDEX;
      END LOOP;
      CLOSE CUR_FIRST_INDEX;
    END;  

      注意:使用while循环时,需要fetch两次。

      方式四:BULK COLLECT+FORALL(速度最快)

    /* 如果是在存储过程外使用显示游标,需要使用DECLARE关键字 */
    /*声明游标*/
    DECLARE
      /*创建显式游标*/
      CURSOR CUR_FIRST_INDEX IS
        SELECT A.ID        A_ID, --一级指标ID
               A.INDEXNAME A_INDEXNAME --一级指标名称
          FROM INDEX_A A
         ORDER BY A_ID;
      /*定义表类型,该表的表结构为游标CUR_FIRST_INDEX的行记录(可以存储多条游标记录)*/
      TYPE TABLE_CUR_FIRST_INDEX IS TABLE OF CUR_FIRST_INDEX%ROWTYPE;
      /* 声明表变量*/
      TAB_FIRST_INDEX TABLE_CUR_FIRST_INDEX;
    /*游标处理过程*/
    BEGIN
      /*遍历游标*/
      OPEN CUR_FIRST_INDEX;
      LOOP
        --将n行游标数据放到表中
        FETCH CUR_FIRST_INDEX BULK COLLECT
          INTO TAB_FIRST_INDEX LIMIT 1; -- 数据量太少,仅当前测试使用哦,实际开发建议 500 左右
        -- 退出条件
        EXIT WHEN TAB_FIRST_INDEX.COUNT = 0;
        --循环表数据
        FORALL I IN TAB_FIRST_INDEX.FIRST .. TAB_FIRST_INDEX.LAST LOOP
          DBMS_OUTPUT.PUT_LINE('{"ID":"' || TAB_FIRST_INDEX(I).A_ID || '","名称":"' || TAB_FIRST_INDEX(I).A_INDEXNAME || '"}');
        END LOOP;
      END LOOP;
      CLOSE CUR_FIRST_INDEX;
    END;
    

        

    4.总结 

      使用for循环的优势在于:

      不需要手动打开&关闭游标(声明游标的开启和关闭);

      不需要手动捕获数据(自动将数据fetch到记录型变量);

      不需要关注何时要退出,也就是不需要写退出循环的满足条件(遍历完成就会退出)。

      第4方式与前3种的区别在于:

      前三种的游标变量:ROW_CUR_FIRST_INDEX,只能存储游标的一条数据;

      第四种的表变量:TAB_FIRST_INDEX,可以存储游标的多条数据。

      大数据批量处理的时候,第4种方式的优势将会凸显出来。

    写在最后

      哪位大佬如若发现文章存在纰漏之处或需要补充更多内容,欢迎留言!!!

     相关推荐:

  • 相关阅读:
    npm安装elasticsearch-reindex
    Linux14_文本编辑器与终端配置
    Linux13_群组的管理和文件权限的管理
    Linux12_用户和权限
    Linux11_文件及目录以及其相关的组织命令
    Linux10_常用命令和操作
    Linux9_安装Linux系统
    基础概念——什么是POSIX
    C++Review21_宏和常量
    C++Review20_C++函数高级特性(重载、内联、const和virtual)
  • 原文地址:https://www.cnblogs.com/Marydon20170307/p/12869692.html
Copyright © 2011-2022 走看看