2012-05-03 39 views
0

如果自上次检查(每天一次)以来发生了某些变化,我会定期检查某个查询(通过该方式包含多个表)以向用户添加信息性消息。检测SQL Server 2000表数据中的更改

我试图使它与checksum_agg(binary_checksum(*))工作,但它并没有帮助,所以this question没有太大的帮助,因为我有以下的情况下(简单化):

select checksum_agg(binary_checksum(*)) 
from  
(
    select 1 as id, 
      1 as status 

    union all 

    select 2 as id, 
      0 as status 
) data 

select checksum_agg(binary_checksum(*)) 
from  
(
    select 1 as id, 
      0 as status 

    union all 

    select 2 as id, 
      1 as status 
) data 

上述两种情况都会导致相同的总和49,并且很明显数据已更改。

这并不一定是一个简单的函数或一个简单的解决方案,但我需要一些方法来唯一地标识的区别像这样在SQL Server 2000中

+0

相关问题:http://stackoverflow.com/questions/7362312/is-there-a-function-feature-in-sql-server-to-determine-if-a-table-has-any -recen –

+1

尝试在您的基表中添加'timestamp' /'rowversion'列。 – wqw

回答

1

CHECKSUM_AGG似乎只是BIN​​ARY_CHECKSUM的结果相加为所有行。尽管每一行都改变了,但两个校验和的总和还没有(即17 + 32 = 16 + 33)。这是不是真的用于检查更新的规范,但我能想出的建议如下:

  1. 而不是使用checksum_agg的,串联校验为分隔字符串,字符串比较,沿行SELECT binary_checksum(*) + ',' FROM MyTable FOR XML PATH('')。要检查和存储的字符串要长得多,但误判比较的可能性要小得多。
  2. 不使用内置校验和例程,而是使用HASHBYTES计算8000字节块中的MD5校验和,并将结果与​​xor结合在一起。这会给你一个更有弹性的校验和,虽然仍然不是防弹的(即它仍然有可能获得错误的匹配,但是不太可能)。我将粘贴下面我写的HASHBYTES演示代码。
  3. 最后一个选项和绝对最后的手段是以XML格式实际存储表格表并进行比较。这确实是您绝对可以确定没有错误匹配的唯一方式,但不可扩展并涉及存储和比较大量数据。

每种方法(包括您开始使用的方法)都有优点和缺点,不同程度的数据大小和处理要求与准确性有关。根据您需要的准确度级别,使用适当的选项。获得100%准确性的唯一方法是存储所有表格数据。

或者,您可以在每个表中添加一个date_modified字段,该表在插入和更新触发器后使用GetDate()设置。你可以做SELECT COUNT(*) FROM #test WHERE date_modified > @date_last_checked。这是检查更新的更常见方式。这个缺点是不能跟踪删除。

另一种方法是创建一个带有table_name(VARCHAR)和is_modified(BIT)字段的修改表,其中包含您希望跟踪的每个表的一行。使用insert,update和delete触发器,针对相关表的标志被设置为True。当您运行计划时,将检查并重置is_modified标志(在同一事务中) - 沿着SELECT @is_modified = is_modified, is_modified = 0 FROM tblModified

的行 - 以下脚本生成三个结果集,每个结果集都与此响应中前面的编号列表相对应。我已经评论哪个输出与SELECT语句之前的哪个选项相对应。要查看输出是如何派生的,可以通过代码向后工作。

-- Create the test table and populate it 
CREATE TABLE #Test (
    f1 INT, 
    f2 INT 
) 
INSERT INTO #Test VALUES(1, 1) 
INSERT INTO #Test VALUES(2, 0) 
INSERT INTO #Test VALUES(2, 1) 

/******************* 
OPTION 1 
*******************/ 
SELECT CAST(binary_checksum(*) AS VARCHAR) + ',' FROM #test FOR XML PATH('') 

-- Declaration: Input and output MD5 checksums (@in and @out), input string (@input), and counter (@i) 
DECLARE @in VARBINARY(16), @out VARBINARY(16), @input VARCHAR(MAX), @i INT 

-- Initialize @input string as the XML dump of the table 
-- Use this as your comparison string if you choose to not use the MD5 checksum 
SET @input = (SELECT * FROM #Test FOR XML RAW) 

/******************* 
OPTION 3 
*******************/ 
SELECT @input 

-- Initialise counter and output MD5. 
SET @i = 1 
SET @out = 0x00000000000000000000000000000000 
WHILE @i <= LEN(@input) 
BEGIN 
    -- calculate MD5 for this batch 
    SET @in = HASHBYTES('MD5', SUBSTRING(@input, @i, CASE WHEN LEN(@input) - @i > 8000 THEN 8000 ELSE LEN(@input) - @i END)) 
    -- xor the results with the output 
    SET @out = CAST(CAST(SUBSTRING(@in, 1, 4) AS INT)^CAST(SUBSTRING(@out, 1, 4) AS INT) AS VARBINARY(4)) + 
     CAST(CAST(SUBSTRING(@in, 5, 4) AS INT)^CAST(SUBSTRING(@out, 5, 4) AS INT) AS VARBINARY(4)) + 
     CAST(CAST(SUBSTRING(@in, 9, 4) AS INT)^CAST(SUBSTRING(@out, 9, 4) AS INT) AS VARBINARY(4)) + 
     CAST(CAST(SUBSTRING(@in, 13, 4) AS INT)^CAST(SUBSTRING(@out, 13, 4) AS INT) AS VARBINARY(4)) 
    SET @i = @i + 8000 
END 

/******************* 
OPTION 2 
*******************/ 
SELECT @out 
+0

+1,以及以XML格式存储表格的想法。 –

+0

不幸的是,'hashbytes'不是SQL Server 2000中公认的函数名称。 –

+1

Aaah SQL2000。我错过了那一个!我在这里找到了用于T-SQL的MD实现:http://www.hackchina.com/en/r/184114/MD5.sql__html。对疏忽表示歉意。 – Peter

相关问题