在Oracle下使用Update有諸多限制,之前有研究過使用兩個Table進行Update的語法。但是在真正資料量極大及SQL條件極複雜的情況下,常常有做到當機而未完成。後來真正遇到了要使用Update更新約一年份的交易資料時,這種寫法完全是擾人的作法,Update SQL一下去,全公司幾乎不用工作了,系統資源都被我佔用掉了(笑)。
在學會Cursor語法後,覺得是方便又快速多了,加上有網友詢問使用兩個Table進行Update的語法,所以我就趕緊記錄下來,希望能幫助到有需要的人。
Cursor的基本語法相當簡單,只要從基本架構去加入條件即可:
declare
cursor c_rec is //建立一個指標
[Select SQL]; //將需要Update的資料先篩選出來
r_rec c_rec%rowtype; //在記憶體中建立一個臨時表來記錄Select出來的資料,使用指標來存取這個表
begin
for r_rec in c_rec loop //開始把臨時表中的資料讀出來
[Update SQL]; //對資料進行更新
end loop;
commit;
end;
我用使用兩個Table進行Update的語法來作比較,但先將語法再複雜化一點。
這一段語法的目的是找出在B表中B2欄位=2時的A表資料,並將A表中的A2欄位更新為B表中的B3內容,A3欄位更新為B表中的B4內容。
Update ( Select A.A2, A.A3
From A
Where A.A1 in (Select B.B1
From A,B
Where A.A1=B.B1
And B.B2='2'))
Set (A2,A3) = (Select B.B3, B.B4
From B
Where A.A1=B.B1
And B.B2='2')
使用這種寫法時,如果AB表各有十萬筆,則在Update語法中就會執行十萬筆的比對(如果一對一而已),在Set語法中還會再進行十萬筆資料比對一次,所以相當費時耗資源。如果你還要加上Max、Min、Sum等函數,其效能之差足以讓資料跑上一般Update的十倍以上(我沒實際算過,但依邏輯來講應該就是會非常差)。
因為效能極差,所以將它改成Cursor來作,這樣的寫法效能較佳,AB表第一次關聯後如果只剩下一千筆資料,那麼從單一表中找出一千筆資料來作事,絕對會比跑上十萬次或更多次來得好。
declare
cursor c_rec is
Select A.A1, B.B3, B.B4
From A,B
Where A.A1=B.B1
And B.B2='2';
r_rec c_rec%rowtype;
begin
for r_rec in c_rec loop //這邊的迴圈只會跑有寫進臨時表中的資料,也就是Select後的筆數,在這個地方不會再進行一次Select去咬住系統資源作篩選
update A
set A2 = r_rec.B3,
A3 = r_rec.B4
where 1 = 1
and A1 = r_rec.A1;
end loop;
commit;
end;
如果你要寫的Update語法相當複雜,那麼可以考慮使用Cursor來簡化。
總結步驟就是兩個:
(1)下Select找出需要被更新、條件值、更新值之類的資料
(2)將Update語法中的Where條件與(1)中的條件作關聯,然後更新過去。
以上是一點簡單的Cursor寫法,太艱深的我還沒學到(笑)。
2011/11/22
Oracle的Cursor寫法
訂閱:
張貼留言 (Atom)
沒有留言:
張貼留言