-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathJoin-CDC-Concat-NotEqual-HardDelete.sql
148 lines (126 loc) · 3.68 KB
/
Join-CDC-Concat-NotEqual-HardDelete.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/* Run once
IF OBJECT_ID('tempdb.dbo.#source') IS NOT NULL DROP TABLE #source;
IF OBJECT_ID('tempdb.dbo.#target') IS NOT NULL DROP TABLE #target;
-- Conditions:
-- 1) Source data is not SCD2
-- 2) Target data is not SCD2
-- 3) Use CONCAT + NOT EQUAL comparison for Change Data Capture
-- 4) Physically delete target rows not in source
-- 5) Both source and target have an identity column for SK (they don't have to match) (or else join on the NK)
-- 6) Use a join to create a XREF table of the source and target SK based on the NK
CREATE TABLE #source
( SK INT IDENTITY(1,1)
, FirstName VARCHAR(20)
, LastName VARCHAR(30)
, EmailAddress VARCHAR(50)
)
CREATE TABLE #target
( SK INT IDENTITY(1,1)
, FirstName VARCHAR(20)
, LastName VARCHAR(30)
, EmailAddress VARCHAR(50)
, Status CHAR(1)
)
INSERT INTO #source
(FirstName,LastName,EmailAddress)
VALUES
('John','Doe','[email protected]')
,('Mary','Jones','[email protected]')
,('Joe','Bloggs','[email protected]')
*/
-- Create code as a SP for easy reuse
DROP PROCEDURE deleteme
GO
CREATE PROCEDURE deleteme
AS
BEGIN
-- Use a full outer join to create a XREF table
IF OBJECT_ID('tempdb.dbo.#xref') IS NOT NULL DROP TABLE #xref;
;WITH ACTION (ACTION, SRC_SK, TGT_SK, CHANGED)
AS (
SELECT CASE
-- List the WHEN clauses in order of probability
WHEN (tgt.SK IS NULL and src.SK IS NOT NULL) THEN 'INSERT'
WHEN (tgt.SK IS NOT NULL and src.SK IS NOT NULL) THEN 'UPDATE'
WHEN (tgt.SK IS NOT NULL and src.SK IS NULL) THEN 'DELETE'
ELSE '' -- Will never happen but CASE likes an ELSE clause
END AS ACTION
,src.SK AS SRC_SK
,tgt.SK AS TGT_SK
,CASE
WHEN CONCAT(
tgt.FirstName
,tgt.LastName
,tgt.EmailAddress
) <>
CONCAT(
src.FirstName
,src.LastName
,src.EmailAddress
)
) THEN 1 ELSE 0 END AS CHANGED
FROM #source src
FULL OUTER JOIN #target tgt
ON src.FirstName = tgt.FirstName
AND src.LastName = tgt.LastName
)
SELECT *
INTO #xref
FROM ACTION a
WHERE a.ACTION IN ('INSERT','DELETE') OR (a.ACTION = 'UPDATE' AND a.CHANGED = 1)
;
-- Use the XREF table to issue separate INSERT/UPDATE/DELETE blocks
BEGIN TRANSACTION
-- INSERT
INSERT INTO #target
(FirstName,LastName,EmailAddress,Status)
SELECT src.FirstName
,src.LastName
,src.EmailAddress
,'I'
FROM #source src
INNER JOIN #xref x
ON src.SK = x.SRC_SK
WHERE x.ACTION = 'INSERT';
-- UPDATE
UPDATE tgt
SET FirstName = src.FirstName
,LastName = src.LastName
,EmailAddress = src.EmailAddress
,Status = 'U'
FROM #target tgt
INNER JOIN #xref x
ON tgt.SK = x.TGT_SK
INNER JOIN #source src
ON src.SK = x.SRC_SK
WHERE x.ACTION = 'UPDATE'
-- DELETE
DELETE tgt
FROM #target tgt
INNER JOIN #xref x
ON tgt.SK = x.TGT_SK
WHERE x.ACTION = 'DELETE';
COMMIT;
SELECT * FROM #source;
SELECT * FROM #target;
SELECT * FROM #xref;
END
-- Load #1: All new rows
TRUNCATE TABLE #target;
EXEC deleteme;
-- Load #2: No change (run the merge again)
-- There should be no change to target
-- Note there is no debug output
EXEC deleteme;
-- Load #3:
-- Record #1 unchanged
-- Record #2 changed (married, new email address)
-- Record #3 deleted
-- Record #4 added
UPDATE #source SET EmailAddress='[email protected]' WHERE SK=2;
DELETE FROM #source WHERE SK=3;
INSERT INTO #source
(FirstName,LastName,EmailAddress)
VALUES
('Billy','Bob','[email protected]')
EXEC deleteme;