ट्रिगर्स मुश्किल हैं और जब आप एक बना रहे हैं तो आपको थोक में सोचने की आवश्यकता है। प्रत्येक अद्यतन विवरण के लिए एक बार एक ट्रिगर आग लगती है। यदि अद्यतन अद्यतन कई पंक्तियों को अद्यतन करता है, तो ट्रिगर अभी भी एक बार आग लग जाएगा। UPDATE() फ़ंक्शन कॉलम के लिए सत्य लौटाता है जब उस कॉलम को UPDATE कथन में शामिल किया जाता है। यह फ़ंक्शन ट्रिगर की दक्षता में सुधार करने में मदद करता है जिससे आप SQL तर्क को विभाजित कर सकते हैं जब उस कॉलम को अद्यतन कथन में भी शामिल नहीं किया जाता है। यह आपको नहीं बताता है कि किसी दिए गए पंक्ति में कॉलम के लिए मान बदल गया है या नहीं।
यहां एक नमूना तालिका है ...
CREATE TABLE tblSample
(
SampleID INT PRIMARY KEY,
SampleName VARCHAR(10),
SampleNameLastChangedDateTime DATETIME,
Parent_SampleID INT
)
निम्नलिखित एसक्यूएल इस तालिका के खिलाफ इस्तेमाल किया गया था:
UPDATE tblSample SET SampleName = 'hello'
..और एक इसके बाद सम्मिलित करें, अद्यतन ट्रिगर, इस विशेष प्रभाव में था SQL कथन हमेशा निम्नानुसार अद्यतन कार्य का मूल्यांकन करेगा ...
IF UPDATE(SampleName) --aways evaluates to TRUE
IF UPDATE(SampleID) --aways evaluates to FALSE
IF UPDATE(Parent_SampleID) --aways evaluates to FALSE
ध्यान दें कि अद्यतन (SampleName) हमेशा इस SQL विवरण के लिए सच हो सकता है, क्या SampleName मूल्यों से पहले थे की परवाह किए बिना। यह सच हो जाता है क्योंकि अद्यतन विवरण में उस खंड के एसईटी अनुभाग में कॉलम नमूना नाम शामिल है और यह मान नहीं है कि मूल्य पहले या बाद में क्या था। अद्यतन() फ़ंक्शन निर्धारित नहीं करेगा कि मान बदल गए हैं या नहीं। यदि आप मानों को बदलते हैं या नहीं, तो आप एसक्यूएल का उपयोग करने और डालने और हटाए गए पंक्तियों की तुलना करने के लिए कार्रवाइयां करना चाहते हैं।
यहाँ सिंक में एक अंतिम अपडेट स्तंभ रखने के लिए एक दृष्टिकोण है:
--/*
IF OBJECT_ID('dbo.tgr_tblSample_InsertUpdate', 'TR') IS NOT NULL
DROP TRIGGER dbo.tgr_tblSample_InsertUpdate
GO
--*/
CREATE TRIGGER dbo.tgr_tblSample_InsertUpdate ON dbo.tblSample
AFTER INSERT, UPDATE
AS
BEGIN --Trigger
IF UPDATE(SampleName)
BEGIN
UPDATE tblSample SET
SampleNameLastChangedDateTime = CURRENT_TIMESTAMP
WHERE
SampleID IN (SELECT Inserted.SampleID
FROM Inserted LEFT JOIN Deleted ON Inserted.SampleID = Deleted.SampleID
WHERE COALESCE(Inserted.SampleName, '') <> COALESCE(Deleted.SampleName, ''))
END
END --Trigger
तर्क निर्धारित करने के लिए करता है, तो पंक्ति अद्यतन किया गया था कहां खंड में ऊपर है। यह वास्तविक चेक है जो आपको करने की ज़रूरत है। मेरा तर्क कुल मूल्यों और INSERTS को संभालने के लिए COALESCE का उपयोग कर रहा है।
...
WHERE
SampleID IN (SELECT Inserted.SampleID
FROM Inserted LEFT JOIN Deleted ON Inserted.SampleID = Deleted.SampleID
WHERE COALESCE(Inserted.SampleName, '') <> COALESCE(Deleted.SampleName, ''))
ध्यान दें कि यदि अद्यतन() की जांच जब SampleName स्तंभ नहीं अद्यतन किया जा रहा है के लिए ट्रिगर की दक्षता में सुधार करने में मदद करने के लिए इस्तेमाल किया जाता है। यदि किसी SQL कथन ने उदाहरण के लिए Parent_SampleID कॉलम को अद्यतन किया है, तो अगर अद्यतन (नमूना नाम) चेक उस IF कथन में अधिक जटिल तर्क के आसपास सेडस्टेप में मदद करेगा, जब इसे चलाने की आवश्यकता नहीं है। UPDATE() का उपयोग करने पर विचार करें जब यह उचित है लेकिन गलत कारण के लिए नहीं।
यह भी महसूस करें कि आपके आर्किटेक्चर के आधार पर, अद्यतन फ़ंक्शन का आपके पास कोई उपयोग नहीं हो सकता है। यदि आपका कोड आर्किटेक्चर एक मध्यम-स्तरीय का उपयोग करता है जो किसी ऑब्जेक्ट को सहेजते समय व्यवसाय ऑब्जेक्ट में मानों के साथ तालिका के किसी पंक्ति में सभी कॉलम अपडेट करता है, तो एक ट्रिगर में UPDATE() फ़ंक्शन बेकार हो जाता है। उस स्थिति में, आपका कोड हमेशा मध्य-स्तर से जारी किए गए प्रत्येक अद्यतन विवरण के साथ सभी कॉलम अपडेट कर सकता है। यह मामला होने पर, अद्यतन (कॉलमनाम) फ़ंक्शन हमेशा सत्य के मूल्यांकन का मूल्यांकन करेगा जब आपके व्यवसाय की वस्तुएं सहेजी जाती हैं क्योंकि सभी कॉलम नाम हमेशा अपडेट स्टेटमेंट में शामिल होते हैं। उस स्थिति में, ट्रिगर में UPDATE() का उपयोग करना उपयोगी नहीं होगा और अधिकांश समय के लिए उस ट्रिगर में अतिरिक्त ओवरहेड होगा।
INSERT INTO tblSample
(
SampleID,
SampleName
)
SELECT 1, 'One'
UNION SELECT 2, 'Two'
UNION SELECT 3, 'Three'
GO
SELECT SampleID, SampleName, SampleNameLastChangedDateTime FROM tblSample
/*
SampleID SampleName SampleNameLastChangedDateTime
----------- ---------- -----------------------------
1 One 2010-10-27 14:52:42.567
2 Two 2010-10-27 14:52:42.567
3 Three 2010-10-27 14:52:42.567
*/
GO
INSERT INTO tblSample
(
SampleID,
SampleName
)
SELECT 4, 'Foo'
UNION SELECT 5, 'Five'
GO
SELECT SampleID, SampleName, SampleNameLastChangedDateTime FROM tblSample
/*
SampleID SampleName SampleNameLastChangedDateTime
----------- ---------- -----------------------------
1 One 2010-10-27 14:52:42.567
2 Two 2010-10-27 14:52:42.567
3 Three 2010-10-27 14:52:42.567
4 Foo 2010-10-27 14:52:42.587
5 Five 2010-10-27 14:52:42.587
*/
GO
UPDATE tblSample SET SampleName = 'Foo'
SELECT SampleID, SampleName, SampleNameLastChangedDateTime FROM tblSample
/*
SampleID SampleName SampleNameLastChangedDateTime
----------- ---------- -----------------------------
1 Foo 2010-10-27 14:52:42.657
2 Foo 2010-10-27 14:52:42.657
3 Foo 2010-10-27 14:52:42.657
4 Foo 2010-10-27 14:52:42.587
5 Foo 2010-10-27 14:52:42.657
*/
GO
UPDATE tblSample SET SampleName = 'Not Prime' WHERE SampleID IN (1,4)
SELECT SampleID, SampleName, SampleNameLastChangedDateTime FROM tblSample
/*
SampleID SampleName SampleNameLastChangedDateTime
----------- ---------- -----------------------------
1 Not Prime 2010-10-27 14:52:42.680
2 Foo 2010-10-27 14:52:42.657
3 Foo 2010-10-27 14:52:42.657
4 Not Prime 2010-10-27 14:52:42.680
5 Foo 2010-10-27 14:52:42.657
*/
--Clean up...
DROP TRIGGER dbo.tgr_tblSample_InsertUpdate
DROP TABLE tblSample
उपयोगकर्ता GBN निम्नलिखित सुझाव दिया था:
IF EXISTS (
SELECT
*
FROM
INSERTED I
JOIN
DELETED D ON I.key = D.key
WHERE
D.valuecol <> I.valuecol --watch for NULLs!
)
blah
एक IF (का उपयोग करने का GBN के सुझाव मौजूद है (... खंड और डाल
यहाँ कुछ एसक्यूएल ऊपर ट्रिगर के साथ खेलने के लिए है अगर I पंक्ति में मौजूद पंक्तियां मौजूद हैं तो तर्क बदल सकता है। यह दृष्टिकोण ट्रिगर में शामिल सभी पंक्तियों के लिए आग लग जाएगा, भले ही केवल कुछ पंक्तियों को वास्तव में बदला गया हो (जो आपके समाधान के लिए उपयुक्त हो सकता है, लेकिन हो सकता है उपयुक्त अगर आप केवल कुछ करना चाहते हैं पंक्तियों को हिंग करना जहां मूल्य बदल गए।) यदि आपको पंक्तियों में कुछ करने की आवश्यकता है जहां वास्तविक परिवर्तन हुआ है, तो आपको प्रदान किए गए अपने एसक्यूएल में अलग-अलग तर्क की आवश्यकता है।
ऊपर दिए गए मेरे उदाहरणों में, जब अद्यतन tblSample SET नमूना नाम = 'फू' कथन जारी किया गया है और चौथी पंक्ति पहले से ही 'foo' है, तो "अंतिम बदले गए डेटाटाइम" कॉलम को अपडेट करने के लिए जीबीएन के दृष्टिकोण का उपयोग करके चौथी पंक्ति भी अपडेट होगी , जो इस मामले में उपयुक्त नहीं होगा।
धन्यवाद। परिवर्तन खोजने के लिए SQL सर्वर से उपलब्ध कोई अन्य विकल्प? या मुझे परिवर्तन खोजने के लिए प्रत्येक पंक्ति के माध्यम से लूप करना होगा? –
बस कुंजी पर 2 टेबल में शामिल हों, कोई loosp – gbn
आवश्यक है जिसे 'हटाया गया' और '** डाला ** ** वर्चुअल टेबल होना चाहिए, है ना? मैंने कभी "अद्यतन" वर्चुअल टेबल –