对于数据量较大的插入操作可采用此种方法操作,注意:

  1. limit减少内存占用,如果数据量较大一次性全部加载到内存中,对PGA来说压力太大,可采用limit的方法一次加载一定数量的数据,建议值通常为1000。使用limit时注意,循环的时候如果用while cursor_name%found loop,对于最后一次fetch的数据量不足设定值1000,%found条件就会不成立。示例使用v_oid_lst.count > 0作为判断条件。
  2. 在写plsql代码块,定义数值变量时,建议采用pls_integer类型,或者simple_integer类型,区别:

    oracle9i之前有binary_integer类型,和11g中引入的pls_integer数值范围相同:-2147483647~+2147483647,但pls_integer有更高的性能。两者性能均优于number类型。

    Oracle中也引入了simple_integer类型,不过不能包含null值,范围:-2147483648~2147483647,性能优于pls_integer。

  3. 使用ref cursor。
  4. 使用绑定变量。
  5. 自定义table类型。
  6. Bulk collect into加载到内存中,处理完业务逻辑后forall批量插入到数据表中。
  7. Forall可以使用returning bulk collect into,且可使用sql%rowcount返回其更新行数。
  8. type numbers is table of number index by binary_integer/pls_integer/simple_integer; 其作用是:

    加了"index by binary_integer "后,numbers类型的下标就是自增长,numbers类型在插入元素时,不需要初始化,不需要每次extend增加一个空间。

    而如果没有这句话"index by binary_integer",那就得要显示对初始化,且每插入一个元素到numbers类型的table中时,都需要先extend。

  9. 关于table、record、varray的详细使用,参考:http://blog.csdn.net/liangweiwei130/article/details/38223319

示例代码:

 SQL Code 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

  

declare
  type v_t_oid is table of ljz_all_objects.object_id%type;
  v_oid_lst v_t_oid;
  type v_t_cur_oid is ref cursor;
  v_cur_oid v_t_cur_oid;
  v_cnt     simple_integer := 1000;
begin
  open v_cur_oid for 'select object_id from ljz_all_objects where object_id>:1'
    using 1;
  fetch v_cur_oid bulk collect
    into v_oid_lst limit v_cnt;
  while v_oid_lst.count > 0 loop
    for i in 1 .. v_oid_lst.count loop
      --业务处理逻辑
      v_oid_lst(i) := v_oid_lst(i) + 1;
    end loop;
    forall i in v_oid_lst.first .. v_oid_lst.last
      insert into ljz_test (col) values (v_oid_lst(i));
    fetch v_cur_oid bulk collect
      into v_oid_lst limit 1000;
    commit;
  end loop;
  close v_cur_oid;
end;

定义record类型,多列插入:

 SQL Code 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

  

declare
  type v_t_r is record(
    object_id   ljz_all_objects.object_id%type,
    object_name ljz_all_objects.object_name%type);
  v_r v_t_r;
  type v_t_oid is table of v_t_r index by simple_integer;
  v_oid_lst  v_t_oid;
  v_oid_lst1 v_t_oid;
  type v_t_cur_oid is ref cursor;
  v_cur_oid v_t_cur_oid;
  v_cnt     simple_integer := 1000;
begin
  open v_cur_oid for 'select object_id,object_name from ljz_all_objects where object_id>:1'
    using 1;
  fetch v_cur_oid bulk collect
    into v_oid_lst limit v_cnt;
  while v_oid_lst.count > 0 loop
    for i in 1 .. v_oid_lst.count loop
      --业务处理逻辑
      v_oid_lst(i).object_id := v_oid_lst(i).object_id + 1;
    end loop;
    forall i in v_oid_lst.first .. v_oid_lst.last
      insert into ljz_test
        (num, col)
      values
        (v_oid_lst(i).object_id, v_oid_lst(i).object_name)
      returning num, col bulk collect into v_oid_lst1;
    dbms_output.put_line('v_oid_lst1.count=' || v_oid_lst1.count ||
                         ',隐式游标rowcount:' || sql%rowcount);
    fetch v_cur_oid bulk collect
      into v_oid_lst limit 1000;
    commit;
  end loop;
  close v_cur_oid;
end;

批量update、delete、insert,异常捕获:

 SQL Code 

,num数值型。
,这里有异常
条时出错,则前4条数据执行成功,第5条及其后面所有数据都不再执行。
,如下输出是1
        dbms_output.put_line('sql%bulk_exceptions.count:' ||
                             sql%bulk_exceptions.count);
    end;
    --批量更新
    forall i in v_objs.first .. v_objs.last
      update test1
         set num = v_objs(i).object_id
       where col = v_objs(i).object_name;
    --对于批量更新,除了sql%rowcount几个隐式游标属性外,另具有sql%bulk_rowcount属性,用来记录第N行更新影响行数。
    if sql%bulk_rowcount(2) > 0 then
      dbms_output.put_line('第二行更新影响行数:' || sql%bulk_rowcount(2));
    end if;
    begin
      --批量删除,使用save exceptions,和之前异常捕获区别:使用save exceptions异常后可继续执行直至结束。
      --新属性:sql%bulk_exceptions.count、sql%bulk_exceptions(i).error_index、sql%bulk_exceptions(i).error_code
      forall i in v_objs.first .. v_objs.last save exceptions
        delete from test1 where v_objs(i).object_id / 0 > 1;
    exception
      when others then
        for i in 1 .. sql%bulk_exceptions.count loop
          dbms_output.put_line('sql%bulk_exceptions(i).error_index:' || sql%bulk_exceptions(i)
                               .error_index);
          dbms_output.put_line('sqlerrm sql%bulk_exceptions(i).error_code:' ||
                               sqlerrm(sql%bulk_exceptions(i).error_code));
        end loop;
    end;
    fetch v_cur_obj bulk collect
      into v_objs limit v_lmt_cnt;
  end loop;
  close v_cur_obj;
end;

Oracle forall bulk collect批量数据更新的更多相关文章

  1. oracle 批处理 bulk collect 带来的性能优势

    create table -- drop table tmp_20190706_220000-- truncate table tmp_20190706_220000 create table tmp ...

  2. ORACLE fetch bulk collect into limit

    DECLARE TYPE rr IS REF CURSOR; TYPE r_emp IS RECORD( empno ), ename ), job ), mgr ), hiredate DATE, ...

  3. oracle中bulk collect into用法

    通过bulk collect减少loop处理的开销 采用bulk collect可以将查询结果一次性地加载到collections中. 而不是通过cursor一条一条地处理. 可以在select in ...

  4. Oracle批量SQL之 BULK COLLECT 子句

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

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

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

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

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

  7. PL/SQL — BULK COLLECT用法

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

  8. ORACLE批量绑定FORALL与BULK COLLECT

    FORALL与BULK COLLECT的使用方法: 1.使用FORALL比FOR效率高,因为前者只切换一次上下文,而后者将是在循环次数一样多个上下文间切换. 2.使用BLUK COLLECT一次取出一 ...

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

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

随机推荐

  1. ABP配套代码生成器(ABP Code Generator)帮助文档,实现快速开发

    ABP代码生成器介绍 针对abp这个框架做了一个代码生成器,功能强大.分为两大功能点,一个是数据层,一个是视图层. 数据服务层:通过它,可以实现表设计.领域层初始化.多语言.automapper自动注 ...

  2. 将一句话里的单词进行倒置,标点符号不倒换。比如将“I come from Shanghai.”倒换后变为“Shanghai. from come I”

    string str = "I come from Shanghai."; //根据空格切割 string[] strS = str.Split(' '); string temp ...

  3. CSS系列目录

    1.  在HTML中引入CSS的方法 2.  CSS选择器 2.1 CSS3新增选择器 3.  CSS的继承与层叠特性 4.  CSS中盒子模型 5.  CSS中盒子之间的关系 6.  CSS中盒子的 ...

  4. 4、DES和RSA简介

    DES是分组加密算法,速度快,使用单一密钥,加密解密都使用同一个密钥,一般用于大量数据加密,目前处于半淘汰状态. RSA算法是流式加密算法,速度慢,但是使用成对的密钥,加密解密使用不同的密钥,有利于保 ...

  5. MVC5 网站开发之五 展示层架构

    展示层由Ninesky.Web项目实现,负责网站内容的显示,项目包含Member和Control两个区域.   目录 奔跑吧,代码小哥! MVC5网站开发之一 总体概述 MVC5 网站开发之二 创建项 ...

  6. ASP.NET Core 阶段性总结

    自从年前用 ASP.NET 5 磕磕绊绊重写了一个项目后 (2015.12),就没怎么关注 ASP.NET 5 相关内容了,为啥?因为实际应用问题太多,而且不是正式版本,变化实在太快,可能你今天了解的 ...

  7. Notepad++ 实用技巧

    Notepad++是一款开源的文本编辑器,功能强大.很适合用于编辑.注释代码.它支持绝大部分主流的编程语言. 本文主要列举了本人在实际使用中遇到的一些技巧. 快捷键 自定义快捷键 首先,需要知道的是: ...

  8. 深入理解JavaScript——闭包

    跟很多新手一样我也是初入前端,对闭包的理解花费的时间和精力相当的多.效果也还行,今天我就来根据自己的理解细致的讲一讲闭包,由于是初入学习的时候不免有一些弯路和困惑,我想信这也是很多跟我一样的人会同样遇 ...

  9. 用github来展示你的前端页面吧

    前言 经常会有人问我如何才能将自己做的静态页面放到网上供他人欣赏,是不是需要自己有一个服务器,是不是还要搞个域名才能访问?对于以上问题我都会回答:用github来展示你的前端页面吧. 工欲善其事,必先 ...

  10. web 开发自动化grunt

    现在web开发自动化已很流行,如何进行压缩文件,如何进行测试js是否正确,如何进行 检测html文件是否规范等等都可以通过web自动化技术进行实现,只要打一个命令即可. 本文主要是通过grunt进行实 ...