BULK COLLECT 子句会批量检索结果,即一次性将结果集绑定到一个集合变量中,并从SQL引擎发送到PL/SQL引擎。通常可以在SELECT INTO、
FETCH INTO以及RETURNING INTO子句中使用BULK COLLECT。本文将逐一描述BULK COLLECT在这几种情形下的用法。
    有关FORALL语句的用法请参考:批量SQL之 FORALL 语句

一、BULK COLLECT批量绑定的示例

  1. --下面的示例中使用了BULK COLLECT将得到的结果集绑定到记录变量中
  2. DECLARE
  3. TYPE emp_rec_type IS RECORD          --声明记录类型
  4. (
  5. empno      emp.empno%TYPE
  6. ,ename      emp.ename%TYPE
  7. ,hiredate   emp.hiredate%TYPE
  8. );
  9. TYPE nested_emp_type IS TABLE OF emp_rec_type;  --声明记录类型变量
  10. emp_tab   nested_emp_type;
  11. BEGIN
  12. SELECT empno, ename, hiredate
  13. BULK   COLLECT INTO emp_tab       --使用BULK COLLECT 将所得的结果集一次性绑定到记录变量emp_tab中
  14. FROM   emp;
  15. FOR i IN emp_tab.FIRST .. emp_tab.LAST
  16. LOOP
  17. DBMS_OUTPUT.put_line('Current record is '||emp_tab(i).empno||chr(9)||emp_tab(i).ename||chr(9)||emp_tab(i).hiredate);
  18. END LOOP;
  19. END;
  20. --上面的例子可以通过FOR 循环和普通的SELECT INTO来实现,那两者之间的差异呢?
  21. --差异是FOR循环的SELECT INTO逐行提取并绑定到记录变量,而BULK COLLECT则一次即可提取所有行并绑定到记录变量。即谓批量绑定。

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

用法:
        FETCH ... BULK COLLECT INTO ... [LIMIT rows]

  1. DECLARE
  2. CURSOR emp_cur IS
  3. SELECT empno, ename, hiredate FROM emp;
  4. TYPE emp_rec_type IS RECORD
  5. (
  6. empno      emp.empno%TYPE
  7. ,ename      emp.ename%TYPE
  8. ,hiredate   emp.hiredate%TYPE
  9. );
  10. TYPE nested_emp_type IS TABLE OF emp_rec_type;   -->定义了基于记录的嵌套表
  11. emp_tab     nested_emp_type;           -->定义集合变量,此时未初始化
  12. v_limit     PLS_INTEGER := 5;          -->定义了一个变量来作为limit的值
  13. v_counter   PLS_INTEGER := 0;
  14. BEGIN
  15. OPEN emp_cur;
  16. LOOP
  17. FETCH emp_cur
  18. BULK   COLLECT INTO emp_tab         -->fetch时使用了BULK COLLECT子句
  19. LIMIT v_limit;                      -->使用limit子句限制提取数据量
  20. EXIT WHEN emp_tab.COUNT = 0;        -->注意此时游标退出使用了emp_tab.COUNT,而不是emp_cur%notfound
  21. v_counter   := v_counter + 1;       -->记录使用LIMIT之后fetch的次数
  22. FOR i IN emp_tab.FIRST .. emp_tab.LAST
  23. LOOP
  24. DBMS_OUTPUT.put_line( 'Current record is '||emp_tab(i).empno||CHR(9)||emp_tab(i).ename||CHR(9)||emp_tab(i).hiredate);
  25. END LOOP;
  26. END LOOP;
  27. CLOSE emp_cur;
  28. DBMS_OUTPUT.put_line( 'The v_counter is ' || v_counter );
  29. END;

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

  1. --下面示例中从表emp中删除所有deptno=20的记录
  2. DECLARE
  3. TYPE emp_rec_type IS RECORD
  4. (
  5. empno      emp.empno%TYPE
  6. ,ename      emp.ename%TYPE
  7. ,hiredate   emp.hiredate%TYPE
  8. );
  9. TYPE nested_emp_type IS TABLE OF emp_rec_type;
  10. emp_tab   nested_emp_type;
  11. --   v_limit   PLS_INTEGER := 3;
  12. --   v_counter   PLS_INTEGER := 0;
  13. BEGIN
  14. DELETE FROM emp
  15. WHERE  deptno = 20
  16. RETURNING empno, ename, hiredate     -->使用returning 返回这几个列
  17. BULK   COLLECT INTO emp_tab;         -->将前面返回的列的数据批量插入到集合变量
  18. DBMS_OUTPUT.put_line( 'Deleted ' || SQL%ROWCOUNT || ' rows.' );
  19. COMMIT;
  20. IF emp_tab.COUNT > 0 THEN                 -->当集合变量不为空时,输出所有被删除的元素
  21. FOR i IN emp_tab.FIRST .. emp_tab.LAST
  22. LOOP
  23. DBMS_OUTPUT.
  24. put_line(
  25. 'Current record  '
  26. || emp_tab( i ).empno
  27. || CHR( 9 )
  28. || emp_tab( i ).ename
  29. || CHR( 9 )
  30. || emp_tab( i ).hiredate
  31. || ' has been deleted' );
  32. END LOOP;
  33. END IF;
  34. END;

四、FORALL与BULK COLLECT 综合运用
    FORALL与BULK COLLECT是实现批量SQL的两个重要方式,我们可以将其结合使用以提高性能。下面的示例即是两者的总和运用。

  1. DROP TABLE tb_emp;
  2. CREATE TABLE tb_emp AS                        -->创建表tb_emp
  3. SELECT empno, ename, hiredate
  4. FROM   emp
  5. WHERE  1 = 2;
  6. DECLARE
  7. CURSOR emp_cur IS                          -->声明游标
  8. SELECT empno, ename, hiredate FROM emp;
  9. TYPE nested_emp_type IS TABLE OF emp_cur%ROWTYPE;  -->基于游标的嵌套表类型
  10. emp_tab   nested_emp_type;                         -->声明嵌套变量
  11. BEGIN
  12. SELECT empno, ename, hiredate
  13. BULK   COLLECT INTO emp_tab                        -->BULK  COLLECT批量提取数据
  14. FROM   emp
  15. WHERE  sal > 1000;
  16. FORALL i IN 1 .. emp_tab.COUNT                     -->使用FORALL语句将变量中的数据插入到表tb_emp
  17. INSERT INTO (SELECT empno, ename, hiredate FROM tb_emp)
  18. VALUES emp_tab( i );
  19. COMMIT;
  20. DBMS_OUTPUT.put_line( 'The total ' || emp_tab.COUNT || ' rows has been inserted to tb_emp' );
  21. END;

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

Oracle批量SQL之 BULK COLLECT 子句的更多相关文章

  1. ORACLE PL/SQL开发--bulk collect的用法 .

    刚刚在inthirties老大的博客里看到这篇文章,写的不错,正好自己最近在学习PL/SQL,转过来学习学习. ============================================ ...

  2. PL/SQL批处理语句(BULK COLLECT子句和FORALL语句)

    Oracle为PL/SQL中的SQL相关功能提供了FORALL语句和BULK COLLECT子句,显著的增强了SQL相关功能.这两个语句一起被称作PL/SQL的批处理语句.Oracle为什么要提供这两 ...

  3. Oracle学习笔记之五sp1,PL/SQL之BULK COLLECT

    Bulk Collect特性可以让我们在PL/SQL中能使用批查询,批查询在某些情况下能显著提高查询效率. BULK COLLECT 子句会批量检索结果,即一次性将结果集绑定到一个集合变量中,并从SQ ...

  4. Oracle数据库之FORALL与BULK COLLECT语句

    Oracle数据库之FORALL与BULK COLLECT语句 我们再来看一下PL/SQL块的执行过程:当PL/SQL运行时引擎处理一块代码时,它使用PL/SQL引擎来执行过程化的代码,而将SQL语句 ...

  5. bulk collect 在KingbaseES和Oracle的使用方法比较

    概述 BULK COLLECT 子句会批量检索结果,即一次性将结果集绑定到一个集合变量中,并从SQL引擎发送到PL/SQL引擎.通常可以在SELECT INTO.FETCH INTO以及RETURNI ...

  6. PL/SQL — BULK COLLECT用法

    BULK COLLECT 子句会批量检索结果,即一次性将结果集绑定到一个集合变量中,并从SQL引擎发送到PL/SQL引擎.通常可以在SELECT INTO.FETCH INTO以及RETURNING ...

  7. PL/SQL批处理语句(一)BULK COLLECT

    我们知道PL/SQL程序中运行SQL语句是存在开销的,因为SQL语句是要提交给SQL引擎处理,这种在PL/SQL引擎和SQL引擎之间的控制转移叫做上下文却换,每次却换时,都有额外的开销.然而,FORA ...

  8. PL/SQL 批量SQL

    批量SQL包括: FORALL语句 BULK COLLECT子句 FORALL语句 FORALL具有如下结构: FORALL loop_counter IN bounds_clause [SAVE E ...

  9. Oracle forall bulk collect批量数据更新

    对于数据量较大的插入操作可采用此种方法操作,注意: limit减少内存占用,如果数据量较大一次性全部加载到内存中,对PGA来说压力太大,可采用limit的方法一次加载一定数量的数据,建议值通常为100 ...

随机推荐

  1. 1080 Graduate Admission (30)(30 分)

    It is said that in 2013, there were about 100 graduate schools ready to proceed over 40,000 applicat ...

  2. 【Lintcode】135.Combination Sum

    题目: Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C  ...

  3. 详解使用python crontab设置linux定时任务

    熟悉linux的朋友应该知道在linux中可以使用crontab设置定时任务.可以通过命令crontab -e编写任务.当然也可以直接写配置文件设置任务. 但是有时候希望通过脚本自动设置,比如我们应用 ...

  4. WPF架构分析

    1.DisptcherObject提供了线程和并发模型,实现了消息系统. 2.DependencyObject提供了更改通知,实现了绑定,样式. 3.Visual是托管API和非托管API(milco ...

  5. 人工智能实践:TensorFlow 框架

    张量.计算图.会话 基本概念 基于Tensorflow的NN:用张量表示数据,用计算图搭建神经网络,用会话执行计算图,优化线上的权重(参数),得到模型. 张量(Tensor):张量就是多维数组(列表) ...

  6. @SpringBootApplication注解分析

    首先我们分析的就是入口类Application的启动注解@SpringBootApplication,进入源码: @Target(ElementType.TYPE) @Retention(Retent ...

  7. git repo

  8. CentOS快速搭建LAMP环境

    LAMP --  Linux Apache MySQL PHP 在CentOS安装的顺序,我一般是Apache -> MySQL -> PHP 第一步.安装并配置Apache 1.使用yu ...

  9. iOS ipa包重签名

    背景:公司做游戏SDK的,提供SDK给第三方后,他们打包过来我们需要分发在不同的渠道,这个时候需要修改SDK的配置文件,ipa文件修改后是需要手机越狱或者ipa重签名才能安装成功的,所以研究了一下重签 ...

  10. LayUI 子父窗体的交互

    ---恢复内容开始--- 收到的工作是将一个ERP的窗体程序改为网页实现,所以就肯定需要弹框来选择(如:物料编码.部门.业务员等等) 本文采取的前段框架是LayUI. layUI的官网API网址:ht ...