利用游标更新数据

基本用法:
 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
  2  as
  3  select * from all_objects;
表已创建。

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

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

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

SQL> declare
  2      cursor sal_cursor is
  3          select object_name
  4              from t
  5                for update nowait;
  6  begin
  7      for i in sal_cursor loop
  8          update t
  9                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
  2      cursor sal_cursor is
  3          select object_name
  4              from t1
  5                for update nowait;
  6  begin
  7      for i in sal_cursor loop
  8          update t1
  9                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                                0        131,072        131,072
STAT..session pga memory                                0        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 过程已成功完成。

你可能感兴趣的:(利用游标更新数据)