/*
This code generates a merge statement joining on the natural key
and checking all other columns to see if they have changed.
The full version deals with type 2 processing and an audit trail but this version is useful.
Just the insert or update part is handy too.
Change the table at the top (spt_values in master in the version) and the join columns for the merge in @nk.
The output generated is at the top and the code to run to generate it below.
*/
— Output
merge spt_values a
using spt_values b
on a.name = b.name
and a.number = b.number
and a.type = b.type
when matched and (1=0
or(a.low = b.low) or(a.low is null and b.low is not null) or(a.low is not null and b.low is null)
or(a.high = b.high) or(a.high is null and b.high is not null) or(a.high is not null and b.high is null)
or(a.status = b.status) or(a.status is null and b.status is not null) or(a.status is not null and b.status is null)
)
then update set
low = b.low
, high = b.high
, status = b.status
when not matched by target then insert
(
name
, number
, type
, low
, high
, status
)
values
(
b.name
, b.number
, b.type
, b.low
, b.high
, b.status
);
— Generator
set nocount on
declare @t varchar(128) = ‘spt_values’
declare @i int = 0
— this is the natural key on the table used for the merge statement join
declare @nk table (ColName varchar(128))
insert @nk select ‘Number’
insert @nk select ‘Name’
insert @nk select ‘Type’
declare @cols table (seq int, nkseq int, type int, colname varchar(128))
;with cte as
(
select ordinal_position,
type = case when columnproperty(object_id(@t), COLUMN_NAME,’IsIdentity’) = 1 then 3
when nk.ColName is not null then 1 else 0 end,
COLUMN_NAME
from information_schema.columns c
left join @nk nk
on c.column_name = nk.ColName
where table_name = @t
)
insert @cols(seq, nkseq, type, colname)
select ordinal_position, row_number() over (partition by type order by ordinal_position) ,
type, COLUMN_NAME
from cte
Declare @result table (i int, j int, k int, data varchar(500))
select @i = @i + 1
insert @result(i, data)
select @i, ‘merge ‘ + @t + ‘ a’
select @i = @i + 1
insert @result(i, data)
select @i, ‘ using cte b’
select @i = @i + 1
insert @result(i, j, data)
select @i, nkseq, ‘ ‘ + case when nkseq = 1 then ‘on’ else ‘and’ end + ‘ a.’ + ColName + ‘ = b.’ + ColName
from @cols
where type = 1
select @i = @i + 1
insert @result(i, data)
select @i, ‘ when matched and (1=0’
select @i = @i + 1
insert @result(i, j, k, data)
select @i, seq, 1,
‘ or (a.’ + ColName + ‘ b.’ + ColName + ‘)’
+ ‘ or (a.’ + ColName + ‘ is null and b.’ + ColName + ‘ is not null)’
+ ‘ or (a.’ + ColName + ‘ is not null and b.’ + ColName + ‘ is null)’
from @cols
where type = 1
select @i = @i + 1
insert @result(i, data)
select @i, ‘ )’
select @i = @i + 1
insert @result(i, data)
select @i, ‘ then update set’
select @i = @i + 1
insert @result(i, j, data)
select @i, nkseq,
‘ ‘ + case when nkseq = 1 then ‘ ‘ else ‘, ‘ end
+ colname + ‘ = b.’ + colname
from @cols
where type = 0
select @i = @i + 1
insert @result(i, data)
select @i, ‘ when not matched by target then insert’
select @i = @i + 1
insert @result(i, data)
select @i, ‘ (‘
select @i = @i + 1
insert @result(i, j, data)
select @i, seq, ‘ ‘ + case when seq = 1 then ‘ ‘ else ‘, ‘ end + colname
from @cols
where type = 3
select @i = @i + 1
insert @result(i, data)
select @i, ‘ )’
select @i = @i + 1
insert @result(i, data)
select @i, ‘ values’
select @i = @i + 1
insert @result(i, data)
select @i, ‘ (‘
select @i = @i + 1
insert @result(i, j, data)
select @i, seq, ‘ ‘ + case when seq = 1 then ‘ ‘ else ‘, ‘ end + ‘b.’ + colname
from @cols
where type = 3
select @i = @i + 1
insert @result(i, data)
select @i, ‘ );’
select data from @result order by i,j,k,data
Load comments