フラグのあるアイテムを含むターゲットテーブルがあり、ステートメントIsActive
を使用してソーステーブルから挿入および更新しています。MERGE
ソーステーブルに何かが存在する場合はアクティブであり、存在しない場合はアクティブではありません。ロジックは非常に単純です。
- ソースとターゲットに存在する場合、行は
IsActive
trueである必要があります - ソースにのみ存在する場合は、新しい行をターゲットに挿入する必要があり
IsActive
ます。true - ターゲットにのみ存在する場合は、
IsActive
falseに設定する必要があります。
SourceId
ターゲットテーブルにもソーステーブルに関連する識別列があることを除いて、すべて非常に簡単です。MERGE
したがって、特定のソーステーブルについては、対応する。を持つ行に対してのみ実行したいと思いSourceId
ます。
(正規化されたテーブルには、複数のシステムからの同一のデータ型の行が含まれています。これらのシステムからデータを個別に取得するため、一度に1つのソースからマージする必要があります)
次に例を示します。
IF OBJECT_ID('tempdb..#target') IS NOT NULL DROP TABLE #target
IF OBJECT_ID('tempdb..#source') IS NOT NULL DROP TABLE #source
CREATE TABLE #target ( Id INT, SourceId INT, IsActive BIT )
INSERT #target VALUES (1, 1, 0)
INSERT #target VALUES (2, 1, 1)
INSERT #target VALUES (3, 2, 1)
CREATE TABLE #source ( Id INT )
INSERT #source VALUES (1)
INSERT #source VALUES (4)
DECLARE @SourceId INT = 1;
SELECT * FROM #target
MERGE INTO #target t
USING
(
SELECT [Id] FROM #source
) AS s
ON t.[Id] = s.[Id] AND t.[SourceId] = @SourceId
WHEN MATCHED THEN UPDATE SET [IsActive] = 1
WHEN NOT MATCHED BY TARGET THEN INSERT VALUES ([Id], @SourceId, 1)
WHEN NOT MATCHED BY SOURCE THEN UPDATE SET [IsActive] = 0;
SELECT * FROM #target
私の最初の試みはAND t.[SourceId] = @SourceId
、マージ条件にを含めることでしたが、明らかにそれは機能しません-マージするアイテムを制限していますが、ターゲットテーブルは制限していません。ターゲット行ID=3は一致しないため、追加の条件が含まれているかどうかに関係なく、非アクティブに設定されます。
その結果、ソースシステムに対してプロシージャが実行されるたびに、他のすべてのシステムが非アクティブに設定されます。
これまでの私の解決策は、とだけを実行してからMERGE
、一致しない行に対して後続を実行することです。MATCHED
NOT MATCHED BY TARGET
UPDATE
UPDATE #target
SET [IsEnabled] = 0
WHERE [SourceId] = @SourceId
AND [ID] NOT IN (SELECT [ID] FROM #source)
MERGE
このフィルター条件をステートメントに含める方法はありますか?これを達成するための他の賢い方法はありますか?