我應該在審計表中創建多大的列來儲存 COLUMNS_UPDATED() 的輸出?
我有一個儲存過程,它在將表名傳遞到其中時創建一個互補的觸發器和審計表。SP 過濾掉所有計算的列和其他阻止您執行 ‘SELECT *’ 進行審計的內容,然後編寫一個觸發器,將這些特定列插入
table
到table_audit
onDELETE
//以及一些審計數據,例如INSERT
和。這很少使用,但通常適用於要求它的客戶。UPDATE``HOST_NAME()``COLUMNS_UPDATED()
在最近一輪測試中,我被要求在測試數據庫上設置審計。這導致我們主表中的插入失敗,因為“字元串或二進制數據將被截斷”,經過調查,我發現
COLUMNS_UPDATED()
儲存結果的列是問題所在。列的定義是:
[UpdateColumns] [varbinary](16) NULL
將定義更改為此已使一切恢復正常:
[UpdateColumns] [varbinary](24) NULL
但是,這突出顯示的是,我不了解表中的列數(在本例中為 95,其中計算了 7 個)與
COLUMNS_UPDATED()
. 我認為[varbinary](16)
= 128 位,這對於 95 列來說應該綽綽有餘。所以我的問題是:什麼是關係?
x
第二個問題:在建構觸發器時,我是否可以輕鬆地從將被審計的列數中得出一個值,[UpdateColumns] [varbinary](x)
或者我是否最好設置x
為更大的數字?
COLUMNS_UPDATED()
讓我從一個問題開始:如果您不了解如何讀取它,為什麼要儲存它的值?你可以從儲存它中獲得什麼可能的價值?但是要回答您的問題,請為目前在表中或以前在表中的
COLUMNS_UPDATED()
每列返回一位。COLUMNS_UPDATED()
是基於column_id
您可以從中檢索的sys.columns
。每個新列都會在其中分配一個遞增的值,有點像一個IDENTITY
值,但是為每個表重新啟動。因此,如果您刪除並重新添加列,舊值將不會被重用;相反,您將有差距。以下程式碼片段展示了這一點:CREATE TABLE dbo.tx(c1 INT, c2 INT, c3 INT); ALTER TABLE dbo.tx DROP COLUMN c2; ALTER TABLE dbo.tx ADD c4 INT; SELECT name, column_id FROM sys.columns WHERE object_id = OBJECT_ID('dbo.tx');
這是此查詢的輸出:
|name | column_id| +-----+----------+ |c1 | 1 | |c3 | 3 | |c4 | 4 |
這有一個很大的優勢,即您不必更改正在尋找特定列的觸發程式碼。然而,它有一個巨大的缺點,那就是一切都變得模糊不清。此外,您可能無法編寫表和触發器的腳本並在測試數據庫中重新創建它們,因為那裡的
column_id
值可能不同。因此,要弄清楚您需要多少位,只需查看
MAX(column_id)
表的值即可。另一種方法是使用
UPDATE()
函式,該函式採用單個列名並返回一個值,指示該列是否已更改。這兩個函式都有一個額外的缺點,即它們實際上並不比較值;他們只是報告該列已被引用,即使該列中的值保持不變。在您的情況下,您似乎正在嘗試擷取實際的數據更改。看看變更數據擷取- 無需重新發明輪子。