FORALL(INDICES AND VALUES)

Oracle9i引入的批量绑定能显著提升数据处理速度,主要通过bulk collect和forall语句实现。本文详细介绍了forall在insert、update、delete操作中的用法,包括indices of和values of子句的应用,以及如何处理批量操作中的异常情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

批量绑定是oracle9i新增加特性,是指执行单次SQL操作能传递所有集合元素的数据,通过批量绑定可以极大的加快数据处理速度,提高应用程序的性能,批量绑定是使用bulk collect子句和forall语法完成,其他bulk  collect子句用于取得批量数据,该子句只能用于select语句、fetch语句和DML返回子句,而forall语句只适用于批发批量的DML操作。
forall语句
当要在PL/SQL应用程序中执行批量insert、update、delete操作时,可以使用forall语句,在oracle9i之前,当使用forall语句时,必须具有连续的元素,而从oracle9i开始,通过使用新增的indices of子句和values of子句,可以使用不连续的集合元素,注意for语句是循环语句,而forall可不是循环语句,从oracle10g开始,forall语句有是三种执行方法,如下所示;
1、语法一:
   forall  index  in lower_bound..upper_bound
       sql_statement;
如上所示:index是隐含定义的整数变量(将作为集合元素下标被引用);lower_bound和upper_bound分别是集合元素的上、下界。
2、语法二:
   forall index in indies of collection
     [between lower_bound and upper_bound]
如上所示:indices of子句用于指定只取得对应中的collection集合元素下标的index值。

   indices of子句是oracle10g新增加的特征,该子句用于跳转null集合元素
3、语法三:
forall index in values of index_collection
    sql_statement;
如上所示:其中values of子句用于指定index值从集合变量index_collection中取得,注意Oracle9i只能使用第一种方法,以下通过示例
说明:
(1)、在insert语句上使用批量绑定
   当使用批量绑定为数据库表插入数据时,首先需要给集合元素赋值,然后使用forall语句执行批量绑定插入操作,示例如下: 

Oracle代码
declare  
type id_table_type is  table of number(6)  
index by binary_integer;   
type name_table_type is  table of varchar2(10)  
index by binary_integer;  
id_table id_table_type;  
name_table name_table_type;  
begin  
for i in 1..10 loop  
id_table(i):=i;  
name_table(i):='name'||to_char(i);  
end loop;  
forall i in 1..id_table.count  
insert into demo values(id_table(i),name_table(i));  
end; 

(2)、在update语句上使用批量绑定
   当使用批量绑定为更新数据时,首先需要给集合元素赋值,然后使用forall语句执行批量绑定修改操作,示例如下:

Oracle代码
declare  
 type id_table_type is table of number(6) index by binary_integer;  
 type name_table_type is table of varchar2(10) index by binary_integer;  
 id_table id_table_type;  
 name_table name_table_type;  
begin  
for i in 1..10 loop  
id_table(i):=i;  
name_table(i):='yanglin'|| to_char(i);  
end loop;  
forall i in 1..id_table.count  
update demo set name=name_table(i) where id=id_table(i);  
end; 

(3)、在delete语句上使用批量绑定
   当使用批量绑定删除数据时,首先需要给集合元素赋值,然后使用forall语句执行批量绑定删除操作,示例如下:

Oracle代码
declare  
 type id_table_type is table of number(6) index by binary_integer;  
 id_table id_table_type;  
begin  
for i in 1..10 loop  
id_table(i):=i;  
end loop;  
forall i in 1..id_table.count  
delete from  demo where id=id_table(i);  
end; 

(4)、在forall语句上使用部分集合元素
   当使用forall语句进行批量操作时,即可以使用集合的所有元素,也可以使用集合的部分元素,示例如下:

Oracle代码
declare  
 type id_table_type is table of number(6) index by binary_integer;  
 id_table id_table_type;  
begin  
for i in 11..20 loop  
id_table(i):=i;  
end loop;  
forall i in 15..20 
delete from  demo where id=id_table(i);  
end; 

(5)、在forall语句上使用indices of子句
   indices of子句是oracle10g新增加的特征,该子句用于跳转null集合元素,示例如下:

Oracle代码
declare  
 type id_table_type is table of number(6);  
 id_table id_table_type;  
begin  
id_table:=id_table_type(11,null,12,null,13,null);  
forall i in indices of id_table  
delete from  demo where id=id_table(i);  

(6)、在forall语句上使用values of  index_collection子句 

index_collection下标数组

DECLARE
  TYPE id_table_type IS TABLE OF pls_integer;
  id_table id_table_type;
  TYPE index_table_type IS TABLE OF pls_integer;
  v_index_table index_table_type;
BEGIN
  v_index_table := index_table_type(1, 3, 5);
  id_table      := id_table_type(11, NULL, 12, NULL, 13, NULL);
 
 FORALL i IN VALUES OF v_index_table
   INSERT INTO test1 VALUES( id_table(i));
  --test1 :11,12,13 只插入了1,3,5元素的值
END;

(7)、save exceptions 来处理批量绑定过程中的异常情况

    create table t2(id int not null);

       -- Created on 2010/7/12 by DUQIANG
declare
  -- Local variables here
  type numlist is table of number index by pls_integer;
  n numlist;
begin
 
  for i in 1..3 loop
  n(i) :=i;
  end loop;-- Test statements here
 
  n(3) :=null;
 
  forall i in 1..3 save exceptions insert into t2 values(n(i));
exception
 when others then
 dbms_output.put_line('there are '||sql%bulk_exceptions.count||' errors');
 for i in 1..sql%bulk_exceptions.count loop
 dbms_output.put_line(sql%bulk_exceptions(i).error_index);
 dbms_output.put_line(sql%bulk_exceptions(i).error_code);
 dbms_output.put_line('message:');
 dbms_output.put_line(sqlerrm(sql%bulk_exceptions(i).error_code));
 end loop;
end;

(8)、为避免集体使用forall 批量收集带来的内存异常增大,可以使用limit来平衡 

 但有一点需要注意,当游标不足50行时,

 loop

       fetch cursor bulk collect into resultset limit 50;

exit when cursor%notfound;

processing;

end loop;

此时你永远不能processing,当读到21行时,%notfound被触发。

应该修改为:

loop

       fetch cursor bulk collect into resultset limit 50;

processing;

exit when cursor%notfound;

end loop;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值