FORALL与BULK COLLECT是实现批量SQL

2014年11月20日,星期四 更新

1. 示例1
declare
/*    type card_rec_type is record
    ( dn_no channel.dn_no%type,
        channel_id channel.channel_id%type);
    type nested_card_type is table of card_rec_type;
    card_tab nested_card_type; */
    cursor card_rec is
        select dn_no,channel_id from channel;
    type nested_card_type is table of card_rec%rowtype;-->基于游标的嵌套表类型
    card_tab nested_card_type;
begin
    select dn_no,channel_id
    bulk collect into card_tab
    from channel
    where lan_id=7;
    forall i in card_tab.first .. card_tab.last
        insert into (select dn_no,channel_id from tb_card)
        values card_tab(i);
    commit;
    dbms_output.put_line('The total '||card_tab.count||' has insert into tb_card');
end;
/
--如果我们在forall抛出异常的时候进行捕获,在Exception处理语句中进行commit的话,我们成功更新的记录是可以保存下来

示例2
declare
  cursor cur is select object_id,object_name from dba_objects a where a.OBJECT_TYPE='TABLE';
  l_count number :=0;
  l_commit number :=100;
  
  type t_target is table of cur%rowtype;
  l_target t_target;
  l_limit number default 10;
  
begin
  open cur;
  loop
    fetch cur bulk collect into l_target limit l_limit;
    exit when l_target.count=0;
         forall i in l_target.first .. l_target.last
         insert into tmp_lbx (id,name) values(l_target(i).object_id,l_target(i).object_name);
         
         l_count :=l_count + l_target.count;
         if l_count >= l_commit then
           commit;
           l_count :=0;
         end if;  
     end loop;
     commit;    
     close cur;
end;

2. 异常处理示例 Forall中Bulk_Exceptions捕获
declare
type id_list is table of t.object_id%type index by binary_integer;
id_info id_list;
i number;
ERRORS_NUM number;
begin
    select object_id
    bulk collect into id_info from t;
 
    forall i in id_info.first .. id_info.last save exceptions
        update t set subobject_name=object_type||timestamp
        where object_id=id_info(i);
    commit;
    exception
        when others then
            errors_num :=sql%bulk_exceptions.count;
            dbms_output.put_line('Total Exception is :'||to_char(errors_num));
 
            if errors_num > 10 then
                errors_num := 10;
            end if;
 
            for i in 1 .. errors_num loop
                dbms_output.put_line('Error #'||i||' is '||sql%bulk_exceptions(i).error_index||' ' ||sqlerrm(-sql%bulk_exceptions(i).error_code));
            end loop;
 
            rollback;
end;
/

--异常记录入库
--创建测试表
create table   tb_bulk_test(p_id number(10) primary key,p_name varchar2(50));
insert into tb_bulk_test (p_id,p_name)
select a.OBJECT_ID,a.OBJECT_NAME from dba_objects a where a.OBJECT_ID>500 and rownum<=1000;

--生成随机数表
create table tb_test  as
SELECT trunc(DBMS_RANDOM.value(10,10000)) id FROM DUAL connect by level <1001;
--创建异常记录表
create table log_error (err_ind varchar2(10),err_code varchar2(50), insert_date date default sysdate);

declare 
cursor c1 is select id from tb_test;
type c1_type is table of c1%rowtype;
c1_tab c1_type;
bulk_errors exception;
pragma exception_init(bulk_errors,-24381);

type type_errorindex is table of number index by binary_integer;
err_ind type_errorindex;
type type_errorcode is table of varchar2(50) index by binary_integer;
err_code type_errorcode;

begin
  open c1 ;
    fetch c1 bulk collect into c1_tab ;
    forall i in c1_tab.first .. c1_tab.last save exceptions
    insert into (select p_id from tb_bulk_test ) values c1_tab(i);
    commit;
    exception
      when bulk_errors then
        for j in 1 .. sql%bulk_exceptions.count() 
          loop
            err_ind(j) :=sql%bulk_exceptions(j).error_index;
            err_code(j) := -sql%bulk_exceptions(j).error_code;
            execute immediate 'insert into log_error(err_ind,err_code) values(:1,:2)'
            using err_ind(j),err_code(j);
            commit;
          end loop;   
end;
   
3. forall与rowcount
declare
type id_list is table of t.object_id%type index by binary_integer;
id_info id_list;
i number;
j number;
ERRORS_NUM number;
begin
    select object_id
    bulk collect into id_info from t;
 
    forall i in id_info.first .. id_info.last save exceptions
        update t set subobject_name=object_type||timestamp
        where object_id=id_info(i);
 
 
    for j in id_info.first .. id_info.last loop
        dbms_output.put_line('Iteration# '||j||' : '||sql%bulk_rowcount(j)||' rows.');
    end loop;
    commit;
end;
/





参考:





posted @ 2014-11-20 23:11  bowshy  阅读(256)  评论(0编辑  收藏  举报