我有一個包含具有IsActive
標誌的項目的目標表,並且我使用MERGE
語句從源表插入和更新。如果源表中存在某種東西,那麼它是活動的,如果它不存在,則它不是活動的。邏輯很簡單:我可以在MERGE語句中的目標上應用WHERE子句嗎?
- 如果它存在於源和目標的行應該有
IsActive
真正 - 如果只存在於源,則新行應插入到目標,與
IsActive
true - 如果它只存在於目標中,那麼
IsActive
應設置爲false。
所有非常直接的,除了目標表還有一個歧視列SourceId
它涉及到源表。因此,對於給定的源表,我只希望MERGE
與相應的SourceId
對應的行。
(我的歸一化的表包含來自多個系統的相同數據類型的行 - I從這些系統檢索數據個別地並且因此需要從一個源同時合併)
下面是一個例子:
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 #target
SET [IsEnabled] = 0
WHERE [SourceId] = @SourceId
AND [ID] NOT IN (SELECT [ID] FROM #source)
有沒有什麼辦法,包括在MERGE
聲明中過濾條件的後續UPDATE
?有沒有其他聰明的方法來實現這一目標?
如果您嘗試這樣做,您會發現它爲該行提供了「3 2 0」。原因是當你加入't.id = source.id'時,第3行沒有't'。它與第2行一樣被對待,並被標記爲活動。 –
@KirkBroadhurst它不適合我!請參閱上面的完整測試 – podiluska
啊,我看到了,我太快讀了。真棒回答謝謝!我不知道我可以在那裏放置一個條件。 –