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

  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. Atitit 常用二维码对比(QR、PDF417、DM、汉信码 Aztec code maxicode

    Atitit 常用二维码对比(QR.PDF417.DM.汉信码 Aztec code maxicode DM码则更"小",可在仅仅25mm²的面积上编码30个数字.但也就是因为太小 ...

  2. node.js学习总结(一)

    1.1.1 安装 Node.js 有三种方式安装 Node.js:一是通过安装包安装,二是通过源码编译安装,三是在 Linux 下可以通过 yum|apt-get 安装,在 Mac 下可以通过 Hom ...

  3. Chrome调试手机页面

    新开发的网页需要在手机或是模拟机上运行测试,如果手头事件比加紧,那么可以借助 Chrome提供的手机网页预览程序进行简单调试.查看 制作的网页是否能够适合各种手机型号使用. 下面所以下如何使用Chro ...

  4. CSS系列:CSS常用样式

    1. 通用样式 Base.css * { margin:; padding:; } body { width: 1000px; margin: 0 auto; font-size: 12px; fon ...

  5. Python下载网页的几种方法

    get和post方式总结 get方式:以URL字串本身传递数据参数,在服务器端可以从'QUERY_STRING'这个变量中直接读取,效率较高,但缺乏安全性,也无法来处理复杂的数据(只能是字符串,比如在 ...

  6. 前端学PHP之PDO基础操作

    × 目录 [1]创建PDO [2]使用PDO [3]事务处理 前面的话 PDO(php data object)扩展类库为php访问数据库定义了轻量级的.一致性的接口,它提供了一个数据库访问抽象层,这 ...

  7. Task三个列子的分享

    这次要分享的是C#Task任务的几个列子,感觉最实用的是封装的分页任务执行方法,这个方法步奏也是目前在我工作中执行多任务常用的,不知道各位也有这用的情况,那么开始吧. 1.顺序任务执行 //顺序任务执 ...

  8. Oracle从文件系统迁移到ASM存储

    环境:RHEL 6.4 + Oracle 11.2.0.4 需求:数据库存储由文件系统迁移到ASM 数据库存储迁移到ASM磁盘组 1.1 编辑参数文件指定新的控制文件路径 1.2 启动数据库到nomo ...

  9. Python爬虫小白入门(二)requests库

    一.前言 为什么要先说Requests库呢,因为这是个功能很强大的网络请求库,可以实现跟浏览器一样发送各种HTTP请求来获取网站的数据.网络上的模块.库.包指的都是同一种东西,所以后文中可能会在不同地 ...

  10. .NET平台上插拔姿势的AOP

    AOP概述 AOP技术的诞生并不算晚,早在1990年开始,来自Xerox Palo Alto Research Lab(即PARC)的研究人员就对面向对象思想的局限性进行了分析.他们研究出了一种新的编 ...