ORACLE批量更新方法
第一種方法 就是update tab a set a.name=(select b.name from b where a.id=b.id) where exists (select 1 from b where a.id=b.id) 但是我不知道為啥要加後面 exists
(sql%rowcount的資料量(不管你是否更新到)就是select count(*) from table_name的資料量啦,即全表更新)
第二種就是 merge into tab
using () on (條件)
when match then
do update
when no match then
do insert
第三種估計好多人不知道 update(select a.name,b.name from a,b where a.id=b.id) set a.name=b.name; 但是這種情況下要保證b.id要唯一 最好還能建立索引啥的
在做報表的時候,遇到這麼一個問題,由於資料量大,資料上傳時間問題,經常要處理更新幾天前的資料,這時需要涉及UPDATE或者INSERT兩個操作,這時推薦用MERGE INTO,但用這個時候需注意一個問題,我先來一個測試:
SQL> select * from ytrep.tab1;
COL_A COL_B COL_C
---------- ---------- ----------
1 A
2 B
3 C
4 D
5 E
6 F
7 G
8 H
8 rows selected
SQL> select * from ytrep.tab2;
COL_A COL_B COL_C COL_D
---------- ---------- ---------- ----------
1 A A1 1
1 A A1 2
2 B B1 1
3 C C1 1
4 D D1 1
5 E E1 2
5 E E2 1
6 F F1 1
6 F F1 2
9 G G1 1
10 H H1 1
11 rows selected
有以上兩表,其中需要根據ytrep.tab2表的col_a及col_b值來更新ytrep.tab1的col_c值,這時,我們來執行以下SQL:
Merge into ytrep.tab1 p
using (
select t.col_A, t.col_B, col_C
from ytrep.tab2 t
) tmp
on (p.col_A= tmp.col_A and p.col_B= tmp.col_B)
when not matched then
insert (col_A, col_B, col_C) values (tmp.col_a, tmp.col_B, tmp.col_C)
when matched then
update set p.col_c = tmp.col_c;
提示:
ORA-30926: 無法在源表中獲得一組穩定的行
ORA-30926: unable to get a stable set of rows in the source tables
好了,現在我們來分析為什麼會出現這種錯誤,在ON條件裡,我們可以看到p.col_A= tmp.col_A and p.col_B= tmp.col_B,
當tmp表返回記錄後,ytrep.tab1取第一條記錄 col_a = '1' and col_b = 'A' 與tmp表關聯時,發現tmp有兩條匹配的記錄,這時ORACLE就無法判斷到底UPDATE SET時應該取TMP表的哪條記錄的COL_C值是A1還是A2了,這時ORACLE就返回以上錯誤;
這時,我們就可以推斷,TMP結果集裡返回的在ON條件裡有涉及欄位的值必須是唯一的,否則肯定報以上ORA-30926錯誤;
這時,有人也許會問,那到底該怎麼寫呢?
可分為兩種情況:
1、一種是通過將TMP表的資料GROUP BY,取得MIN或MAX值;
Merge into ytrep.tab1 p
using (
select t.col_A, t.col_B, max(col_C) col_C --min(col_C) col_C
from ytrep.tab2 t
group by t.col_a, t.col_b
) tmp
on (p.col_A= tmp.col_A and p.col_B= tmp.col_B)
when not matched then
insert (col_A, col_B, col_C) values (tmp.col_a, tmp.col_B, tmp.col_C)
when matched then
update set p.col_c = tmp.col_c;
SQL> select * from ytrep.tab1;
COL_A COL_B COL_C
---------- ---------- ----------
1 A A1
2 B B1
3 C C1
4 D D1
5 E E2
6 F F1
7 G
8 H
10 H H1
9 G G1
10 rows selected
2、一種是分組後再根據某列值排序取第一行或最後一行值;
Merge into ytrep.tab1 p
using (
select distinct t.col_A, t.col_B, first_value(col_c) over (partition by t.col_a, t.col_b order by t.col_d asc) col_c
from ytrep.tab2 t
) tmp
on (p.col_A= tmp.col_A and p.col_B= tmp.col_B)
when not matched then
insert (col_A, col_B, col_C) values (tmp.col_a, tmp.col_B, tmp.col_C)
when matched then
update set p.col_c = tmp.col_c;
SQL> select * from ytrep.tab1;
COL_A COL_B COL_C
---------- ---------- ----------
1 A A1
2 B B1
3 C C1
4 D D1
5 E E2
6 F F1
7 G
8 H
10 H H1
9 G G1
10 rows selected
以上兩個SQL,大家可以通過改變order by排序方式對比一下結果。
以上只是本人學習測試結果,如有不同意見或或好的建議,可以留言。謝謝!