如果你只是想記錄各列的變化在你的扳機,你可以嘗試unpivoting,可能與全加入一起。我們的想法是,你既UNPIVOT和inserted
然後deleted
加入他們放在桌上的鑰匙和含逆轉置名稱列,篩選出其中的值相同的行。
下面是該方法的示例說明。
首先,該表的定義:
CREATE TABLE TestTable (
ID int IDENTITY PRIMARY KEY,
Attr1 int,
Attr2 int,
Attr3 int
);
CREATE TABLE TestTableLog (
ID int IDENTITY PRIMARY KEY,
TableID int,
AttrName sysname,
OldValue int,
NewValue int,
Timestamp datetime DEFAULT GETDATE()
);
接下來,記錄變化的觸發。這一次會抓住所有的操作:插入,更新和刪除:
CREATE TRIGGER trTestTable ON TestTable
AFTER INSERT, UPDATE, DELETE
AS BEGIN
WITH inserted_unpivot AS (
SELECT
ID,
AttrName,
Value
FROM inserted i
UNPIVOT (Value FOR AttrName IN (Attr1, Attr2, Attr3)) u
),
deleted_unpivot AS (
SELECT
ID,
AttrName,
Value
FROM deleted d
UNPIVOT (Value FOR AttrName IN (Attr1, Attr2, Attr3)) u
)
INSERT INTO TestTableLog (TableID, AttrName, OldValue, NewValue)
SELECT
ISNULL(i.ID, d.ID),
ISNULL(i.AttrName, d.AttrName),
d.Value,
i.Value
FROM inserted_unpivot i
FULL JOIN deleted_unpivot d
ON i.ID = d.ID AND i.AttrName = d.AttrName
WHERE CASE i.Value WHEN d.Value THEN 0 ELSE 1 END = 1
END
現在,讓我們充滿TestTable的一些數據:
WHILE (SELECT COUNT(*) FROM TestTable) < 15
INSERT INTO TestTable
SELECT RAND() * 1000, RAND() * 1000, RAND() * 1000
;
這裏的後續變化之前,它的內容:
ID Attr1 Attr2 Attr3
----------- ----------- ----------- -----------
1 820 338 831
2 795 881 453
3 228 430 719
4 36 236 105
5 246 115 649
6 488 657 438
7 990 360 15
8 668 978 724
9 872 385 562
10 460 396 462
11 62 599 630
12 145 815 439
13 595 7 54
14 587 85 655
15 80 606 407
現在讓我們對內容進行一些修改:
UPDATE TestTable SET Attr2 = 35 WHERE ID = 3;
UPDATE TestTable SET Attr3 = 0 WHERE ID BETWEEN 6 AND 10;
INSERT INTO TestTable VALUES (1, 1, 1);
DELETE FROM TestTable WHERE ID = 14;
下面是我們在TestTable
事後得:
ID Attr1 Attr2 Attr3
----------- ----------- ----------- -----------
1 820 338 831
2 795 881 453
3 228 35 719
4 36 236 105
5 246 115 649
6 488 657 0
7 990 360 0
8 668 978 0
9 872 385 0
10 460 396 0
11 62 599 630
12 145 815 439
13 595 7 54
15 80 606 407
16 1 1 1
而這正是已被記錄:
ID TableID AttrName OldValue NewValue Timestamp
----------- ----------- ----------- ----------- ----------- -----------------------
1 3 Attr2 430 35 2011-08-22 20:12:19.217
2 10 Attr3 462 0 2011-08-22 20:12:19.227
3 9 Attr3 562 0 2011-08-22 20:12:19.227
4 8 Attr3 724 0 2011-08-22 20:12:19.227
5 7 Attr3 15 0 2011-08-22 20:12:19.227
6 6 Attr3 438 0 2011-08-22 20:12:19.227
7 16 Attr1 NULL 1 2011-08-22 20:12:19.227
8 16 Attr3 NULL 1 2011-08-22 20:12:19.227
9 16 Attr2 NULL 1 2011-08-22 20:12:19.227
10 14 Attr1 587 NULL 2011-08-22 20:12:19.230
11 14 Attr2 85 NULL 2011-08-22 20:12:19.230
12 14 Attr3 655 NULL 2011-08-22 20:12:19.230
的設置,當然,已經有所簡化。特別是,所有要記錄的主表的列都是相同的類型,因此不需要將數據轉換爲某種泛型來包含各種數據。但也許這就是你需要的。如果不是,我相信這可以爲實施最終解決方案提供良好的開端。
是不是應該結束前的腳本?我缺少一個「END」和「IF」語句 –
我不相信你可以調用Update(後一個命令)一樣,(通過在PARAM)或許COLUMNS_UPDATED()(http://msdn.microsoft。 com/en-us/library/ms186329(v = SQL.90).aspx)位掩碼可能更適合您的需要。 很可能有一個更好的方式做你想要完全做什麼。如果你發佈整個觸發器 –
,這將是有益的,這是我想要做的。當表更新時,我試圖將更新列的舊值和新值單獨存儲在表中。對於更新函數,我遵循http://msdn.microsoft.com/en-us/library/ms187326(v=SQL.100).aspx中的語法。但是我不知道我是否可以在函數中使用靜態變量。我可以直接使用列名。使用爲我的情況更新的列的問題是我必須檢查近25列,所以必須爲它們創建一個位掩碼。我也認爲可能有更好的方法來做到這一點。但還不知道。 ty – deepak