क्या डिलीट ट्रिगर पर जानकारी को पास करने का कोई तरीका है जिससे यह पता चल सके कि रिकॉर्ड को किसने डिलीट किया है?
हाँ: एक बहुत ही शांत (और उपयोग की सुविधा के तहत) का उपयोग करके कहा जाता है CONTEXT_INFO
। यह अनिवार्य रूप से सत्र मेमोरी है जो सभी स्कोपों में मौजूद है और लेनदेन से बाध्य नहीं है। इसका उपयोग जानकारी (कोई भी जानकारी - अच्छी तरह से, जो कि सीमित स्थान में फिट होती है) को ट्रिगर करने के लिए और साथ ही उप-प्रोक / एक्सईसी कॉल के बीच आगे-पीछे हो सकता है। और मैंने इसका उपयोग इसी सटीक स्थिति के लिए पहले भी किया है।
यह कैसे काम करता है यह देखने के लिए निम्नलिखित के साथ परीक्षण करें। ध्यान दें कि मैं करने से CHAR(128)
पहले परिवर्तित कर रहा हूँ CONVERT(VARBINARY(128), ..
। इससे वापस करने के लिए परिवर्तित करने के लिए बनाने के लिए बल खाली-गद्दी के लिए है VARCHAR
जब यह से बाहर हो रही CONTEXT_INFO()
के बाद से VARBINARY(128)
साथ सही-गद्देदार है 0x00
रों।
SELECT CONTEXT_INFO();
-- Initially = NULL
DECLARE @EncodedUser VARBINARY(128);
SET @EncodedUser = CONVERT(VARBINARY(128),
CONVERT(CHAR(128), 'I deleted ALL your records! HA HA!')
);
SET CONTEXT_INFO @EncodedUser;
SELECT CONTEXT_INFO() AS [RawContextInfo],
RTRIM(CONVERT(VARCHAR(128), CONTEXT_INFO())) AS [DecodedUser];
परिणाम:
0x492064656C6574656420414C4C20796F7572207265636F7264732120484120484121202020202020...
I deleted ALL your records! HA HA!
यह सब एक साथ डालें:
एप्लिकेशन को एक "डिलीट" संग्रहीत कार्यविधि को कॉल करना चाहिए जो उपयोगकर्ता नाम (या जो भी) पास करता है जो रिकॉर्ड को हटा रहा है। मुझे लगता है कि यह पहले से ही इस्तेमाल किया जा रहा मॉडल है क्योंकि यह लगता है जैसे आप पहले से ही सम्मिलित और अपडेट संचालन पर नज़र रख रहे हैं।
"हटाएं" संग्रहीत कार्यविधि करता है:
DECLARE @EncodedUser VARBINARY(128);
SET @EncodedUser = CONVERT(VARBINARY(128),
CONVERT(CHAR(128), @UserName)
);
SET CONTEXT_INFO @EncodedUser;
-- DELETE STUFF HERE
ऑडिट ट्रिगर करता है:
-- Set the INT value in LEFT (currently 50) to the max size of [UserWhoMadeChanges]
INSERT INTO AuditTable (IdOfRecordedAffected, UserWhoMadeChanges)
SELECT del.ID, COALESCE(
LEFT(RTRIM(CONVERT(VARCHAR(128), CONTEXT_INFO())), 50),
'<unknown>')
FROM DELETED del;
कृपया ध्यान दें कि, जैसा कि @SeanGallardy ने एक टिप्पणी में बताया है, अन्य प्रक्रियाओं और / या तदर्थ प्रश्नों के कारण इस तालिका से रिकॉर्ड हटा रहे हैं, यह संभव है कि या तो:
CONTEXT_INFO
सेट नहीं किया गया है और अभी भी है NULL
:
इस कारण से मैंने मान को डिफ़ॉल्ट INSERT INTO AuditTable
करने के लिए ऊपर का अद्यतन किया है COALESCE
। या, यदि आप एक डिफ़ॉल्ट नहीं चाहते हैं और एक नाम की आवश्यकता है, तो आप कुछ ऐसा कर सकते हैं:
DECLARE @UserName VARCHAR(50); -- set to the size of AuditTable.[UserWhoMadeChanges]
SET @UserName = LEFT(RTRIM(CONVERT(VARCHAR(128), CONTEXT_INFO())), 50);
IF (@UserName IS NULL)
BEGIN
ROLLBACK TRAN; -- cancel the DELETE operation
RAISERROR('Please set UserName via "SET CONTEXT_INFO.." and try again.', 16 ,1);
END;
-- use @UserName in the INSERT...SELECT
CONTEXT_INFO
उस मान पर सेट किया गया है जो मान्य उपयोगकर्ता नाम नहीं है, और इसलिए यह AuditTable.[UserWhoMadeChanges]
फ़ील्ड के आकार से अधिक हो सकता है :
इस कारण से मैंने यह LEFT
सुनिश्चित करने के लिए एक फ़ंक्शन जोड़ा कि जो कुछ भी पकड़ा गया है CONTEXT_INFO
वह टूट नहीं जाएगा INSERT
। जैसा कि कोड में उल्लेख किया गया है, आपको बस क्षेत्र 50
के वास्तविक आकार को निर्धारित करने की आवश्यकता है UserWhoMadeChanges
।
SQL सर्वर 2016 और नए के लिए अद्यतन
SQL सर्वर 2016 ने इस प्रति-सत्र मेमोरी का एक बेहतर संस्करण जोड़ा: सत्र संदर्भ। नया सत्र संदर्भ मूल रूप से "की" प्रकार sysname
(यानी NVARCHAR(128)
) और "मूल्य" होने के साथ की-वैल्यू जोड़े का हैश टेबल है SQL_VARIANT
। अर्थ:
- अन्य उपयोगों के साथ संघर्ष की संभावना कम होने के कारण अब मूल्यों का अलगाव होता है
- आप विभिन्न प्रकारों को संग्रहित कर सकते हैं, मूल्य के माध्यम से वापस जाने पर विषम व्यवहार के बारे में चिंता करने की आवश्यकता नहीं है
CONTEXT_INFO()
(विवरण के लिए, कृपया मेरी पोस्ट देखें: क्यों नहीं CONTEXT_INFO () SET CONTEXT_INFO द्वारा सटीक मान सेट करें? )
- आपको बहुत अधिक स्थान मिलता है : 8000 बाइट्स अधिकतम "मूल्य", सभी कुंजियों पर कुल 256kb तक (128 बाइट्स अधिकतम की तुलना में
CONTEXT_INFO
)
जानकारी के लिए, कृपया निम्नलिखित दस्तावेज पृष्ठ देखें:
SUSER_SNAME()
जो रिकॉर्ड नष्ट करने के लिए महत्वपूर्ण है।