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

  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. Jmeter正则表达式

    Jmeter正则表达式 文章转自:http://www.cnblogs.com/jamesping/articles/2252675.html 正则表达式可以帮助我们更好的描述复杂的文本格式.一旦你描 ...

  2. Liunx下配置DNS服务

    当Ping 主机名时可以映射出该主机的IP地址,反之亦然.配置并指定DNS服务器可以快速部署集群,不需要每台主机都去修改HOSTS文件即可实现IP与主机名的相互解析.而在Linux下的DNS是用bin ...

  3. 1. 使用Filter 作为控制器

    最近整理一下学习笔记,并且准备放到自己的博客上.也顺便把Struts2 复习一遍 1. MVC 设计模式概览 实现 MVC(Model.View.Controller) 模式的应用程序由 3 大部分构 ...

  4. 读书笔记--SQL必知必会06--用通配符进行过滤

    6.1 LIKE操作符 通配符(wildcard),用来匹配某些值的的特殊字符. 在搜索子句中必须通过LIKE操作符使用通配符. 通配符搜索只能用于文本字段(字符串),非文本数据类型字段不能使用通配符 ...

  5. J2EE 邮件发送那些事儿

    距离自己写的关于java邮件发送的第一篇博客已经有很长一段时间了,现在回过头看看.虽然代码质量方面有待提高,整体结构也不怎样,但是基本思路和过程还是比较纯的.现在有空写写J2EE中邮件发送的开发,实际 ...

  6. 微信开发之Ngrok环境准备

    一.为什么要使用ngrok? 各位肯定都知道,做微信开发,我们的开发服务器需要和微信服务器做交互,SO,我们需要准备一台放置在公网的服务器,能够使得我们的服务器可以正常访问微信服务器,并且微信服务器也 ...

  7. 没有神话,聊聊decimal的“障眼法”

    0x00 前言 在上一篇文章<妥协与取舍,解构C#中的小数运算>的留言区域有很多朋友都不约而同的说道了C#中的decimal类型.事实上之前的那篇文章的立意主要在于聊聊使用二进制的计算机是 ...

  8. .NET 版本区别,以及与 Windows 的关系

    老是记不住各 Windows 版本中的 .NET 版本号,下面汇总一下: .NET Framework各版本汇总以及之间的关系 Mailbag: What version of the .NET Fr ...

  9. 使用C#,轻松发邮件之QQ邮箱

    参考来源 http://www.cnblogs.com/youring2/archive/2008/11/29/1343911.html

  10. 文字处理控件TX Text Control的使用

    这几天一直在研究TX Text Control的使用,由于这方面的资料相对比较少,主要靠下载版本的案例代码进行研究,以及官方的一些博客案例进行学习,使用总结了一些心得,特将其总结出来,供大家分享学习. ...