2016-08-08 3 views
0

私はMERGEステートメントを使用してデータベースにレコードを挿入/更新しています。SQL Server MERGE複数の句のバリエーション

私のソーステーブルには、レコードが挿入または更新される必要があるかどうかを識別するために使用される3つの列が含まれています。私の問題はON句で発生します。ターゲットテーブルとソーステーブルは3つのカラムを使用して結合されますが、どのように結合できるかについてはさまざまなバリエーションがあります。 (下の例を参照)

これを達成するためにAND/OR演算子を使用できますが、これは面倒でメンテナンスが難しいことがわかります。もっと効率的な方法があるのだろうかと思っていましたか?

私のコードの例は以下の通りです:事前に

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…] 

ありがとう!

+0

あなたが私のためにリストアップした内容に基づいて伝えるのは難しいです。どの列も他の表の他の列と一致することはできますか?読みやすさはパフォーマンスIMHOほど重要です。そして、複数のAND/OR演算子を使用しているので、SQL Serverの優先順位を覚えておいてください。 https://msdn.microsoft.com/en-us/library/ms190276.aspx – scsimon

+0

こんにちは、お返事ありがとうございます。はい。ソーステーブルで使用している3つの変数は、ターゲットテーブルの3つの列のいずれかと任意の順序で一致します。さらに私は例を3つの変数に限定しましたが、最大6つまであります。私は、データを評価し、その変数が列の中で見つかったかどうかを確認するより良い方法があるかどうかを確認したいと思います。 – ccalgie

+0

すべてのパラメータが一意ですか、たとえば、param1とparam2の両方を「1」にすることはできますか? –

答えて

0

ORを使用するのではなく、マージ条件の前に組み合わせを構築することができます。例えば

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

これはあなたの6つの組み合わせ(各持つが、必ず同じパラメータを再使用していない作った結合)を与える:

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

だからあなたMERGE状態がずっと簡単になる:

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…]; 

これにより、さらにパラメータを追加することが容易になります。したがって、4番目のパラメータは、の全く新しいセットではなく、CTE paramsに余分な行しか必要としません。多くの特別なコードなしで24のすべての組み合わせを与える。