2012-04-18 23 views
35

以下需要:牛逼SQL合併例子來幫助理解

MERGE dbo.commissions_history AS target 
USING (SELECT @amount, @requestID) AS source (amount, request) 
ON (target.request = source.request) 
WHEN MATCHED THEN 
    UPDATE SET amount = source.amount 
WHEN NOT MATCHED THEN 
    INSERT (request, amount) 
    VALUES (source.request, source.amount); 

https://stackoverflow.com/a/2967983/857994是做插入/更新(並增加了一些工作,刪除)一個非常漂亮的方式。即使經過一些Google搜索,我仍然發現很難遵循。

可有人請:

  • 解釋這一點簡單來說 - MSDN文檔肢解我的大腦在這種情況下。
  • 告訴我如何修改它,以便用戶可以鍵入&請求的值,而不是從另一個數據庫位置選擇它們。

基本上,我想用它來從C#應用程序中插入/更新從我得到的XML文件中獲取的信息。所以,我需要了解如何手動制定一個查詢來使用這種機制將我的分析數據存入數據庫。

+0

我在下面做了一個演練,但如果我是你,我會在這裏發表第二個問題o n SO具有目標表的結構和來自xml源代碼的示例代碼片段,並詢問...我將如何編寫MERGE語句以從此xml更新此表。另外請記住,MERGE聲明最終可能不是這項工作的最佳工具。 – RThomas 2012-04-18 23:58:11

+0

謝謝,那實際上正是我所需要的。我可能會在稍後提出額外的問題,這是一個很好的建議。 – 2012-04-19 00:36:01

回答

67

如果你不熟悉join statements那麼這就是你需要開始的地方。瞭解連接如何工作是休息的關鍵。一旦你熟悉了連接,那麼理解合併最簡單的辦法是把它看作是一個完整的連接,指示如何處理或不匹配的行。

因此,使用所提供的代碼示例讓我們看看錶commissions_history

| Amount | Request | <other fields | 
-------------------------------------------- 
| 12.00 | 1234  | <other data | 
| 14.00 | 1235  | <other data | 
| 15.00 | 1236  | <other data | 

MERGE語句創建一個表之間的全面加入,被稱爲「目標」,並返回表的表達式(或結果集在邏輯上非常類似於像CTE這樣的表)稱爲「源」。

在給出的示例中,它使用變量作爲我們假設已由用戶設置或作爲參數傳遞的源。

DECLARE @Amount Decimal = 18.00; 
DECLARE @Request Int = 1234; 

MERGE dbo.commissions_history AS target  
USING (SELECT @amount, @requestID) AS source (amount, request)  
ON (target.request = source.request) 

當被認爲是連接時,創建以下結果集。

| Amount | Request | <other fields | Source.Amount | Source.Request | 
------------------------------------------------------------------------------ 
| 12.00 | 1234  | <other data | 18.00  |  1234  | 
| 14.00 | 1235  | <other data | null  |  null  | 
| 15.00 | 1236  | <other data | null  |  null  | 

在找到匹配的情況下,使用關於如何對目標執行的指示。

WHEN MATCHED THEN   
UPDATE SET amount = source.amount  

生成的目標表現在看起來像這樣。具有請求1234的行被更新爲18.

| Amount | Request | <other fields | 
-------------------------------------------- 
| 18.00 | 1234  | <other data | 
| 14.00 | 1235  | <other data | 
| 15.00 | 1236  | <other data | 

由於匹配WAS發現沒有其他事情發生。但讓我們說來源的價值是這樣的。

DECLARE @Amount Decimal = 18.00; 
DECLARE @Request Int = 1239; 

得到的加入應該是這樣的:

| Amount | Request | <other fields | Source.Amount | Source.Request | 
------------------------------------------------------------------------------ 
| 12.00 | 1234  | <other data | null  |  null  | 
| 14.00 | 1235  | <other data | null  |  null  | 
| 15.00 | 1236  | <other data | null  |  null  | 
| null | null  | null   | 18.00  |  1239  | 

由於匹配的行並沒有在目標中找到的語句執行的其他條款。

WHEN NOT MATCHED THEN         
INSERT (request, amount)         
VALUES (source.request, source.amount); 

從而產生了目標表,現在看起來是這樣的:

| Amount | Request | <other fields | 
-------------------------------------------- 
| 12.00 | 1234  | <other data | 
| 14.00 | 1235  | <other data | 
| 15.00 | 1236  | <other data | 
| 18.00 | 1239  | <other data | 

合併報表真正潛力是當源和目標都大表。因爲它可以用一個簡單的語句爲每一行執行大量的更新和/或插入操作。

最後一點。請注意,not matched默認爲全部子句not matched by target,但您可以指定not matched by source來代替默認子句或除此之外還指定not matched by source。合併語句支持兩種類型的不匹配(源中的記錄不在目標中,或者目標中的記錄不在源中,如條款所定義)。 You can find full documentation, restrictions, and complete syntax on MSDN.

+4

很好的答案,謝謝! – 2013-06-04 11:31:42

+0

'完全聯合'可以做很棒的事情! – ErikE 2013-06-08 00:35:28

+0

很好的答案,很全面。我喜歡用WHEN NOT MATCHED子句總是指定'BY TARGET'或'BY SOURCE',因爲當它重新讀入軌道時它更清晰。您不必記住默認設置,它更接近英文。 – Davos 2015-05-26 07:11:18

0

在你做

DECLARE @Request Int 

給出答案的例子,但稱這是在SQL如下:

SELECT @amount, @requestID 

另一個將被命名和調用變量相同:

@amount vs. Amount -> @Amount & Amount