2012-05-18 18 views
26

假設我有一張帶有標識字段的表格。如果它不存在,我想在它中插入一條記錄。在下面的例子中,我檢查存儲在@ Field1中的值是否已經存在於表中。如果沒有,我插入一個新的記錄:表中的如何在比賽結束後使用MERGE後獲得身份值?

定義:

MyTable (MyTableId int Identity not null, Field1 int not null, Field2 int not null) 

這是我如何檢查是否值已經存在,並在必要時

merge MyTable as t 
using (@Field1, @Field2) as s (Field1,Field2) 
on (t.Field1=s.Field1) 
when not matched then 
    insert (Field1,Field2) values (s.Field1,s.Field2); 

獲取身份插入當表中記錄不存在時可以通過添加值來完成:

output Inserted.MyTableId 

但是如果記錄已經在表格中(即如果有匹配)呢?

我發現的唯一方法是執行MERGE語句之後查詢表:

select MyTableId from MyTable where [email protected] 

有沒有辦法直接從合併獲得的標識值?

回答

25

在當記錄已經存在的情況下,你可以匹配的ID存儲到這樣一個變量:

DECLARE @MatchedId INTEGER; 

MERGE MyTable as t 
.... 
.... 
WHEN MATCHED THEN 
    UPDATE SET @MatchedId = t.MyTableId; 

UPDATE:
這裏有一個完整的例子。這表明了一個辦法:

DECLARE @UpdateVariable bit 
DECLARE @ChangeResult TABLE (ChangeType VARCHAR(10), Id INTEGER) 
DECLARE @Data TABLE (Id integer IDENTITY(1,1), Val VARCHAR(10)) 
INSERT @Data ([Val]) VALUES ('A'); 

MERGE @data AS TARGET 
USING (SELECT 'A' AS Val UNION ALL SELECT 'B' AS Val) AS SOURCE ON TARGET.Val = SOURCE.Val 
WHEN NOT MATCHED THEN 
    INSERT ([Val]) 
    VALUES (SOURCE.Val) 
WHEN MATCHED THEN 
    UPDATE SET @UpdateVariable = 1 
OUTPUT $action, inserted.Id INTO @ChangeResult; 

SELECT * FROM @data 
SELECT * FROM @ChangeResult 

點需要注意的是:

  • $行動會給你的行執行何種類型的動作(INSERT,UPDATE,DELETE)
  • @ChangeResult表將持有關於什麼類型的更改的信息
  • 對於WHEN MATCHED情況,我基本上設置了一個虛擬變量。除了確保UPDATE路徑被命中以在輸出中生成UPDATE行之外,此處不起任何作用。即@UpdateVariable不用於其他任何事情。如果你真的想更新現有的行,那麼你會在這裏放置一個適當的UPDATE,但是如果你不想實際更新現有的行,那麼這個「虛擬」更新似乎是必需的。
+1

感謝艾德里安,但如果沒有匹配,那麼你如何獲得新的身份值到@MatchedId? – Anthony

+4

感謝您的更新。是的,這將工作,但它看起來像是更多的代碼,而不僅僅是在合併後(顯然它取決於真實表的大小等)「從MyTable中選擇MyTableId where Field1 = @ Field1」。我只是希望Merge語句中有一個「內置」解決方案,它將在兩種情況下返回標識值(匹配或不匹配)。 – Anthony

17

這是一種替代和略微簡單的方法(在我看來):

DECLARE @Id [int]; 

MERGE INTO [MyTable] AS [t] 
USING (VALUES 
    (@FieldA, @FieldB) 
) 
AS [x] (FieldA, FieldB) 
ON [t].[FieldA] = [x].[FieldA] 
AND [t].[FieldB] = [x].[FieldB] 
WHEN NOT MATCHED BY TARGET THEN 
    INSERT (FieldA, FieldB) 
    VALUES (FieldA, FieldB) 
WHEN MATCHED THEN 
    UPDATE SET @Id = [t].[Id] 

IF @Id IS NULL 
BEGIN 
    SET @Id = CAST(SCOPE_IDENTITY() as [int]); 
END 
SELECT @Id; 

如果MERGE語句產生了一個匹配,那麼@Id將被設置爲匹配行的標識。在不匹配的情況下,新行將被插入,其新標識準備從SCOPE_IDENTITY()中選擇。

相關問題