2013-11-03 82 views
3

我正在閱讀有關MERGE的msdn主題。 http://msdn.microsoft.com/en-us/library/bb510625.aspx說明以簡單字合併SQL語句?

但是這對我來說很困惑。比方說,我有一個表,

DECLARE @T Table 
(
    ID INt, 
    Name VARCHAR(10) 
) 

,我有,

MERGE INTO @T T1 
USING (SELECT 4 AS ID) T2 ON (T1.ID = T2.ID) 

WHEN MATCHED THEN當找到一個匹配,WHEN NOT MATCHED THEN將執行每次當未找到匹配時將執行每一次?這是對的嗎?那麼WHEN NOT MATCHED BY SOURCEWHEN NOT MATCHED BY Target怎麼樣。請幫我

+3

一旦你完成了MERGE如何工作以及它能做什麼,你應該暫停[閱讀它不做的事](http://www.mssqltips.com/sqlservertip/3074/use-caution -with-SQL服務器合併語句/)。 –

+0

@AaronBertrand,很有意思。但是我們是否應該使用MERGE或UPSERT會造成混淆?你怎麼看? – user960567

+1

對我來說,我會繼續使用傳統的單獨陳述。 MERGE不會增加任何收益並引入潛在風險。 –

回答

1

我認爲它從targetsource兩個分支記錄到不同的執行路徑的條件。

下面我給出了一個簡單的數字列表的例子。我使用full join表示合併,case表示「分支」。

DECLARE @source TABLE (i INT, c CHAR(1)) 
DECLARE @target TABLE (i INT) 

INSERT INTO @source (i) 
VALUES (1), (2), (3), (4), (5) 

INSERT INTO @target (i) 
VALUES (1), (2), (3), (6), (7) 

SELECT 
    [source] = s.i, 
    [target] = t.i, 
    [branch] = CASE WHEN t.i IS NULL THEN 'not matched by target' 
        WHEN s.i IS NULL THEN 'not matched by source' 
        ELSE 'matched' END, 
    [possible action] = CASE WHEN t.i IS NULL THEN 'insert into target' 
          WHEN s.i IS NULL THEN 'update target or delete from target' 
          ELSE 'update target or delete from target' END 
FROM @source s 
FULL JOIN @target t ON t.i = s.i 

這將產生以下

source  target  branch     possible action 
----------- ----------- --------------------- ----------------------------------- 
1   1   matched    update target or delete from target 
2   2   matched    update target or delete from target 
3   3   matched    update target or delete from target 
4   NULL  not matched by target insert into target 
5   NULL  not matched by target insert into target 
NULL  6   not matched by source update target or delete from target 
NULL  7   not matched by source update target or delete from target 

所以

  • 當源記錄沒有在目標(not matched by target)匹配,則它們可以是insert編入目標
  • 當目標記錄在源(not matched by source)中沒有匹配時,則相應的targ et記錄可以是update d或deleted這裏顯然不會有任何源記錄可供參考。
  • 當源記錄與目標記錄匹配時(matched),則目標記錄也可以是update d或delete d,但與not matched by source不同,此處您還將獲得來源的記錄。

更新和刪除的注意事項是,不需要使用連接或以其他方式將源連接到目標,在「分支」中的目標等,因爲這些關係已經解決,儘管你正在採取個人記錄。

例如你可能認爲你將不得不做更新,因爲

Update t 
Set t.col = s.col 
From target t 
Join source s On s.id = t.id 

但事實並非如此。

當記錄已經要麼matchednot matched by source那麼可以進一步謂詞數據以決定它是否應該是delete d或update d。這是通過提供兩個相同的'分支'來完成的,如example dMERGE中所示的附加AND子句。

+0

非常好。那麼什麼時候不匹配?我發現這隻會在源和目標之間沒有記錄匹配的情況下執行。正確?如果您添加MERGE語句樣本以更好地理解所有可能性,則更好。 – user960567

+0

不符合目標不匹配 –

+0

其實這是一個很好的解釋。 – user960567

0

後兩者應該是顯而易見的。如果找不到匹配項,則表示其中一個或另一個表沒有另一個表所在的行。也就是說,T1可能有一行,但T2中沒有相應的行,或T2可能有一行,但T1中沒有相應的行。 T2是源,T1是目標,所以當你說時,你指定了T2沒有一行時的動作,而NOT MATCHED BY TARGET是T1沒有一行時的動作。

1

合併基本上會合並兩個表的數據。如果源表中存在來自源表的ID字段,它將執行UPDATE語句(WHEN MATCHED THEN)。如果不存在,它將執行INSERTWHEN NOT MATCHED BY TARGET)。

WHEN NOT MATCHED BY SOURCE表示目標表中有一行不存在於源表中。這通常表示該行在源系統中已被刪除,您必須決定如何處理它。 (在跨國系統的情況下,行簡單地被刪除,而如果您正在處理數據倉庫,則希望保留數據,但將其標記爲「非活動」或沿着這些行)。

在使用MERGE語句之前,必須自己編寫該邏輯。

1

您需要一個源表,並嘗試將新記錄合併到此源表中。您將條件設置爲根據源數據新數據檢查。如果條件爲真,那麼這是一個匹配,如果不是這樣,這不匹配,每個都會有它自己的語句。

當您想要決定是否將新數據添加到插入源或更新現有記錄時,最常用(來自sql我見過/使用過)。例如,產品庫存,您可能會添加新的庫存或更新現有庫存的數量。

有一個很好的例子遵循https://www.simple-talk.com/sql/learn-sql-server/the-merge-statement-in-sql-server-2008/