TL; DR;
有没有办法比较同一个表的两行,无论表模式如何,但忽略了一个特定的列?
长
我在一个系统维护中突然失控,被要求在几个表中实施审计......确切地说是72个表...我决定在更新和删除时使用触发器。它工作正常,表现得像预期的那样
我的问题是系统非常愚蠢,并且在没有任何更改的情况下更新表格上的行,并且为#X和#34;更改X,除了行具有" rowversion"列,所以,最后" rowversion"已更新。我的问题是:有没有办法比较"插入"行的版本和"删除"版本,无论表模式和忽略特定列(因为如果rowversion进入操作,行将不会相同...)。这里的主要目标是单脚本,我只需更改表名...
答案 0 :(得分:2)
这是一个我刚刚编写的脚本,它将创建一个可以从触发器内部调用以获得比较查询的函数。然后,您可以运行该查询并将结果插入到临时表中,并根据行是否更改来执行您需要执行的操作。
create function GetChangedRowsQuery(
@TableName varchar(50),
@PrimaryKeyColumnName varchar(50),
@RowVersionColumnName varchar(50) = ''
)
returns varchar(max)
as
begin
declare
@ColumnName varchar(50),
@GetChangedRowsQuery varchar(max)
select @GetChangedRowsQuery =
'select isnull(a.' + @PrimaryKeyColumnName + ', b.' + + @PrimaryKeyColumnName + ')
from #inserted a
full join #deleted b on a.' + @PrimaryKeyColumnName + ' = b.' + @PrimaryKeyColumnName + '
where '
declare ColumnCursor cursor Read_Only
for select Name
from Sys.columns
where object_id = Object_Id('Member')
open ColumnCursor
fetch next from ColumnCursor into @ColumnName
while @@FETCH_STATUS = 0
begin
if (@ColumnName != @PrimaryKeyColumnName and @ColumnName != @RowVersionColumnName)
begin
select @GetChangedRowsQuery = @GetChangedRowsQuery + '((a.' + @ColumnName + ' != b.' + @ColumnName + ' or a.' + @ColumnName + ' is null or b.' + @ColumnName + ' is null) and (a.' + @ColumnName + ' is not null or b.' + @ColumnName + ' is not null))' + char(13) + ' or '
end
fetch next from ColumnCursor into @ColumnName
end
close ColumnCursor
deallocate ColumnCursor
select @GetChangedRowsQuery = substring(@GetChangedRowsQuery, 0, len(@GetChangedRowsQuery) -7)
return @GetChangedRowsQuery
end
然后你可以创建你的触发器来看起来像这样
create trigger TestTrigger on Member for Insert, Update, Delete
as
begin
//We can't access the inserted or deleted tables from inside the exec statement
//Dump that data into temp tables so you we can
select *
into #Inserted
from Inserted
select *
into #Deleted
from Deleted
declare @GetChangedRowsQuery varchar(max)
select @GetChangedRowsQuery = dbo.GetChangedRowsQuery('Member', 'MemberId', '')
select @GetChangedRowsQuery
create table #Temp (PrimaryKey int)
insert into #Temp (PrimaryKey)
exec (@GetChangedRowsQuery)
//Do what you need to do with the rows that have or haven't been updated
drop table #Temp
end
go
我现在已经更新了这个答案了十几次,而且我认为我已经解决了这个问题,但我不保证。
像这样的查询可能会破坏性能,我不确定我是否真的建议实现它,但创建它很有趣。