2009-03-02 33 views
1

我試圖通過向我的表添加觸發器並將行插入到我的審計表中來執行審計歷史記錄。我有一個存儲過程,使插入更容易一些,因爲它節省了代碼;我不必寫出整個插入語句,而是使用我想要插入的列的幾個參數來執行存儲過程。在觸發器中審計每個插入的行

我不知道如何爲「插入」表中的每一行執行存儲過程。我想也許我需要使用遊標,但我不確定。我以前從未使用過光標。

由於這是一個審計,我將需要比較舊的每列的值,以查看它是否發生了變化。如果確實發生了變化,我將執行向我的審計表添加一行的存儲過程。

有什麼想法?

+0

您正在使用什麼版本的SQL Server?如果SQL 2K8中有一些內置的審計工具必須比您構建的維護更好。 – JohnFx 2009-03-18 14:47:51

回答

1

如果您的數據庫需要擴展一些用戶,這將變得非常昂貴。我會建議查看第三方數據庫審計工具。

3

我會交易空間的時間,而不是做比較。只需在插入/更新時將新值推送到審計表。磁盤很便宜。

此外,我不確定存儲過程購買了什麼。你不能做喜歡的事,在觸發簡單:

insert into dbo.mytable_audit 
    (select *, getdate(), getdate(), 'create' from inserted) 

當扳機上插入運行,要添加創建時間,最後更新時間和修改類型字段。對於更新,這是一個有點tricker因爲你需要提供命名參數爲創建的時間不應該被更新

insert into dbo.mytable_audit (col1, col2, ...., last_updated, modification) 
    (select *, getdate(), 'update' from inserted) 

而且,你打算只審覈成功或失敗呢?如果你想審覈失敗,你會需要觸發器以外的東西,因爲如果事務回滾,觸發器將不會運行 - 而且如果觸發器先運行,你將不具有事務的狀態。

我實際上已將我的審計移至我的數據訪問層,並在代碼中執行此操作。它使成功和失敗審計變得更容易,並且(使用反射)很容易將字段複製到審計對象。它允許我做的另一件事是給用戶上下文,因爲我沒有給數據庫實際的用戶權限,並使用服務帳戶運行所有查詢。

+0

我同意。磁盤很便宜。每次只保存新的(插入的)值。舊值將位於審計表的前一行中。 – MikeW 2009-03-02 23:53:25

1

已經有一個內置函數UPDATE()它告訴你列是否已經改變(但它是在整個插入行集上)。

你可以看看Paul Nielsen's AutoAudit triggers中的一些技術,這些技術是代碼生成的。

它能做什麼是同時檢查:

IF UPDATE(<column_name>) 
INSERT Audit (...) 
SELECT ... 
FROM Inserted 
JOIN Deleted 
    ON Inserted.KeyField = Deleted.KeyField -- (AutoAudit does not support multi-column primary keys, but the technique can be done manually) 
AND NOT (Inserted.<column_name> = Deleted.<column_name> OR COALESCE(Inserted.<column_name>, Deleted.<column_name>) IS NULL) 

但審計每一列的變化作爲一個單獨的行。我使用它來審計配置表的更改。我目前沒有用它來審計繁重的變更表。 (但是在我設計的大多數事務處理系統中,重活動表上的行通常是不可變的,您沒有太多的UPDATE s,只是很多INSERT s - 所以您甚至不需要這種審計) 。例如,訂單或分類帳條目永遠不會改變,購物車是一次性的 - 也不會有這種審計。在像客戶這樣的低交易量表上,您可以使用這種審計。

1

Jeff, 我同意Zodeus ..一個好的選擇是使用第三個工具。 我已經使用審計數據庫(免費)網絡工具,生成審計觸發器(你不需要寫一行TSQL代碼)

另一個好的工具是Apex SQL審計,但它不是免費的。

我希望這可以幫助你, F.奧尼爾

+0

網站是www.auditdatabase.com – 2009-03-30 04:49:12