2012-05-18 6 views
26

Angenommen, ich habe eine Tabelle mit einem Identitätsfeld. Ich möchte einen Datensatz darin einfügen, wenn es nicht bereits existiert. Im folgenden Beispiel überprüfe ich, ob der in @ Field1 gespeicherte Wert bereits in der Tabelle existiert. Falls nicht, füge ich einen neuen Rekord:Wie erhalten Sie den Identitätswert nach der Verwendung von MERGE, wenn es eine Übereinstimmung gibt?

Definition der Tabelle:

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

Dies ist, wie ich überprüfen, ob bereits der Wert vorhanden ist, und legen Sie es dann notwendig, wenn

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); 

Abrufen der Identität Wert, wenn der Datensatz noch nicht in der Tabelle vorhanden ist, kann durch Hinzufügen von hinzugefügt werden:

aber was ist, wenn der Rekord schon in der Tabelle war (dh wenn es ein Match gab)?

Der einzige Weg, ich ist gefunden die Tabelle abzufragen, nachdem die Merge-Anweisung ausführen:

select MyTableId from MyTable where [email protected] 

Gibt es eine Möglichkeit, die Identität Wert direkt aus dem Merge zu bekommen?

Antwort

25

Im Fall, wenn der Datensatz bereits vorhanden ist, können Sie die angepassten ID in eine Variable wie folgt speichern:

DECLARE @MatchedId INTEGER; 

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

UPDATE:
Hier ist ein vollständiges Beispiel. Dies zeigt einen Weg:

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 

Punkte sind zu beachten:

  • $ Aktion geben, welche Art von Aktion für eine Zeile durchgeführt wurde (INSERT, UPDATE, DELETE)
  • @ChangeResult Tisch wird die Info halten, welche Arten von Änderungen vorgenommen wurden
  • für den Fall WENN MATCHED, ich bin im Grunde eine Dummy-Variable einstellen. Dies dient hier keinem anderen Zweck als sicherzustellen, dass der UPDATE-Pfad zum Erzeugen der UPDATE-Zeile in der Ausgabe getroffen wird. d. h., dass @UpdateVariable für nichts anderes verwendet wird. Wenn Sie die bestehende Zeile wirklich aktualisieren wollten, dann würden Sie hier ein richtiges UPDATE eingeben, aber in dem Fall, in dem Sie die bestehende Zeile nicht wirklich aktualisieren möchten, scheint diese "Dummy" -Update erforderlich zu sein.
+1

Danke Adrian, aber wenn es "keine Übereinstimmung" gibt, wie erhalten Sie den neuen Identitätswert in @MatchedId? – Anthony

+4

Danke für das Update. Ja, das würde funktionieren, aber es sieht so aus, als wäre es viel mehr Code als nur "wähle MyTableId von MyTable, wobei Field1 = @ Field1" nach dem Merge (offensichtlich hängt es von der Größe der realen Tabelle usw. ab).Ich hatte nur gehofft, dass es in der Merge-Anweisung eine 'eingebaute' Lösung gab, die den Identitätswert in beiden Fällen zurückgab (übereinstimmend oder nicht übereinstimmend). – Anthony

17

Hier ist ein alternative und etwas einfacherer Ansatz (meiner Meinung nach):

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; 

Wenn die Merge-Anweisung in einem Spiel führte dann @Id auf die Identität der passenden Zeile eingestellt werden. Wenn keine Übereinstimmung vorliegt, wird die neue Zeile mit ihrer neuen Identität eingefügt, die zur Auswahl aus SCOPE_IDENTITY() bereit ist.

Verwandte Themen