टी-एसक्यूएल ट्रिगर कैसे होता है जो केवल वास्तविक परिवर्तनों पर फायर करता है?


9

मेरे पास UPDATE और INSERT पर एक टेबल ट्रिगर है जो एक पंक्ति को दूसरी तालिका में जोड़ता है। यह केवल एक पंक्ति जोड़ने की जरूरत है अगर चार कॉलमों में से एक को बदल दिया जाए। मैंने परिवर्तनों के परीक्षण के लिए IF UPDATE (कॉल) का उपयोग करने की कोशिश की, लेकिन इसमें एक अंधा स्थान है। यह केवल परीक्षण करता है कि कुछ मूल्य आया था। मुझे गहराई में जाने की जरूरत है, मुझे एक सच्चे बदलाव को देखने के लिए पुराने और नए मूल्यों की तुलना करने की आवश्यकता है। इसमें INSERT और UPDATE दोनों के साथ काम करना होता है।

एक अद्यतन के मामले में यह आसान है क्योंकि सम्मिलित और हटाए गए तालिकाओं में वे मान हैं जो मैं ट्रिगर के भीतर तुलना कर सकता हूं। हालाँकि, INSERT के लिए केवल सम्मिलित तालिका में मान हैं। क्योंकि मुझे एक ही ट्रिगर में यह सब चाहिए, मैं उस INSERT केस को कैसे संभालूँ?

यहां उस ट्रिगर की स्क्रिप्ट दी गई है जिसे मैं संशोधित करना चाहता हूं:

ALTER TRIGGER [dbo].[trATPerson_alter] 
   ON  [mydb].[dbo].[AT_Person]
   AFTER INSERT,UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    -- Not all updates require a push
    IF (UPDATE([First_Name]) OR UPDATE([Last_Name]) OR UPDATE([JobCode]) OR UPDATE([Inactive]))
    BEGIN
        INSERT INTO [mydb].[dbo].[AT_Person_To_Push] (
                [Facility],
                [VendorID],
                [Person_code],
                [First_Name],
                [Last_Name],
                [JobCode],
                [Alink],
                [Inactive]
            )
        SELECT  [Facility],
                [VendorID],
                [Person_code],
                [First_Name],
                [Last_Name],
                [JobCode],
                [Alink],
                [Inactive]
        FROM inserted 
    END
END

2
"IF UPDATE (<कॉलम>)" के उपयोग पर एक त्वरित शब्द। यह सच है कि अगर DML कॉलम के लिए कोई मूल्य निर्दिष्ट करता है, भले ही मूल्य वास्तव में बदल गया हो या नहीं।
जोनाथन फाइट

जवाबों:


18

आप INSERT और UPDATE दोनों को EXCEPT सेट ऑपरेटर के साथ संभाल सकते हैं। EXISTS केवल TRUE का मूल्यांकन करेगा, अगर यह सिर्फ एक INSERT है, या यदि यह इन कॉलमों में से किसी एक के लिए विभिन्न मानों के साथ अद्यतन है।

IF EXISTS (
           SELECT First_Name, Last_Name, JobCoe, Inactive FROM inserted
           EXCEPT
           SELECT First_Name, Last_Name, JobCoe, Inactive FROM deleted
          )
BEGIN...

विभिन्न स्तंभ-अद्यतन कार्यों को देखने की तुलना में यह बहुत अधिक सुरुचिपूर्ण है। हमने कुछ फ्रंट-एंड कोड के साथ उन्हें केवल बदले हुए मूल्यों (बहुत तकलीफ के बाद) में भेजा। EXCEPT का उपयोग करने से बहुत कुछ समझ में आता है।
पीटर शोट

2
यह उन मामलों में काम नहीं करता है जहां एक अद्यतन में 2 पंक्तियों को "स्वैप" किया जाता है। अगर हमारे पास दो जॉन स्मिथ हैं जिन्हें अपने जॉबकोड को अपडेट करने की आवश्यकता है (पहले जॉन 1 से 2 तक; दूसरा जॉन 2 से 1) - यह कहेंगे कि कोई अपडेट नहीं हुआ है।
स्टीवन Hibble

2
@StevenHibble - जबकि संभव है कि ऐसा कैसे संभव है? उपरोक्त मामलों में PK कॉलम को शामिल करके उस मामले को आसानी से हल किया जा सकता है।
चाड

1
मैं कहूंगा कि संभावना डेटा स्रोत और खराब डेटा प्रविष्टि की संभावना पर निर्भर करती है। "उफ़, गलत जॉन स्मिथ ..." ऐसा नहीं लगता कि ऐसा कभी नहीं होगा। किसी भी मामले में, यह एक बहु-पंक्ति अद्यतन के अन्य आधे हिस्से को संबोधित नहीं करता है: आप केवल उन पंक्तियों को सम्मिलित करना सुनिश्चित करते हैं जो परिवर्तन करते हैं? यह EXISTSजाँचता है कि कोई पंक्ति बदल गई। यदि आप प्रश्न से इन्सर्ट रखते हैं, तो आप सभी अद्यतन पंक्तियों को लॉग करेंगे जब केवल एक सार्थक तरीके से परिवर्तन होता है।
स्टीवन हैबल

2

यदि कोई अपडेट कई पंक्तियों को प्रभावित कर सकता है, तो आपको दो चीजों से बचाव करना होगा:

  1. हम उन अपडेट्स पर विचार करना चाहते हैं जो समान पंक्तियों के बीच मूल्यों को स्वैप करते हैं। यदि दो जॉन स्मिथ हैं, जिन्हें अपने जॉबकोड को अपडेट करने की आवश्यकता है (पहले जॉन 1 से 2 तक; दूसरा जॉन 2 से 1), तो हमें यह कहने के लिए सावधान रहने की आवश्यकता है कि वे दोनों अपडेट किए गए थे।
  2. हम केवल परिवर्तित पंक्तियों को लॉग इन करना चाहते हैं AT_Person_To_Push। यदि 5 पंक्तियों को अपडेट किया जाता है, लेकिन केवल 2 को इस तरह से अपडेट किया जाता है, जिसकी हमें परवाह है, तो हमें केवल 2 प्रासंगिक पंक्तियों को संसाधित करने की आवश्यकता है।

यहां बताया गया है कि मैं इसे कैसे संभालूंगा:

  1. लेफ्ट जॉइन insertedकरें deleted, क्योंकि insertedआवेषण और अपडेट के deletedलिए पंक्तियाँ होंगी जबकि केवल अपडेट के लिए पंक्तियाँ होंगी।
  2. का प्रयोग करें EXISTSसाथ EXCEPTपंक्तियों जहां खोजने के लिए insertedमूल्यों से अलग deletedमान। i.First_Name != d.First_Name OR i.Last_Name != d.Last_Name...जब ट्रिगर एक INSERT संभाल रहा होता है, तो आप उपयोग नहीं कर सकते क्योंकि हटा दी गई तालिका खाली हो जाएगी (और LEFT JOIN नल वापस आ जाएगी)।
  3. केवल प्रभावित पंक्तियों को सम्मिलित करें AT_Person_To_Push
ALTER TRIGGER [dbo].[trATPerson_alter] 
   ON  [mydb].[dbo].[AT_Person]
   AFTER INSERT,UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    INSERT INTO [mydb].[dbo].[AT_Person_To_Push] (
            [Facility],
            [VendorID],
            [Person_code],
            [First_Name],
            [Last_Name],
            [JobCode],
            [Alink],
            [Inactive]
        )
    SELECT  i.[Facility],
            i.[VendorID],
            i.[Person_code],
            i.[First_Name],
            i.[Last_Name],
            i.[JobCode],
            i.[Alink],
            i.[Inactive]
    FROM inserted i
         LEFT JOIN deleted d
           ON i.Person_code = d.Person_code
    -- Check for changes that require a push
    WHERE EXISTS (SELECT i.[First_Name], i.[Last_Name], i.[JobCode], i.[Inactive]
                  EXCEPT
                  SELECT d.[First_Name], d.[Last_Name], d.[JobCode], d.[Inactive]);
END

1

इसे इस्तेमाल करे,

Declare @Acton int=0

If exists (Select 1 from inserted)
set @Acton=1

If exists (Select 1 from deleted)
set @Acton=@Acton+2

if(@Action=1) -- Only insert

if(@Action=3) -- Only Update
begin
IF (UPDATE([First_Name]) OR UPDATE([Last_Name]) OR UPDATE([JobCode]) OR UPDATE([Inactive]))
Begin

End
end

if(@Action=2) -- Only Delete
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.