Posted on 2010-05-10 23:04
Prayer 閱讀(405)
評論(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
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