यदि आप केवल अपने ट्रिगर में अलग-अलग कॉलम के परिवर्तनों को लॉग करना चाहते हैं, तो आप संभवतः पूर्ण जुड़ाव के संयोजन के साथ, अनपिवट करने का प्रयास कर सकते हैं। विचार यह है कि, आप दोनों को अनपिवट करें 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
आइए अब टेस्टटेबल को कुछ डेटा से भरें:
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
बेशक, सेटअप को कुछ हद तक सरल बनाया गया है। विशेष रूप से, सभी मुख्य तालिका के कॉलम जिन्हें लॉग किया जाना है, एक ही प्रकार के हैं, और इसलिए विभिन्न प्रकार के डेटा को अपनाने के लिए डेटा को कुछ सामान्य प्रकार में बदलने की आवश्यकता नहीं है। लेकिन शायद आपको बस यही चाहिए। और यदि नहीं, तो मेरा मानना है कि यह अंतिम समाधान को लागू करने के लिए एक अच्छी शुरुआत प्रदान कर सकता है।