1. 程式人生 > >ORACLE批量更新方法

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要唯一 最好還能建立索引啥的

439人閱讀 評論(0)收藏 舉報

在做報表的時候,遇到這麼一個問題,由於資料量大,資料上傳時間問題,經常要處理更新幾天前的資料,這時需要涉及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排序方式對比一下結果。

以上只是本人學習測試結果,如有不同意見或或好的建議,可以留言。謝謝!