-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMerge-CDC-Binary_Checksum-HardDelete.sql
179 lines (153 loc) · 3.65 KB
/
Merge-CDC-Binary_Checksum-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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
/* 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;
IF OBJECT_ID('tempdb.dbo.#debug') IS NOT NULL DROP TABLE #debug;
-- Conditions:
-- 1) Source data is not SCD2
-- 2) Target data is not SCD2
-- 3) Use BINARY_CHECKSUM for Change Data Capture
-- 4) Physically delete target rows not in source
CREATE TABLE #source
( SK INT IDENTITY(1,1)
, FirstName VARCHAR(20)
, LastName VARCHAR(30)
, EmailAddress VARCHAR(50)
)
CREATE TABLE #target
( SK INT
, FirstName VARCHAR(20)
, LastName VARCHAR(30)
, EmailAddress VARCHAR(50)
, Status CHAR(1)
, BCS INT
)
CREATE TABLE #debug
( ACTION CHAR(6)
, SK INT
, FirstName VARCHAR(20)
, LastName VARCHAR(30)
, EmailAddress VARCHAR(50)
)
INSERT INTO #source
(FirstName,LastName,EmailAddress)
VALUES
('John','Doe','[email protected]')
,('Mary','Jones','[email protected]')
,('Joe','Bloggs','[email protected]')
*/
/*
Note: BINARY_CHECKSUM can experience data collisions. Run this code:
DECLARE @t TABLE (s VARCHAR(50));
INSERT INTO @t
VALUES
('2Volvo Director 20')
,('3Volvo Director 30')
,('4Volvo Director 40')
SELECT s, BINARY_CHECKSUM(s) FROM @t
https://decipherinfosys.wordpress.com/2007/05/18/checksum-functions-in-sql-server-2005/
*/
-- Create code as a SP for easy reuse
DROP PROCEDURE deleteme
GO
CREATE PROCEDURE deleteme
AS
BEGIN
TRUNCATE TABLE #debug
INSERT INTO #debug
SELECT
ACTION
,SK
,FirstName
,LastName
,EmailAddress
FROM (
MERGE #target tgt
USING #source src
ON (tgt.SK = src.SK)
-- New Rows
WHEN NOT MATCHED
THEN INSERT
(
SK
,FirstName
,LastName
,EmailAddress
,Status
,BCS
)
VALUES (
src.SK
,src.FirstName
,src.LastName
,src.EmailAddress
,'I'
,BINARY_CHECKSUM(
src.SK
,src.FirstName
,src.LastName
,src.EmailAddress
)
)
-- Changed Rows
-- Use BINARY_CHECKSUM comparison to detect actual changes
WHEN MATCHED
AND (tgt.BCS <> BINARY_CHECKSUM(
src.SK
,src.FirstName
,src.LastName
,src.EmailAddress
)
)
THEN UPDATE
SET tgt.FirstName = src.FirstName
,tgt.LastName = src.LastName
,tgt.EmailAddress = src.EmailAddress
,tgt.Status = 'U'
,tgt.BCS = BINARY_CHECKSUM(
src.SK
,src.FirstName
,src.LastName
,src.EmailAddress
)
-- Physically delete target rows not in source
WHEN NOT MATCHED BY SOURCE
THEN DELETE
-- Stream output to outer query
OUTPUT
$ACTION
,src.SK
,src.FirstName
,src.LastName
,src.EmailAddress
)
AS changes
(
ACTION
,SK
,FirstName
,LastName
,EmailAddress
)
;
SELECT * FROM #source
SELECT * FROM #target
SELECT * FROM #debug
END
-- Load #1: All new rows
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 LastName='Smith',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;