2012-07-27 79 views
6

我目前正在寫更新語句,以保持可查詢表不斷最新之間的Oracle SQL更新。該模式是兩個表之間的相同和內容並不重要:基於子查詢兩個表

STAGING 

ID 
NAME 
COUNT  

PRODUCTION 

ID 
NAME 
COUNT 

我的更新語句如下所示:

update PRODUCTION 
set name = (select stage.name from staging stage where stage.name=name and rownum <2), 
    count = (select stage.countfrom staging stage where stage.count=count and rownum <2); 

筆記的兩兩件事是:1)沒有WHERE子句我的更新結束(這可能是問題)和2)更新後的所有記錄具有相同的值。我的意思是以下幾點:

BEFORE UPDATE: 

1,"JOHN", 12; 
2,"STEVE",15; 
3,"BETTY",2; 

AFTER UPDATE 

    1,"JOHN", 12; 
    2,"JOHN",12; 
    3,"JOHN",12; 

我的問題是我怎麼解決這個問題,以便表正確反映分期爲正確的SQL更新「新」數據?

UPDATE

所以我臨時數據可能湊巧反映的是在PRODUCTION和討論的緣故,會:

STAGING DATA TO MERGE: 

    1,"JOHN", 12; 
    2,"STEVE",15; 
    3,"BETTY",2; 

更新第二

的查詢我想運行會是這樣:

update PRODUCTION 
set production.name = staging.name, 
    production.count = staging.count 

where production.name = staging.name; 

然而這會導致無效的問題上「staging.name」

+0

是否要在** PRODUCTION **表中保留** name **和** count **以及** STAGING **表正在更改? – hmmftg 2012-07-27 17:39:56

+0

爲什麼不使用觸發器插入新值而不是此更新?這個更新究竟做了什麼? – hmmftg 2012-07-27 17:42:22

+0

同意,在同步表格時,觸發器對於保持實時更新非常有用。只需要注意表格錯誤的變異,並確保將其作爲AFTER INSERT或UPDATE來執行。 – Hermit 2012-07-27 17:45:36

回答

26

有兩種方法可以做到你正在嘗試

一個是Multi-column Correlated Update

UPDATE PRODUCTION a 
SET (name, count) = (
    SELECT name, count 
    FROM STAGING b 
    WHERE a.ID = b.ID); 

DEMO

您可以使用merge

MERGE INTO PRODUCTION a 
USING (select id, name, count 
      from STAGING) b 
ON (a.id = b.id) 
WHEN MATCHED THEN 
UPDATE SET a.name = b.name, 
      a.count = b.count 

DEMO

+0

讓我試試多列相關。我不得不擺脫合併,因爲它很慢(超過1000萬條記錄) – Woot4Moo 2012-07-27 18:35:25

0

正如你已經注意到了,你沒有選擇你的更新語句,以便它更新您的整個表。如果你想更新特定的行(例如,ID匹配的地方),你可能想做一個協調的子查詢。

然而,由於您使用的是Oracle,它可能是更容易地創建一個物化視圖爲您查詢表,並讓Oracle的事務處理機制的細節。 MV的工作完全一樣的語義查詢表,是很容易成立,並允許您指定的刷新間隔。

1

沒有上演,這是一個在黑暗中拍攝的數據集的例子,但你有沒有嘗試過這樣的事情?

update PRODUCTION p, 
     staging s 
set p.name = s.name 
    p.count = s.count 
where p.id = s.id 

這會工作,假設id列在兩個表上匹配。

+0

那麼,如果我想匹配的唯一東西是我的子查詢中的where子句呢? IE設置等等,其中p.name = s.name和p.count = s.count? – Woot4Moo 2012-07-27 17:50:29

+0

如果你這樣做了,你會設置a = to b where a is = to b(即它什麼也不做)。 – Hermit 2012-07-27 18:09:59

+0

哎呀失敗的邏輯我的部分:) – Woot4Moo 2012-07-27 18:19:23

0

試試吧..
更新生產一個
SET(名稱,計數)=(
SELECT姓名,計數
FROM STAGING b
WHERE a.ID = b.ID)
WHERE EXISTS(SELECT 1
FROM STAGING b
WHERE a.ID = b.ID
);