CHECKSUM_AGG似乎只是BINARY_CHECKSUM的結果相加爲所有行。儘管每一行都改變了,但兩個校驗和的總和還沒有(即17 + 32 = 16 + 33)。這是不是真的用於檢查更新的規範,但我能想出的建議如下:
- 而不是使用
checksum_agg
的,串聯校驗爲分隔字符串,字符串比較,沿行SELECT binary_checksum(*) + ',' FROM MyTable FOR XML PATH('')
。要檢查和存儲的字符串要長得多,但誤判比較的可能性要小得多。
- 不使用內置校驗和例程,而是使用HASHBYTES計算8000字節塊中的MD5校驗和,並將結果與xor結合在一起。這會給你一個更有彈性的校驗和,雖然仍然不是防彈的(即它仍然有可能獲得錯誤的匹配,但是不太可能)。我將粘貼下面我寫的HASHBYTES演示代碼。
- 最後一個選項和絕對最後的手段是以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
相關問題:http://stackoverflow.com/questions/7362312/is-there-a-function-feature-in-sql-server-to-determine-if-a-table-has-any -recen –
嘗試在您的基表中添加'timestamp' /'rowversion'列。 – wqw