2016-03-21 26 views
0

我有這兩個表如何合併執行兩個不同的動作時,「不匹配」

TABLE1 
nrb score note source 
nrb1 500 abc e1 
nrb2 500 def e1 

TABLE2 
nrb score note source 
nrb1 500 gls e1 
nrb3 500 dls e1 

有三種情況中,我想執行不同的操作。我需要修改表1與新值:

  1. WHEN MATCHED(由NRB)(f.ex.「NRB1」)我想從table1保留值這個nrb,所以basicly:什麼也不做這個紀錄

  2. WHEN NOT MATCHED#1:存在table2nrb但不是在table1(例如,'nrb3')我要爲這個nrbtable2值插入到table1

  3. WHEN NOT MATCHED#2:如果在table1nrb但不是在table2(如'nrb2')我想在table1改變score 500至

那麼到底它應該是這樣的:

TABLE1 
nrb score note source 
nrb1 500 abc e1 [stays the same] 
nrb2  5 def e1 [score changed] 
nrb3 500 dls e1 [new record from table2] 

我需要爲此任務使用Oracle的merge語句,但我不知道如何執行兩個不同的操作。

回答

3

您需要使用兩個不同的SQL做兩個獨立的任務。由於MERGE不支持UPDATE子句WHEN NOT MATCHED條件。

  • MERGE INSERT
  • UPDATE WHERE NOT EXISTS

設置

SQL> CREATE TABLE t1(
    2 nrb VARCHAR2(10), score NUMBER, note VARCHAR2(10), SOURCE VARCHAR2(10) 
    3 ); 

Table created. 

SQL> INSERT INTO t1 VALUES('nrb1', 500, 'abc', 'e1'); 

1 row created. 

SQL> INSERT INTO t1 VALUES('nrb2', 500, 'def', 'e1'); 

1 row created. 

SQL> COMMIT; 

Commit complete. 

SQL> CREATE TABLE t2(
    2 nrb VARCHAR2(10), score NUMBER, note VARCHAR2(10), SOURCE VARCHAR2(10) 
    3 ); 

Table created. 

SQL> INSERT INTO t2 VALUES('nrb1', 500, 'gls', 'e1'); 

1 row created. 

SQL> INSERT INTO t2 VALUES('nrb3', 500, 'dls', 'e1'); 

1 row created. 

SQL> COMMIT; 

Commit complete. 

MERGE INSERT:要插入不匹配的行

SQL> MERGE INTO t1 
    2 USING t2 
    3 ON (t1.nrb = t2.nrb) 
    4 WHEN NOT MATCHED THEN 
    5 INSERT 
    6  (
    7  nrb, 
    8  score, 
    9  note, 
10  SOURCE 
11  ) 
12  VALUES 
13  (
14  t2.nrb, 
15  t2.score, 
16  t2.note, 
17  t2.SOURCE 
18  ); 

1 row merged. 

SQL> COMMIT; 

Commit complete. 

SQL> SELECT * FROM t1; 

NRB    SCORE NOTE  SOURCE 
---------- ---------- ---------- ---------- 
nrb1    500 abc  e1 
nrb2    500 def  e1 
nrb3    500 dls  e1 

UPDATE聲明:更新自定義值不匹配的行

SQL> UPDATE t1 
    2 SET score = 5 
    3 WHERE NOT EXISTS (SELECT NULL 
    4      FROM t2 
    5      WHERE t1.nrb = t2.nrb); 

1 row updated. 

SQL>     COMMIT; 

Commit complete. 

SQL> SELECT * FROM t1; 

NRB    SCORE NOTE  SOURCE 
---------- ---------- ---------- ---------- 
nrb1    500 abc  e1 
nrb2    5 def  e1 
nrb3    500 dls  e1 

注意代替MERGE只有INSERT,你可以簡單地寫一個INSERT聲明。雖然從病房的10g開始,MATCHED和NOT MATCHED子句是可選的,因此您可以使用單個INSERT或單個UPDATE語句。

+0

值得注意的是,這將設置所有不匹配的值爲5.根據您的數據集和非500分數的規則(例如,如果分數是502?6000?等等),那麼您將需要添加這也適用於where子句,如果需要的話。 –

+0

完美無缺,非常感謝。考慮到你的更新聲明有一個問題,爲什麼你的「哪裏不存在」比簡單更「優化」?像這樣: 更新標籤1 設置分數= 5 其中nrb不在(從標籤2中選擇nrb) ; –

+0

https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:953229842074這是一個比以前鏈接的回覆更好的回覆。 –

3

你不能在一次合併中做到這一點。 when not matched子句可以只有插入,不會更新,如the syntax diagram所示。

enter image description here

同樣的when matched子句更新,不能插入。你不能在它們之間混合搭配。

您將不得不有一個單獨的更新聲明。您可以合併要做的第一部分:

merge into table1 t1 
using (select * from table2) t2 
on (t2.nrb = t1.nrb) 
when not matched then insert (nrb, score, note, source) 
    values (t2.nrb, t2.score, t2.note, t2.source); 

或做等價插入:

insert into table1 (nrb, score, note, source) 
select t2.nrb, t2.score, t2.note, t2.source 
from table2 t2 
where not exists (
    select null 
    from table1 t1 
    where t1.nrb = t2.nrb 
); 

select * from table1; 

NRB  SCORE NOT SO 
---- ---------- --- -- 
nrb1  500 abc e1 
nrb2  500 def e1 
nrb3  500 dls e1 

然後那些無論你做,更新不存在匹配:

update table1 t1 
set score = score/100 -- or fixed value 5; unclear which you need 
where not exists (
    select null 
    from table2 t2 
    where t2.nrb = t1.nrb 
); 

select * from table1; 

NRB  SCORE NOT SO 
---- ---------- --- -- 
nrb1  500 abc e1 
nrb2   5 def e1 
nrb3  500 dls e1 

如果你真的想讓你可以通過合併做到這一點,但它使using子句更復雜 - 的子集table1已在table2沒有matcing紀錄 - 所以我看不出有任何的好處:

merge into table1 t1 
using (
    select * from table1 t1 
    where not exists (
    select null from table2 t2 where t2.nrb = t1.nrb)) t2 
on (t2.nrb = t1.nrb) 
when matched then update set t1.score = score/100; 
相關問題