ITPUB??ì3
12月微软Hyper-V虚拟化沙龙主题征集
ITPUB论坛 » Oracle开发 » 求一个分组循环存储过程的写法

标题: [PL/SQL] 求一个分组循环存储过程的写法
离线 Alex20080808



精华贴数 0
个人空间 0
技术积分 54 (26912)
社区积分 0 (1871041)
注册日期 2008-9-23
论坛徽章:0
      
      

发表于 2008-9-23 11:43 
求一个分组循环存储过程的写法

假定执行单独的insert语句,数据量太大,需要对数据进行分组循环,
50万条commit一次,是不是必须要用游标循环,不用游标可以不可以,
可以的话应该怎么设置变量,怎么写循环?
我是因为工作的需要刚接触ORACLE,应该是刚接触程序这块,以前学硬件方面的,
很恼火,谢谢大家,请帮帮忙哈。


只看该作者    顶部
在线/呼叫 dingjun123
djゆoracle


来自 china
精华贴数 3
个人空间 0
技术积分 1913 (912)
社区积分 15 (8980)
注册日期 2006-7-28
论坛徽章:2
2008北京奥运纪念徽章:铁人三项ITPUB新首页上线纪念徽章    
      

发表于 2008-9-23 11:50 
你应该先把表结构和insert数据源写出来才好解决!


__________________
软件体系架构要以数据库为中心,如oracle,可以充分利用数据库的特性,帮助解决复杂的问题。一个常用的规则是:
如果能用单条sql解决,ok
如果不能用单条sql解决,考虑使用PL/SQL
如果不能用PL/SQL解决,考虑使用java存储过程
如果不能用java解决,那么考虑使用c外部过程
如果c都解决不了,那么考虑一下放弃吧
只看该作者    顶部
在线/呼叫 dingjun123
djゆoracle


来自 china
精华贴数 3
个人空间 0
技术积分 1913 (912)
社区积分 15 (8980)
注册日期 2006-7-28
论坛徽章:2
2008北京奥运纪念徽章:铁人三项ITPUB新首页上线纪念徽章    
      

发表于 2008-9-23 12:08 
循环内部提交,如果效率很低,而且你是插入50万行再提交,有可能造成ora-01555错误。

可以考虑一下使用forall和bulk结合处理


__________________
软件体系架构要以数据库为中心,如oracle,可以充分利用数据库的特性,帮助解决复杂的问题。一个常用的规则是:
如果能用单条sql解决,ok
如果不能用单条sql解决,考虑使用PL/SQL
如果不能用PL/SQL解决,考虑使用java存储过程
如果不能用java解决,那么考虑使用c外部过程
如果c都解决不了,那么考虑一下放弃吧
只看该作者    顶部
离线 Alex20080808



精华贴数 0
个人空间 0
技术积分 54 (26912)
社区积分 0 (1871041)
注册日期 2008-9-23
论坛徽章:0
      
      

发表于 2008-9-23 12:18 


QUOTE:
原帖由 dingjun123 于 2008-9-23 12:08 发表
循环内部提交,如果效率很低,而且你是插入50万行再提交,有可能造成ora-01555错误。

可以考虑一下使用forall和bulk结合处理

谢谢,那我先去试试。


只看该作者    顶部
离线 Alex20080808



精华贴数 0
个人空间 0
技术积分 54 (26912)
社区积分 0 (1871041)
注册日期 2008-9-23
论坛徽章:0
      
      

发表于 2008-9-23 15:04 
存储过程的功能是插入输入参数日期的记录,因为数据量太大,源表数据大概1亿左右,满足当天日期条件的大概有600万左右。

源表E(ename,eno,erq),
目标表A(name,no,rq,r_date),其中name,rq是建立的索引。r_date是更新日期,定义的输入参数是r_date in varchar2
我定义了一个变量n_count 作为循环计数变量。

create or replace procedure p_A(r_date varchar2) is


      n_count number(12);
   BEGIN
      n_count := 0;
      LOOP
      n_count := n_count +1;
      
      --插入数据
      INSERT A (
               name
               ,no
               ,rq
               ,r_date
               )
      SELECT
              ename
              ,eno
              ,erq
              to_date(r_date,'yyyymmdd')
      FROM E WHERE erq = to_date(r_date,'yyyymmdd')
      
   IF n_count >500000 THEN
      COMMIT;  
      n_count := 0;
      
   END IF;
     
END LOOP;
      
END p_A;


我写下来的存储过程编译成功,但是测试数据的时候就报错,ORA-000001错,大概是触犯了主键索引重复。

[ 本帖最后由 Alex20080808 于 2008-9-23 17:49 编辑 ]


只看该作者    顶部
离线 bell6248
高级会员



来自 shanghai
精华贴数 0
个人空间 0
技术积分 3994 (369)
社区积分 45 (5252)
注册日期 2004-7-4
论坛徽章:16
ITPUB元老参与2007年甲骨文全球大会(中国上海)纪念会员2007贡献徽章授权会员ITPUB新首页上线纪念徽章 
      

发表于 2008-9-23 15:07 

__________________
Better information! Better results!
Oracle is the information company!!!
只看该作者    顶部
在线/呼叫 dingjun123
djゆoracle


来自 china
精华贴数 3
个人空间 0
技术积分 1913 (912)
社区积分 15 (8980)
注册日期 2006-7-28
论坛徽章:2
2008北京奥运纪念徽章:铁人三项ITPUB新首页上线纪念徽章    
      

发表于 2008-9-23 15:29 
你的逻辑有问题,循环一次全量更新了一次!


__________________
软件体系架构要以数据库为中心,如oracle,可以充分利用数据库的特性,帮助解决复杂的问题。一个常用的规则是:
如果能用单条sql解决,ok
如果不能用单条sql解决,考虑使用PL/SQL
如果不能用PL/SQL解决,考虑使用java存储过程
如果不能用java解决,那么考虑使用c外部过程
如果c都解决不了,那么考虑一下放弃吧
只看该作者    顶部
在线/呼叫 dingjun123
djゆoracle


来自 china
精华贴数 3
个人空间 0
技术积分 1913 (912)
社区积分 15 (8980)
注册日期 2006-7-28
论坛徽章:2
2008北京奥运纪念徽章:铁人三项ITPUB新首页上线纪念徽章    
      

发表于 2008-9-23 15:41 
给你一个例子,比较适合你现在的这个,大数据量,分批插入多次提交
你吧sour换成SELECT
              ename
              ,eno
              ,erq
              to_date(r_date,'yyyymmdd')
      FROM E WHERE erq = to_date(r_date,'yyyymmdd')
然后稍微改下就可以了
PHP code:


create 
or replace procedure cp_data5 as

  
type t_cur is REF cursor;

  
c_table t_cur;

  
type t_employee is table of employees%rowtype;

  
v_employees t_employee;

  
rows number := 50;--分批,每次插入50条

  v_sql varchar2
(300);

  
v_table varchar(50);

begin

  v_table 
:= 'employee_cp';

  
open c_table for

    
select from employees; --sour

  v_sql 
:= 'insert /*+ APPEND*/ into ' || v_table ||        

           
' (EMPLOYEE_ID,

FIRST_NAME,

LAST_NAME,

EMAIL,

PHONE_NUMBER,

HIRE_DATE,

JOB_ID,

SALARY,

COMMISSION_PCT,

MANAGER_ID,

DEPARTMENT_ID,

BIRTHDAY) values (:1, :2,:3,:4,:5,:6, :7, :8,:9,:10, :11,:12)'
;

  
loop

    fetch c_table bulk collect  

      into v_employees limit rows
; --分批  

    dbms_output
.put_line(v_employees.count);

    for 
i in 1 .. v_employees.count loop  

      execute immediate v_sql    

        using V_EMPLOYEES
(i).EMPLOYEE_IDV_EMPLOYEES(i).FIRST_NAMEV_EMPLOYEES(i).LAST_NAMEV_EMPLOYEES(i).EMAILV_EMPLOYEES(i).PHONE_NUMBERV_EMPLOYEES(i).HIRE_DATEV_EMPLOYEES(i).JOB_IDV_EMPLOYEES(i).SALARYV_EMPLOYEES(i).COMMISSION_PCTV_EMPLOYEES(i).MANAGER_IDV_EMPLOYEES(i).DEPARTMENT_IDV_EMPLOYEES(i).BIRTHDAY

    
end loop;

    
commit

    exit 
when c_table%notfound;

  
end loop;

  
close c_table;

end;

[ 本帖最后由 dingjun123 于 2008-9-23 15:45 编辑 ]


__________________
软件体系架构要以数据库为中心,如oracle,可以充分利用数据库的特性,帮助解决复杂的问题。一个常用的规则是:
如果能用单条sql解决,ok
如果不能用单条sql解决,考虑使用PL/SQL
如果不能用PL/SQL解决,考虑使用java存储过程
如果不能用java解决,那么考虑使用c外部过程
如果c都解决不了,那么考虑一下放弃吧
只看该作者    顶部
在线/呼叫 newkid
资深新手
老程序员


来自 银河系
精华贴数 2
个人空间 0
技术积分 2756 (579)
社区积分 0 (121048)
注册日期 2004-6-26
论坛徽章:5
生肖徽章2007版:马生肖徽章2007版:鸡2008北京奥运纪念徽章:垒球2008北京奥运纪念徽章:羽毛球  
      

发表于 2008-9-23 22:43 
INSERT .... SELECT 是最快的。


__________________
只看该作者    顶部
离线 Alex20080808



精华贴数 0
个人空间 0
技术积分 54 (26912)
社区积分 0 (1871041)
注册日期 2008-9-23
论坛徽章:0
      
      

发表于 2008-9-24 00:02 
但是分组循环提交应该是为了防止发生错误时回滚,那样会很花时间的。
好像是这样的


只看该作者    顶部
相关内容


CopyRight 1999-2006 itpub.net All Right Reserved.
北京皓辰广域网络信息技术有限公司. 版权所有
E-mail:Webmaster@itpub.net
京ICP证:010037号 联系我们 法律顾问