update - 檢查對SQL Server表的更改嗎?




sql語法範例 (6)

不幸的是,CHECKSUM不能正常工作來檢測變化 。 這只是一個原始校驗和,沒有CRC計算。 因此,您不能使用它來檢測所有更改,例如對稱更改導致相同的CHECKSUM!

例如, 帶有CHECKSUM_AGG(BINARY_CHECKSUM(*))的解決方案為所有3個不同內容的表提供始終為0的解決方案!


SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM 
(
  SELECT 1 as numA, 1 as numB
  UNION ALL
  SELECT 1 as numA, 1 as numB
)  q
-- delivers 0!

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM ( SELECT 1 as numA, 2 as numB UNION ALL SELECT 1 as numA, 2 as numB ) q -- delivers 0!

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM ( SELECT 0 as numA, 0 as numB UNION ALL SELECT 0 as numA, 0 as numB ) q -- delivers 0!

如何在不使用觸發器或以任何方式修改數據庫結構的情況下監視SQL Server數據庫對錶的更改? 我的首選編程環境是.NET和C#。

我希望能夠支持任何SQL Server 2000 SP4或更新版本。 我的應用程序是另一家公司產品的螺栓式數據可視化。 我們的客戶群有數千人,因此我不希望在每次安裝時都要求我們修改第三方供應商的表格。

通過“對錶格的更改”,我的意思是對錶格數據的更改,而不是對錶格結構的更改。

最終,我希望更改在我的應用程序中觸發事件,而不必每隔一段時間檢查一次更改。

根據我的要求(無觸發器或架構修改,SQL Server 2000和2005),最好的行動方案似乎是在T-SQL使用BINARY_CHECKSUM函數。 我打算實施的方式是這樣的:

每X秒運行以下查詢:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*))
FROM sample_table
WITH (NOLOCK);

並將其與儲值進行比較。 如果值已更改,請使用查詢逐行瀏覽表:

SELECT row_id, BINARY_CHECKSUM(*)
FROM sample_table
WITH (NOLOCK);

並將返回的校驗和與存儲的值進行比較。


不幸的是,我不認為在SQL2000中有這樣一個乾淨的方法。 如果您將需求縮小到SQL Server 2005(及更高版本),那麼您已經開始運營。 您可以在System.Data.SqlClient使用SQLDependency類。 請參閱SQL Server中的查詢通知(ADO.NET)


您需要多久檢查一次更改以及數據庫中的表有多大(按行大小而定)? 如果使用John建議的CHECKSUM_AGG(BINARY_CHECKSUM(*))方法,它將掃描指定表的每一行。 NOLOCK提示有幫助,但是在大型數據庫上,您仍然會觸及每一行。 您還需要為每一行存儲校驗和,以便您告訴一個已更改。

你有沒有考慮過從另一個角度來看待這個問題? 如果你不想修改模式來添加觸發器(這是有道理的,它不是你的數據庫),你是否考慮過與創建數據庫的應用程序供應商合作?

他們可以實現一個API,該API提供了一種通知配件應用程序數據已更改的機制。 它可以像寫入通知表一樣簡單,該通知表列出哪些表和哪一行被修改。 這可以通過觸發器或應用程序代碼來實現。 從你身邊,ti無所謂,你唯一的擔心就是定期掃描通知表。 數據庫上的性能將遠遠低於掃描每一行的變化。

最困難的部分是讓應用程序供應商說服這個功能。 由於這可以通過觸發器完全通過SQL進行處理,因此您可以通過編寫和測試觸發器然後將代碼提供給應用程序供應商來完成大部分工作。 通過讓供應商支持觸發器,它可以防止添加觸發器時無意中替換供應商提供的觸發器的情況。


有一個以給定間隔運行的DTS作業(或由Windows服務啟動的作業)。 每次運行它時,都會使用系統INFORMATION_SCHEMA表獲取有關給定表的INFORMATION_SCHEMA ,並將這些數據記錄在數據存儲庫中。 將有關表格結構的數據與前一次返回的數據進行比較。 如果不同,那麼你知道結構已經改變。

示例查詢返回有關表ABC中所有列的信息(理想情況下,只列出您想要的INFORMATION_SCHEMA表中的列,而不是像以下那樣使用* select **):

select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'ABC'

根據您如何定義“對錶格的更改”,您可以監視不同的列和INFORMATION_SCHEMA視圖。


瘋狂的猜測在這裡:如果你不想修改第三方的表格,你可以創建一個視圖,然後在該視圖上放置一個觸發器?


看看CHECKSUM命令:

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM sample_table WITH (NOLOCK);

只要表格內容沒有改變,每次運行它都會返回相同的編號。 有關更多信息,請參閱我的文章:

CHECKSUM

在更改表格時,我使用它來重建緩存依賴關係:
ASP.NET 1.1數據庫緩存依賴項(不帶觸發器)





rdbms