14

フラグのあるアイテムを含むターゲットテーブルがあり、ステートメントIsActiveを使用してソーステーブルから挿入および更新しています。MERGEソーステーブルに何かが存在する場合はアクティブであり、存在しない場合はアクティブではありません。ロジックは非常に単純です。

  • ソースとターゲットに存在する場合、行はIsActivetrueである必要があります
  • ソースにのみ存在する場合は、新しい行をターゲットに挿入する必要がありIsActiveます。true
  • ターゲットにのみ存在する場合は、IsActivefalseに設定する必要があります。

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、一致しない行に対して後続を実行することです。MATCHEDNOT MATCHED BY TARGETUPDATE

UPDATE #target
SET [IsEnabled] = 0 
WHERE [SourceId] = @SourceId
AND [ID] NOT IN (SELECT [ID] FROM #source)

MERGEこのフィルター条件をステートメントに含める方法はありますか?これを達成するための他の賢い方法はありますか?

4

1 に答える 1

7

したがって、結果セットは次のようになります。

1 1 1
2 1 0    
3 2 1
4 1 1

この場合、マージステートメントは次のようになります。

merge #target as t
using #source as source
on (t.id=source.id)
when matched then update set isactive=1
when not matched by target then insert values (id, @sourceid,1)
when not matched by source and SourceID=@sourceID then update set isactive=0 

総テスト:

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 
select @SourceId = 1;     

merge #target as t 
using #source as source 
on (t.id=source.id) 
when matched then update set isactive=1 
when not matched by target then insert values (id, @sourceid,1) 
when not matched by source and SourceID=@SourceID then update set isactive=0;


SELECT * FROM #target 

drop table #target;
drop table #source

結果...

Id          SourceId    IsActive
----------- ----------- --------
1           1           1
2           1           0
3           2           1
4           1           1
于 2012-07-25T19:01:32.307 に答える