2016-08-08 72 views
0

Ich verwende die MERGE-Anweisung, um Datensätze in meiner Datenbank einzufügen/zu aktualisieren.SQL Server MERGE mehrere Varianten Variationen

Meine Quellentabelle enthält drei Spalten, die verwendet werden, um festzustellen, ob ein Datensatz eingefügt oder aktualisiert werden muss. Mein Problem tritt in der ON-Klausel auf - die Zieltabelle und die Quelltabelle sind mit den drei Spalten verbunden, es gibt jedoch zahlreiche Variationen darüber, wie diese verknüpft werden könnten. (Siehe folgendes Beispiel)

Ich weiß, dass die AND/OR-Operatoren verwendet werden können, um dies zu erreichen, aber dies wird unordentlich und schwierig zu warten. Ich habe mich gefragt, ob es einen effizienteren Weg gibt?

Ein Beispiel für meinen Code ist unten:

MERGE Target_Table as t 
    USING (select @param1, @param2, @param3)  
     AS s (col1, col2, col3) 
     ON (t.col1 = s.col1 
    AND t.col2 = s.col2 
    AND t.col3 = s.col3) 
     OR (t.col1 = s.col2 
    AND t.col2 = s.col1 
    AND t.col3 = s.col3) 
    WHEN 
MATCHED 
    THEN […update…] 
    WHEN 
    NOT 
MATCHED 
    THEN […insert…] 

Vielen Dank im Voraus!

+0

Schwer zu sagen, was Sie für mich aufgelistet haben. Kann eine Spalte mit einer anderen Spalte in der anderen Tabelle übereinstimmen? Lesbarkeit ist fast so wichtig wie Leistung IMHO. Und obwohl ich mir sicher bin, dass Sie sich dessen bewusst sind, da Sie mehrere AND/OR-Operatoren verwenden, sollten Sie sich bei der Auswertung der SQL Server-Präzedenzfälle daran erinnern. https://msdn.microsoft.com/en-us/library/ms190276.aspx – scsimon

+0

Hallo, vielen Dank für Ihre Antwort. Ja, die drei Variablen, die ich in der Quellentabelle verwende, können in beliebiger Reihenfolge mit jeder der drei Spalten in der Zieltabelle übereinstimmen. Zusätzlich habe ich das Beispiel auf drei Variablen beschränkt, aber es kann bis zu sechs geben. Ich würde gerne sehen, ob es eine schönere Möglichkeit gibt, die Daten auszuwerten und zu sehen, ob die Variablen in einer der Spalten gefunden werden. – ccalgie

+0

Sind alle Parameter eindeutig oder können diese Werte gleich sein? Können zum Beispiel param1 und param2 beide "1" sein? –

Antwort

0

Sie könnten die Quelltabelle anders aufbauen, anstatt OR zu verwenden, können Sie die Kombinationen vor der Zusammenführungsbedingung aufbauen. z.B.

DECLARE @param1 INT = 1, 
     @param2 INT = 2, 
     @param3 INT = 3; 


WITH Params AS 
( SELECT pValue, pNumber 
    FROM (VALUES (@param1, 1), (@param2, 2), (@param3, 3)) p (pValue, pNumber) 
) 
SELECT Col1 = p1.Pvalue, Col2 = p2.Pvalue, Col3 = p3.Pvalue 
FROM Params AS P1 
     INNER JOIN Params AS p2 
      ON p2.pNumber NOT IN (p1.pNumber) 
     INNER JOIN Params AS p3 
      ON p3.pNumber NOT IN (p1.pNumber, p2.pNumber); 

Dies gibt Ihnen Ihre 6-Kombinationen (mit jedem beitreten dafür, dass Sie nicht die gleichen Parameter wiederverwenden):

Col1 Col2 Col3 
------------------ 
2  3  1 
3  2  1 
1  3  2 
3  1  2 
1  2  3 
2  1  3 

So Ihr MERGE worden Zustand viel einfacher:

WITH Params AS 
( SELECT pValue, pNumber 
    FROM (VALUES (@param1, 1), (@param2, 2), (@param3, 3)) p (pValue, pNumber) 
), SourceTable AS 
( SELECT Col1 = p1.Pvalue, Col2 = p2.Pvalue, Col3 = p3.Pvalue 
    FROM Params AS P1 
      INNER JOIN Params AS p2 
       ON p2.pNumber NOT IN (p1.pNumber) 
      INNER JOIN Params AS p3 
       ON p3.pNumber NOT IN (p1.pNumber, p2.pNumber) 
) 
MERGE Target_Table AS t 
USING SourceTable AS s 
    ON t.col1 = s.col1 
    AND t.col2 = s.col2 
    AND t.col3 = s.col3 
WHEN MATCHED THEN […update…] 
WHEN NOT MATCHED THEN […insert…]; 

Dies macht es auch einfacher, weitere Parameter hinzuzufügen, so dass ein vierter Parameter nur eine zusätzliche Zeile im CTE params erfordert, anstatt einen ganz neuen Satz von OR Bedingungen

DECLARE @param1 INT = 1, 
     @param2 INT = 2, 
     @param3 INT = 3, 
     @param4 INT = 4; 


WITH Params AS 
( SELECT pValue, pNumber 
    FROM (VALUES (@param1, 1), (@param2, 2), (@param3, 3), (@Param4, 4)) p (pValue, pNumber) 
) 
SELECT Col1 = p1.Pvalue, Col2 = p2.Pvalue, Col3 = p3.Pvalue 
FROM Params AS P1 
     INNER JOIN Params AS p2 
      ON p2.pNumber NOT IN (p1.pNumber) 
     INNER JOIN Params AS p3 
      ON p3.pNumber NOT IN (p1.pNumber, p2.pNumber); 

Welche gibt dann alle 24 Kombinationen, ohne viel zusätzlichen Code.