1

我有一个每天加载新数据的表和另一个包含该表更改历史的表。检查自上次加载数据以来是否有任何数据发生更改的最佳方法是什么?

例如,我有针对不同国家/地区的一些策略的表@a,表@b 跟踪对表@a 所做的更改。我可以使用 checksum() 对可以更改的字段进行散列,如果现有散列与新散列不同,则将它们添加到表中。然而,MSDN 认为这不是一个好主意,因为可能会发生“冲突”,例如,两个不同的值映射到同一个校验和。

校验和的 MSDN 链接 http://msdn.microsoft.com/en-us/library/aa258245(v=SQL.80).aspx

示例代码:

declare @a table
(
    ownerid bigint
    ,Strategy varchar(50)
    ,country char(3)
)
insert into @a
select 1,'Long','USA'

insert into @a
select 2,'Short','CAN'

insert into @a
select 3,'Neutral','AUS'

declare @b table
(
    Lastupdated datetime
    ,ownerid bigint
    ,Strategy varchar(50)
    ,country char(3)

)

insert into @b
(
    Lastupdated
    ,ownerid
    ,strategy
    ,country
)
select 
    getdate()
    ,a.ownerid
    ,a.strategy
    ,a.country
from @a a left join @b b
    on a.ownerid=b.ownerid
where
    b.ownerid is null

select * from @b

--get a different timestamp
waitfor delay '00:00:00.1'

--change source data
update @a 
set strategy='Short'
where ownerid=1

--add newly changed data into 
insert into @b
select 
    getdate()
    ,a.ownerid
    ,a.strategy
    ,a.country
from 
    (select *,checksum(strategy,country) as hashval from @a) a 
    left join 
    (select *,checksum(strategy,country) as hashval from @b) b
    on a.ownerid=b.ownerid
where 
    a.hashval<>b.hashval

select * from @b
4

3 回答 3

1

如果您对问题使用不同的方法,则无需检查更改。

在您的主表上创建一个触发器INSERTUPDATEDELETE通过写入表来跟踪您的更改@b

如果您在 Internet 上搜索“ SQL 审计表”,您会发现许多页面描述了该过程,例如:向 SQL Server 数据库添加简单的基于触发器的审计

于 2012-05-04T09:29:38.570 回答
1

感谢@newenglander,我能够使用 EXCEPT 找到更改的行。正如@Tony 所说,我不确定多个更改将如何工作,但这里是相同的示例代码,经过重新设计以使用 except 而不是 CHECKSUM

declare @a table
(
    ownerid bigint
    ,Strategy varchar(50)
    ,country char(3)
)
insert into @a
select 1,'Long','USA'

insert into @a
select 2,'Short','CAN'

insert into @a
select 3,'Neutral','AUS'

declare @b table
(
    Lastupdated datetime
    ,ownerid bigint
    ,Strategy varchar(50)
    ,country char(3)

)

insert into @b
(
    Lastupdated
    ,ownerid
    ,strategy
    ,country
)
select 
    getdate()
    ,a.ownerid
    ,a.strategy
    ,a.country
from @a a left join @b b
    on a.ownerid=b.ownerid
where
    b.ownerid is null

select * from @b

--get a different timestamp
waitfor delay '00:00:00.1'

--change source data
update @a 
set strategy='Short'
where ownerid=1



--add newly changed data using EXCEPT
insert into @b 
select getdate(),
    ownerid,
    strategy,
    country
from 
(
    (
    select 
        ownerid
        ,strategy
        ,country 
    from @a changedtable
    ) 
    EXCEPT 
    (
    select 
        ownerid
        ,strategy
        ,country 
    from @b historicaltable
    )
) x

select * from @b
于 2012-05-15T19:24:27.533 回答
1

使用 编写查询怎么样EXCEPT?只需为两个表编写查询,然后EXCEPT在它们之间添加:

(SELECT * FROM table_new) EXCEPT (SELECT * FROM table_old) 

结果将table_new是不在其中的条目table_old(即已更新或插入的条目)。

注意:要获取最近从 中删除的行table_old,您可以颠倒查询的顺序。

于 2012-05-04T10:01:58.693 回答