Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/83.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何扫描两个查询之间的差异?_Sql_Database_Sql Server 2005_Hash_Checksum - Fatal编程技术网

Sql 如何扫描两个查询之间的差异?

Sql 如何扫描两个查询之间的差异?,sql,database,sql-server-2005,hash,checksum,Sql,Database,Sql Server 2005,Hash,Checksum,我有一个每天加载新数据的表和另一个包含该表更改历史的表。检查自上次加载数据以来是否有任何数据已更改的最佳方法是什么 例如,我在表@a中列出了针对不同国家的一些战略,表@b跟踪了对表@a所做的更改。我可以使用checksum()散列可以更改的字段,如果现有散列与新散列不同,则将它们添加到表中。然而,MSDN认为这不是一个好主意,因为可能会发生“冲突”,例如,两个不同的值映射到同一校验和 用于校验和的MSDN链接 示例代码: declare @a table ( ownerid bigin

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

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

用于校验和的MSDN链接

示例代码:

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
declare@a表
(
所有者的bigint
,策略varchar(50)
,国家字符(3)
)
插入@a
选择1、'Long'、'USA'
插入@a
选择2、'Short'、'CAN'
插入@a
选择3、'Neutral'、'AUS'
声明@b表
(
上次更新日期时间
,所有者ID bigint
,策略varchar(50)
,国家字符(3)
)
插入@b
(
最近更新
,所有者ID
,策略
,国家
)
挑选
getdate()
,a.ownerid
a.战略
,一个国家
从@a左连接@b
在a.ownerid=b.ownerid上
哪里
b、 ownerid为空
从@b中选择*
--获取不同的时间戳
等待延迟'00:00:00.1'
--更改源数据
更新@a
将策略设置为“短”
其中ownerid=1
--将新更改的数据添加到
插入@b
挑选
getdate()
,a.ownerid
a.战略
,一个国家
从…起
(从@a中选择*,校验和(策略,国家)作为hashval)a
左连接
(从@b中选择*,校验和(策略,国家)作为hashval)b
在a.ownerid=b.ownerid上
哪里
a、 哈什瓦尔
从@b中选择*

如果使用不同的方法解决问题,则无需检查更改

在主表上为
插入
更新
删除
创建一个触发器,该触发器通过写入表
@b
来跟踪更改


如果您在internet上搜索“SQL审核表”,您将发现许多描述该过程的页面,例如:

使用编写查询如何?只需为两个表编写查询,然后在它们之间添加
,除了

(SELECT * FROM table_new) EXCEPT (SELECT * FROM table_old) 
结果将是
表格_new
中不在
表格_old
中的条目(即已更新或插入的条目)


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

多亏了@newenglander,我可以使用它来查找更改的行。正如@Tony所说的,我不确定多个更改将如何工作,但这里的示例代码经过重新编写,除了使用校验和之外

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

你能控制源数据吗?最好的办法是在创建和/或修改记录时使用datetime字段进行跟踪。然后仅提取时间戳比当前数据新的数据。否则,您将需要比较每行中的每个字段,以查看是否有任何更改。如果“导入”相当简单,那么考虑到您将新数据视为福音,检查成本通常会超过覆盖。请告诉我Table@b是否允许同一所有者ID有多条记录。is ownerid是主键。@Romil-我猜表
@b
上的PK将是
Lastupdated
ownerid
的组合,但最好从FisOfFury得到澄清。@Romil,PK将是Lastupdated和ownerid的组合。希望帮助您假设
表u旧
中的每一行只包含一行
表u新
;这就意味着第二张表与第一张表完全相同。如果有多行,则使用除
之外的
将不起作用。不会看到最近从
表中删除的行_old
,这是您的意思吗?我会记下来的。这可能就是我要找的!我不得不重新编写了一点,但很快就会发布代码。@Tony,我在更新了两行并且两行都从Except返回时检查了这个方法。谢谢这是一个很好的解决方案,但不是针对我试图解决的问题。具有历史记录的表不仅仅是审计表。我想将新的/更改的结果添加到历史记录表中,以便可以引用其在给定时间点的状态。例如,如果我有一个日期参数,我希望获得该日期的所有最新记录。审计表有助于跟踪历史记录,但不能真正用于获取表在特定日期的状态。@Fistofury-这似乎不正确。我一直使用审计表进行时间点报告。是什么特别使它不适合你?(有几种SQL模式可以直接实现这一点,特别是SQL Server的窗口函数和CTE。)@Dems为了在给定时间点获取表的状态,我必须使用审计表重新创建表的所有更改。例如,如果我想知道一年前某个字段的值是多少,我必须使用当前状态和所有以前的状态来回退该值。使用历史记录表,我可以通过一个简单的
select*从max(timestamp)
表中获取相关行。通过避免使用审计表方法,它更干净、更直观、更易于跟踪。我正在使用SQL 2005,因此无法使用SQL 2008中的CHANGETABLE。抱歉,版主拒绝了这些更改。也许只是尝试发布SQL查询本身,而不添加SQL Server特性?