我们知道PL/SQL程序中运行SQL语句是存在开销的,因为SQL语句是要提交给SQL引擎处理,这种在PL/SQL引擎和SQL引擎之间的控制转移叫做上下文却换,每次却换时,都有额外的开销。
然而,FORALL和BULK COLLECT可以让PL/SQL引擎把多个上下文却换压缩成一个,这使得在PL/SQL中的要处理多行记录的SQL语句执行的花费时间骤降。
      

示例:
一、BULK COLLECT将所得的结果集一次性绑定(全部)

--下面的示例中使用了BULK COLLECT将得到的结果集绑定到记录变量中
DECLARE
   TYPE emp_rec_type IS RECORD  --声明记录类型
   (
      empno      emp.empno%TYPE
     ,ename      emp.ename%TYPE
     ,hiredate   emp.hiredate%TYPE
   );

   TYPE nested_emp_type IS TABLE OF emp_rec_type;  --声明记录类型变量
   emp_tab   nested_emp_type;
BEGIN
   SELECT empno, ename, hiredate
   BULK   COLLECT INTO emp_tab       --使用BULK COLLECT 将所得的结果集一次性绑定到记录变量emp_tab中
   FROM   emp;

   FOR i IN emp_tab.FIRST .. emp_tab.LAST
   LOOP
      DBMS_OUTPUT.put_line()||emp_tab(i).ename||chr()||emp_tab(i).hiredate);
   END LOOP;
END;
--上面的例子可以通过FOR 循环和普通的SELECT INTO来实现,那两者之间的差异呢?
--差异是FOR循环的SELECT INTO逐行提取并绑定到记录变量,而BULK COLLECT则一次即可提取所有行并绑定到记录变量。即谓批量绑定。

二、使用LIMIT限制FETCH数据量(限制数量)
在使用BULK COLLECT 子句时,对于集合类型,如嵌套表,联合数组等会自动对其进行初始化以及扩展(如下示例)。因此如果使用BULK COLLECT子句操作集合,则无需对集合进行初始化以及扩展。由于BULK COLLECT的批量特性,如果数据量较大,而集合在此时又自动扩展,为避免过大的数据集造成性能下降,因此使用limit子句来限制一次提取的数据量。limit子句只允许出现在fetch操作语句的批量中。
用法:
    FETCH ... BULK COLLECT INTO ... [LIMIT rows]

DECLARE
   CURSOR emp_cur IS
      SELECT empno, ename, hiredate FROM emp;

   TYPE emp_rec_type IS RECORD
   (
      empno      emp.empno%TYPE
     ,ename      emp.ename%TYPE
     ,hiredate   emp.hiredate%TYPE
   );

   TYPE nested_emp_type IS TABLE OF emp_rec_type;   -->定义了基于记录的嵌套表
   emp_tab     nested_emp_type;           -->定义集合变量,此时未初始化
   v_limit     PLS_INTEGER := 5;          -->定义了一个变量来作为limit的值
   v_counter   PLS_INTEGER := ;
BEGIN
   OPEN emp_cur;

   LOOP
      FETCH emp_cur
      BULK   COLLECT INTO emp_tab         -->fetch时使用了BULK COLLECT子句
      LIMIT v_limit;                      -->使用limit子句限制提取数据量

      EXIT WHEN emp_tab.COUNT = ;        -->注意此时游标退出使用了emp_tab.COUNT,而不是emp_cur%notfound
      v_counter   := v_counter + ;       -->记录使用LIMIT之后fetch的次数

      FOR i IN emp_tab.FIRST .. emp_tab.LAST
      LOOP
         DBMS_OUTPUT.put_line( )||emp_tab(i).ename||CHR()||emp_tab(i).hiredate);
      END LOOP;
   END LOOP;

   CLOSE emp_cur;

   DBMS_OUTPUT.put_line( 'The v_counter is ' || v_counter );
END;

三、使用 RETURNING 子句的批量绑定
    BULK COLLECT除了与SELECT,FETCH进行批量绑定之外,还可以与INSERT,DELETE,UPDATE语句结合使用。当与这几个DML语句结合时,我们
需要使用RETURNING子句来实现批量绑定。

--下面示例中从表emp中删除所有deptno=20的记录
DECLARE
   TYPE emp_rec_type IS RECORD
   (
      empno      emp.empno%TYPE
     ,ename      emp.ename%TYPE
     ,hiredate   emp.hiredate%TYPE
   );

   TYPE nested_emp_type IS TABLE OF emp_rec_type;
   emp_tab   nested_emp_type;
--   v_limit   PLS_INTEGER := ;
--   v_counter   PLS_INTEGER := ;
BEGIN
   DELETE FROM emp
   WHERE  deptno =
   RETURNING empno, ename, hiredate     -->使用returning 返回这几个列
   BULK   COLLECT INTO emp_tab;         -->将前面返回的列的数据批量插入到集合变量  

   DBMS_OUTPUT.put_line( 'Deleted ' || SQL%ROWCOUNT || ' rows.' );
   COMMIT;

   IF emp_tab.COUNT >  THEN                 -->当集合变量不为空时,输出所有被删除的元素
      FOR i IN emp_tab.FIRST .. emp_tab.LAST
      LOOP
         DBMS_OUTPUT.
          put_line(
                       'Current record  '
                    || emp_tab( i ).empno
                    || CHR(  )
                    || emp_tab( i ).ename
                    || CHR(  )
                    || emp_tab( i ).hiredate
                    || ' has been deleted' );
      END LOOP;
   END IF;
END;

四、BULK COLLECT的限制
1、不能对使用字符串类型作键的关联数组使用BULK COLLECT 子句。
2、只能在服务器端的程序中使用BULK COLLECT,如果在客户端使用,就会产生一个不支持这个特性的错误。
3、BULK COLLECT INTO 的目标对象必须是集合类型。
4、复合目标(如对象类型)不能在RETURNING INTO 子句中使用。
5、如果有多个隐式的数据类型转换的情况存在,多重复合目标就不能在BULK COLLECT INTO 子句中使用。
6、如果有一个隐式的数据类型转换,复合目标的集合(如对象类型集合)就不能用于BULK COLLECTINTO 子句中。

最新文章

  1. Linux 进程与线程六
  2. 一个asp采集程序
  3. 疯狂房价"逼死"年轻人,别指望中国未来能出人才了
  4. JavaBean 的小知识点
  5. 【BZOJ-1076】奖励关 概率与期望 + 状态压缩DP
  6. linux下系统对于sigsegv错误时的处理
  7. iOS开发——UI进阶篇(十六)Quartz2D实战小例子
  8. Highcharts用函数动态填充静态值
  9. Teradata(不同date输出要求;表类型)
  10. 事件函数SetEvent、PulseEvent与WaitForSingleObject详解
  11. 使用jQuery POST提交数据返回的JSON是字符串不能解析为JSON对象
  12. 获取字符宽度:并非自适应。coretext去计算
  13. js和java中使用正则表达式校验邮箱
  14. 洛谷 [P1387] 最大正方形
  15. Chapter 2 User Authentication, Authorization, and Security(6):服务器权限授予粒度
  16. 第五节:WebApi的三大过滤器
  17. c——闰年
  18. Java数据库操作(MySQL与SQLserver)
  19. PAT (Advanced Level) Practise 1003 解题报告
  20. 003-读书笔记-企业IT架构转型之道-阿里巴巴中台战略思想与架构实战-分布式服务框架的选择

热门文章

  1. R语言基础入门之二:数据导入和描述统计
  2. C# WPF DataGrid 隔行变色及内容居中对齐
  3. Membership如何得到当前登录的用户名称
  4. Mssql 跨域查询
  5. web自动化:前端页面组成
  6. 利用CocoaLumberjack框架+XcodeColors插件,调试输出有彩色的信息
  7. 将【恢复和重新安装Windows】的介质指定到硬盘
  8. ural 2021 Scarily interesting!(贪心)
  9. 基于vue的滚动条组件之--element隐藏组件滚动条scrollbar使用
  10. 5.MySQL优化---索引优化专题