Sql-Server-2005

我應該在審計表中創建多大的列來儲存 COLUMNS_UPDATED() 的輸出?

  • August 23, 2013

我有一個儲存過程,它在將表名傳遞到其中時創建一個互補的觸發器和審計表。SP 過濾掉所有計算的列和其他阻止您執行 ‘SELECT *’ 進行審計的內容,然後編寫一個觸發器,將這些特定列插入tabletable_auditon DELETE//以及一些審計數據,例如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()函式,該函式採用單個列名並返回一個值,指示該列是否已更改。這兩個函式都有一個額外的缺點,即它們實際上並不比較值;他們只是報告該列已被引用,即使該列中的值保持不變。

在您的情況下,您似乎正在嘗試擷取實際的數據更改。看看變更數據擷取- 無需重新發​​明輪子。

引用自:https://dba.stackexchange.com/questions/48621