面对开源的世界...
如果你追求阳光,就躲不开身后的身影。
posts - 115,comments - 87,trackbacks - 0


前提:
【1】存在susr_basic和susr_info数据表,他们之间是1对N的关系,其中susr_info的customerindex鍵和susr_basic中的外键customerindex关联,susr_basic和susr_info表中的主键分别是userindex和customerindex,其生成方式是调用函数sp_getmaxvalue_func生成唯一序列值。

【2】已经利用sqlload工具将外部的用户号码文件导入到了v3_sub_1表中。


目的:
通过调用该存储过程将v3_sub_1表中的不带86开头的用户号码insert到susr_basic表中生成对应的用户记录,同时要生成对应相同数量的susr_info客户记录,带86开头的号码以及sql异常需要记录log。(期间要利用自定义的v3_sub_2和v3_sub_4做数据缓冲区)


中间表sql脚本:

-- Create table
create table V3_SUB_1
(
  USERCODE 
VARCHAR2(40not null --用户号码
)
/

 

-- Create table
create table V3_SUB_2
(
  USERCODE      
VARCHAR2(40),--用户号码
  CUSTOMERINDEX NUMBER --和v3_sub_4以及susr_info中的customerindex对应
)
/

-- Create/Recreate indexes 
create unique index CUSTOMERINDEX_V2 on V3_SUB_2 (CUSTOMERINDEX) --在customerindex上建建立索引
  /

 

-- Create table
create table V3_SUB_4
(
  USERINDEX     
NUMBER,--调用sp_getmaxvalue_func函数生成唯一值
  USERCODE      VARCHAR2(100),--用户号码
  CUSTOMERINDEX NUMBER --和v3_sub_2以及susr_info中的customerindex对应
)
    /
-- Create/Recreate indexes 
create unique index CUSTOMERINDEX_V4 on V3_SUB_4 (CUSTOMERINDEX)--在customerindex上建立索引
   /


-- Create table
create table V3_SUB_1_LOG
(
  TABLENAME  
VARCHAR2(100), --表名称
  MESSAGE    VARCHAR2(1000),--异常信息
  CREATETIME DATE,--异常发生时间
  USERCODE   VARCHAR2(100)--异常的号码
)
    /


程序思路:

【1】先利用sql将v3_sub_1表中的不以86开头以及是新号码的用户号码insert到v3_sub_2,同时生成customerindex值,带86以及已经存在的号码插到v3_sub_1_log表。

【2】将第1步生成的customerindex作为susr_info的主键insert到susr_info中,记录数和v3_sub_2一致。

【3】将第2步中生成的customerindex字段的值insert到v3_sub_4中,记录数和v3_sub_2一致。

【4】将v3_sub_2表中生成的usercode字段值insert到v3_sub_4用户表,利用v3_sub_2和v3_sub_4的customerindex关联来进行批量update表v3_sub_4中的usercode字段。

【5】将第4步中v3_sub_4表中数据copy一份到zxdbm_ismp.susr_basic表中。

【6】将上面5个步骤做为一个事物进行处理,整个流程就执行完毕。


 下面是存储过程的实现:

CREATE OR REPLACE PROCEDURE V3_SUB_FETCH_111
-- 完成功能:将用户文件中字段存储到temp表,再将temp表数据转到用户表
(
   v_retvalue           out 
varchar2 
)
AS
  v_message 
varchar2(100);
 
begin
    
begin
       
--先将v3_sub_1表中的不带86以及是新号码的insert到v3_sub_2,同时生customerindex
       insert into v3_sub_2(usercode,customerindex)
       
select t1.usercode,sp_getmaxvalue_func('susr_info',1from v3_sub_1 t1 
       
where not exists (select t2.usercode from susr_basic t2 
       
where t1.usercode = t2.usercode ) and substr(t1.usercode,1,2<> '86'
             
       
--将带86以及已经存在的号码插到log表
       --distinct过滤掉重复的86号码记录,'susr_basic','fail',sysdate做特定值insert到v3_sun_1_log表
       insert into v3_sub_1_log
       
select distinct 'susr_basic','fail',sysdate,t1.usercode from v3_sub_1 t1,susr_basic t2             

       
where t1.usercode = t2.usercode or substr(t1.usercode,1,2= '86';        
       
       
--添加客户表信息,插入的记录数和v3_sub_2用户表中号码记录数一致
       insert into susr_info(customerindex,customerid,userpwd,provid)
       
select customerindex,customerindex,'111111','074'from v3_sub_2;
       
       
--插入v3_sub_4的记录数和v3_sub_2用户表中号码记录数一致
       insert into v3_sub_4(customerindex) select customerindex from v3_sub_2;
       
       
--将v3_sub_2表中余下usercode字段值insert到v3_sub_4用户表,批量update
       update v3_sub_4 v4 set 
       (v4.userindex,v4.usercode) 
=
       (
select sp_getmaxvalue_func('susr_basic',1),v2.usercode
       
from v3_sub_2 v2 where v2.customerindex = v4.customerindex);
       
       
--将v3_sub_4表中数据copy一份到susr_basic表中
       insert into susr_basic(userindex,usercode,customerindex)
       
select userindex,usercode,customerindex from v3_sub_4;
                 
       
commit;            
    exception 
when others then --执行sql异常情况
       rollback;
       v_message :
= sqlcode ||':'|| sqlerrm;--记录异常日志
       insert into v3_sub_1_log values('sql',v_message,sysdate,'commit sqls fail'); 
       
commit;    
    
end;

    
execute immediate 'truncate table v3_sub_1';
    
execute immediate 'truncate table v3_sub_2';
    
execute immediate 'truncate table v3_sub_4';

    v_retvalue :
='the end of importing userinfo';
end V3_SUB_FETCH_111;

 
建议:以上过程的insert into susr_basic(userindex,usercode,customerindex) select userindex,usercode,customerindex from v3_sub_4;语句在执行的时候可以先将susr_basic表中索引drop掉,执行完该语句后再创建上该表的索引,可以用动态sql实现,这样效率会进一步得到提升,但做与否要看具体的环境而定。


测试结果:110w的用户号码在PC机上成功导入完毕所花时间约为32min

PC机配置:OS Windows XP  CPU AMD 3800+(双核)  内存1G


posted on 2008-02-03 20:10 cheng 阅读(1443) 评论(1)  编辑  收藏 所属分类: Oracle

FeedBack:
# re: 批量inset和update的存储过程实现
2008-02-17 12:34 | 91cn88
不错呀,好文章  回复  更多评论
  

标题  
姓名  
主页
验证码 *  
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-05-24 14:15 编辑过