Angenommen, Sie haben so etwas:
Quelltabelle (Variable):
Values (
LeftId INT NOT NULL,
RightId INT NOT NULL,
CustomValue varchar(100) NULL
)
Zieltabelle:
Mapping (
LeftId INT NOT NULL,
RightId INT NOT NULL,
CustomValue varchar(100) NULL
)
Ich mag verschmelzen Values
in Target
den folgenden Regeln:
- Match on
source.LeftId = target.LeftId AND source.RightId = target.RightId
- Wenn das Ziel übereinstimmt, aktualisieren Sie es
CustomValue
- Wenn das Ziel nicht übereinstimmt, fügen Sie es ein
- Wenn das Ziel übereinstimmt, aktualisieren Sie es
- Löschen Sie alle nicht übereinstimmenden Werte im Ziel, die mit a
LeftId
in der Quelle übereinstimmen , dh löschen Sie nur Datensätze, die sich auf dieLefId
s der Zusammenführung beziehen .
(Diese letzte Regel ist schwer zu beschreiben, sorry!)
Zum Beispiel:
Quelle:
1, 10, foo
1, 11, foo
Ziel:
1, 10, bar
1, 12, foo
2, 20, car
Ergebnis zusammenführen:
Ergebnisziel:
1, 10, foo (updated)
1, 11, foo (inserted)
1, 12, foo (deleted)
2, 20, car (unchanged)
Damit...
Folgendes habe ich bisher, das kümmert sich um update
und insert
:
MERGE Mapping AS target
USING (SELECT LeftId, RightId, CustomValue FROM @Values)
AS source (LeftId, RightId, CustomValue)
ON target.LeftId = source.LeftId
AND target.RightId = source.RightId
WHEN NOT MATCHED THEN
INSERT (LeftId, RightId, CustomValue)
VALUES (source.LeftId, source.RightId, source.CustomValue)
WHEN MATCHED THEN
UPDATE SET
CustomValue = source.CustomValue;
Wie mache ich den delete
Teil meiner Regel?
sql-server
sql-server-2012
merge
Michael Haren
quelle
quelle
WHEN NOT MATCHED BY source AND EXISTS(SELECT * FROM @Values M WHERE M.LeftId = target.LeftId) THEN DELETE;
Antworten:
Dies ist die separate
DELETE
Operation, an die ich gedacht habe:Wie ich hier skizziere ,
NOT EXISTS
übertrifft dasLEFT JOIN / NULL
Muster bei einem linken Anti-Semi-Join häufig das Muster (aber Sie sollten es immer testen).Sie sind sich nicht sicher, ob Ihr übergeordnetes Ziel Klarheit oder Leistung ist. Daher können nur Sie beurteilen, ob dies für Ihre Anforderungen besser funktioniert als die
NOT MATCHED BY source
Option. Sie müssen die Pläne qualitativ und die Pläne und / oder Laufzeitmetriken quantitativ betrachten, um sicher zu sein.Wenn Sie erwarten, dass Ihr
MERGE
Befehl Sie vor Rennbedingungen schützt, die bei mehreren unabhängigen Anweisungen auftreten würden, sollten Sie sicherstellen, dass dies der Fall ist, indem Sie ihn in Folgendes ändern:(Aus Dan Guzmans Blogbeitrag .)
Persönlich würde ich all dies ohne tun
MERGE
, da es unter anderem ungelöste Fehler gibt . Und Paul White scheint auch separate DML-Anweisungen zu empfehlen .Und hier ist , warum ich ein Schema Präfix hinzugefügt: Sie sollten immer von Objekten nach Schema verweisen, beim Erstellen, zu beeinflussen, etc .
quelle
Sie können die zu berücksichtigenden Zeilen aus der Zieltabelle in einem CTE herausfiltern und den CTE als Ziel für die Zusammenführung verwenden.
quelle
Sie können die
WHEN NOT MATCHED BY SOURCE
Klausel verwenden und eine zusätzliche Bedingung wie folgt angeben:SQL Fiddle
MS SQL Server 2008 Schema-Setup :
Abfrage 1 :
Ergebnisse :
Abfrage 2 :
Ergebnisse :
Ich habe der
MERGE
Anweisung die Ausgabeklausel hinzugefügt, um zu zeigen, welche Aktion für jede Zeile ausgeführt wurde.Wie andere kommentiert haben, müssen Sie auch den
WITH(HOLDLOCK)
Hinweis auf der Zieltabelle angeben, um Rennbedingungen zu vermeiden.quelle
Folgendes habe ich mir ausgedacht. Jedes Feedback wird geschätzt!
-- Testdaten:
- Option 1: Behandeln Sie das
delete
Teil separat:- Option 2: Tun Sie es (umständlich?) In der
MERGE
Anweisung:- Ergebnisse überprüfen:
quelle