Основываясь на ваших дальнейших комментариях, я думаю, что основная проблема заключается в том, как вы обрабатываете обновления типа 2.Быстрый ответ - вам нужны две операции UPDATE (вставка / обновление);и DELETES на самом деле не DELETES, а ОБНОВЛЕНИЯ на временной метке.
Я сформулировал пример запроса ниже, как обрабатывать обновления типа 2, и результаты должны быть самоочевидными.Я попытался выполнить двойную операцию слияния UPDATE, и интересно, что он не может этого сделать и выдает ошибку: "Действие типа INSERT не разрешено в предложении WHEN MATCHEDОператор MERGE. " Так что я думаю, что нет другого выбора, кроме как разделить обновление и вставку оператора UPDATE.
Последнее соображение также касается DELETE, который проявляется как обновление.Я также обработал это в приведенном ниже коде, как определить, когда действие UPDATE действительно является DELETE.
DROP TABLE IF EXISTS _a
CREATE TABLE _a (
id int
,val int
,fromdate datetime
,todate datetime
,isactive bit
)
INSERT INTO _a
select 1,100,'2015-Jan-1',NULL,1
UNION ALL select 2,200,'2015-Feb-1',NULL,1
UNION ALL select 3,300,'2015-Mar-1',NULL,1
DROP TABLE IF EXISTS #data
DROP TABLE IF EXISTS #outputdata
select * INTO #data from _a
select TOP 0 action=CAST('' as varchar(10)),* INTO #outputdata from _a
DELETE #data where id = 3
UPDATE #data set val = 2000 where id = 2
INSERT INTO #data
select 4,400,GETDATE(),NULL,1
--select * from #data
-- _a is your data warehouse table using type2
BEGIN TRAN
select Note='OLD STATE OF _a',* from _a
select Note='NEW SET OF DATA',* from #data
MERGE dbo._a T
USING (
select id,val from #data
) S
ON (S.id = T.id)
WHEN MATCHED
AND ((S.val <> T.val OR (S.val IS NOT NULL AND T.val IS NULL) OR (S.val IS NULL AND T.val IS NOT NULL)))
THEN UPDATE SET
todate = GETDATE()
,isactive = 0
WHEN NOT MATCHED BY TARGET
THEN INSERT (id,val,fromdate,todate,isactive)
VALUES (id,val,GETDATE(),NULL,1)
WHEN NOT MATCHED BY SOURCE --AND T.id IN (SELECT id FROM #data)
--THEN DELETE TYPE2
THEN UPDATE SET /*NO-PK*/
todate = GETDATE()
,isactive = 0
OUTPUT $action as Action
,ISNULL(inserted.id,deleted.id) as id
,ISNULL(inserted.val,deleted.val) as val
,ISNULL(inserted.fromdate,deleted.fromdate) as fromdate
,ISNULL(inserted.todate,deleted.todate) as todate
,ISNULL(inserted.isactive,deleted.isactive) as isactive
INTO #outputdata;
select Note='Logs Output',* from #outputdata
-- FIND THE NEW RECORD
INSERT INTO _a (id,val,fromdate,todate,isactive)
SELECT a.id,a.val,GETDATE()+.000001,a.todate,a.isactive
FROM #data a
INNER JOIN #outputdata b
on a.id = b.id
WHERE b.action ='UPDATE'
select Note='NEW STATE OF _a',* from _a
SELECT Note='Real Action',d1.id,action=CASE WHEN action='UPDATE' AND d2.id is null then 'DELETE' ELSE action END
FROM #outputdata d1
LEFT JOIN _a d2
on d1.action ='UPDATE' and d1.id = d2.id and d2.isactive =1
ROLLBACK TRAN
Результатами будут:
+-----------------+----+-----+-------------------------+--------+----------+
| Note | id | val | fromdate | todate | isactive |
+-----------------+----+-----+-------------------------+--------+----------+
| OLD STATE OF _a | 1 | 100 | 2015-01-01 00:00:00.000 | NULL | 1 |
| OLD STATE OF _a | 2 | 200 | 2015-02-01 00:00:00.000 | NULL | 1 |
| OLD STATE OF _a | 3 | 300 | 2015-03-01 00:00:00.000 | NULL | 1 |
+-----------------+----+-----+-------------------------+--------+----------+
+-----------------+----+------+-------------------------+--------+----------+
| Note | id | val | fromdate | todate | isactive |
+-----------------+----+------+-------------------------+--------+----------+
| NEW SET OF DATA | 1 | 100 | 2015-01-01 00:00:00.000 | NULL | 1 |
| NEW SET OF DATA | 2 | 2000 | 2015-02-01 00:00:00.000 | NULL | 1 |
| NEW SET OF DATA | 4 | 400 | 2019-01-31 09:49:45.943 | NULL | 1 |
+-----------------+----+------+-------------------------+--------+----------+
+-------------+--------+----+-----+-------------------------+-------------------------+----------+
| Note | action | id | val | fromdate | todate | isactive |
+-------------+--------+----+-----+-------------------------+-------------------------+----------+
| Logs Output | INSERT | 4 | 400 | 2019-01-31 09:51:13.647 | NULL | 1 |
| Logs Output | UPDATE | 2 | 200 | 2015-02-01 00:00:00.000 | 2019-01-31 09:51:13.647 | 0 |
| Logs Output | UPDATE | 3 | 300 | 2015-03-01 00:00:00.000 | 2019-01-31 09:51:13.647 | 0 |
+-------------+--------+----+-----+-------------------------+-------------------------+----------+
-- OPERATIONS 1 INSERT 1 UPDATE 1 DELETE
DELETE #data where id = 3
UPDATE #data set val = 2000 where id = 2
INSERT INTO #data
select 4,400,GETDATE(),NULL,1
+-----------------+----+------+-------------------------+-------------------------+----------+
| Note | id | val | fromdate | todate | isactive |
+-----------------+----+------+-------------------------+-------------------------+----------+
| NEW STATE OF _a | 1 | 100 | 2015-01-01 00:00:00.000 | NULL | 1 |
| NEW STATE OF _a | 2 | 200 | 2015-02-01 00:00:00.000 | 2019-01-31 09:51:13.647 | 0 |
| NEW STATE OF _a | 3 | 300 | 2015-03-01 00:00:00.000 | 2019-01-31 09:51:13.647 | 0 |
| NEW STATE OF _a | 4 | 400 | 2019-01-31 09:51:13.647 | NULL | 1 |
| NEW STATE OF _a | 2 | 2000 | 2019-01-31 09:51:13.733 | NULL | 1 |
+-----------------+----+------+-------------------------+-------------------------+----------+
+-------------+----+--------+
| Note | id | action |
+-------------+----+--------+
| Real Action | 4 | INSERT |
| Real Action | 2 | UPDATE |
| Real Action | 3 | DELETE |
+-------------+----+--------+