Prayer

在一般中寻求卓越
posts - 1256, comments - 190, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

利用游标更新数据

Posted on 2010-05-10 23:04 Prayer 阅读(388) 评论(0)  编辑 收藏 引用 所属分类: DB2
基本用法:
 cursor c1 is

     select *

       from tablename

      where name is null

        for update [of column]

 ……

 for r1 in c1 loop

     update tablename

        set column = ……   --已限制了条件了,更新只是当前记录集  

      where current of c1;
end loop;

where current of 子句只能在定义游标的时候使用了for update语句才可以使用。  
上面的语句中r1 是c1中的一行数据,更新的时候应该用current of c1,因为c1只是一个隐式游标,它本身不是通过for update定义的,只是代表了循环中的当前记录。这样,你的update语句或者delete语句的作用范围就只在你循环的当前行的范围中了。  
   
要注意的是,用for update定义的游标会让数据库对涉及的行加锁,别的会话如果要访问该游标中的行便会进入等待状态。你也可以明确指明要加锁的列,用for update of "列名"  就可以了。 

如果select for update选中的行已经被别的会话加锁的话,会话就需要等待解锁,如果别的会话一直不解锁,那么你的select就会一直等待下去,如果你不想等,只需在for update后面加上nowait就可以解决这个问题了,这样你的选择会立即返回。

针对where current of的使用和我们日常的更新方法,进行了一个简单的测试。
编写了两个简单的过程,比较使用where current of和不使用时,性能的差异。
SQL> create table t
  as
  select * from all_objects;
表已创建。

SQL> create table t1
  as
  select * from t;
表已创建。

SQL> select count(*) from t;
  COUNT(*)
----------
     37003

SQL> exec runstats.rs_start;
PL/SQL 过程已成功完成。

SQL> declare
    cursor sal_cursor is
      select object_name
        from t
         for update nowait;
  begin
    for i in sal_cursor loop
      update t
         set data_object_id = data_object_id  + 1
 10       where current of sal_cursor;
 11    end loop;
 12  end;
 13  /
PL/SQL 过程已成功完成。

SQL> exec runstats.rs_middle;
PL/SQL 过程已成功完成。

SQL> declare
    cursor sal_cursor is
      select object_name
        from t1
         for update nowait;
  begin
    for i in sal_cursor loop
      update t1
         set data_object_id = data_object_id  + 1
 10       where object_name = i.object_name;
 11    end loop;
 12    commit;
 13  end;
 14  /
PL/SQL 过程已成功完成。

SQL> exec runstats.rs_stop(1000000);
Run1 ran in 3767 hsecs
Run2 ran in 126597 hsecs
run 1 ran in 2.98% of the time
Name                                  Run1        Run2        Diff
STAT..no work - consistent rea      37,268   9,212,891   9,175,623
STAT..table scan blocks gotten      37,247   9,212,999   9,175,752
STAT..buffer is not pinned cou      37,282   9,213,043   9,175,761
STAT..consistent gets               37,311   9,400,510   9,363,199
STAT..session logical reads        119,901   9,521,124   9,401,223
STAT..redo size                 15,563,548  25,830,156  10,266,608
LATCH.cache buffers chains         502,564  19,504,830  19,002,266
STAT..table scan rows gotten        73,998########################
Run1 latches total versus runs -- difference and pct
Run1        Run2        Diff       Pct
782,133  20,678,374  19,896,241      3.78%
PL/SQL 过程已成功完成。

对t1表建立索引的差异:
SQL> analyze index idx_object_name compute statistics;
索引已分析

SQL> exec runstats.rs_stop(100000);
Run1 ran in 2989 hsecs
Run2 ran in 5250 hsecs
run 1 ran in 56.93% of the time
Name                                  Run1        Run2        Diff
STAT..session logical reads        112,542     231,954     119,412
STAT..session logical reads        112,542     232,502     119,960
STAT..session logical reads        112,542     233,080     120,538
STAT..session pga memory                    131,072     131,072
STAT..session pga memory                    131,072     131,072
LATCH.cache buffers chains         488,072     828,849     340,777
LATCH.cache buffers chains         488,072     832,711     344,639
LATCH.cache buffers chains         488,072     835,333     347,261
STAT..redo size                 15,561,972  25,909,144  10,347,172
STAT..redo size                 15,561,972  25,970,072  10,408,100
STAT..redo size                 15,561,972  26,030,812  10,468,840
Run1 latches total versus runs -- difference and pct
Run1        Run2        Diff       Pct
2,293,947   3,511,140   1,217,193     65.33%
PL/SQL 过程已成功完成。


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理