SQL अद्यतन ट्रिगर केवल जब स्तंभ संशोधित किया गया है


101

अन्य उदाहरणों को देखकर, मैं निम्नलिखित के साथ आया हूं, लेकिन यह काम नहीं करता है जैसा कि मैं चाहूंगा: मैं चाहता हूं कि यह केवल संशोधित जानकारी QtyToRepairको अपडेट करे यदि मूल्य अपडेट किया गया है ... लेकिन यह नहीं करता है उस।

अगर मैं बाहर टिप्पणी करता हूं तो हर मामले में संशोधित जानकारी अपडेट की जाती है। जैसा कि मैंने कहा कि अन्य उदाहरणों ने मुझे आशावादी बना दिया। किसी भी सुराग की सराहना की। धन्यवाद।

वाल्टर

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS 
BEGIN
    SET NOCOUNT ON;

    UPDATE SCHEDULE SET modified = GETDATE()
        , ModifiedUser = SUSER_NAME()
        , ModifiedHost = HOST_NAME()
    FROM SCHEDULE S
    INNER JOIN Inserted I on S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber
    WHERE S.QtyToRepair <> I.QtyToRepair
END

8
के बारे में एक चेतावनी update()- यह केवल परीक्षण करता है यदि स्तंभ अपडेट सूची में दिखाई देता है, और आवेषण के लिए हमेशा सच होता है। यह जाँच नहीं करता है कि क्या स्तंभ मान बदल गया है, क्योंकि आपके पास एक से अधिक पंक्ति हो सकती हैं, जहाँ कुछ मान बदल गए हैं और कुछ नहीं आए हैं।
निकोला मार्कोविनोविक

जवाबों:


128

आपके पास अपने प्रश्न के लिए दो तरीके हैं:

1- अपने ट्रिगर में अपडेट कमांड का उपयोग करें।

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS BEGIN
    SET NOCOUNT ON;
    IF UPDATE (QtyToRepair) 
    BEGIN
        UPDATE SCHEDULE 
        SET modified = GETDATE()
           , ModifiedUser = SUSER_NAME()
           , ModifiedHost = HOST_NAME()
        FROM SCHEDULE S INNER JOIN Inserted I 
        ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber
        WHERE S.QtyToRepair <> I.QtyToRepair
    END 
END

2- सम्मिलित तालिका और हटाए गए तालिका के बीच में शामिल हों का उपयोग करें

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS BEGIN
    SET NOCOUNT ON;    

    UPDATE SCHEDULE 
    SET modified = GETDATE()
       , ModifiedUser = SUSER_NAME()
       , ModifiedHost = HOST_NAME()
    FROM SCHEDULE S 
    INNER JOIN Inserted I ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber
    INNER JOIN Deleted D ON S.OrderNo = D.OrderNo and S.PartNumber = D.PartNumber                  
    WHERE S.QtyToRepair <> I.QtyToRepair
    AND D.QtyToRepair <> I.QtyToRepair
END

जब आप तालिका के लिए अद्यतन आदेश का उपयोग करते हैं SCHEDULEऔर QtyToRepairस्तंभ को नए मान पर सेट करते हैं , यदि नया मान एक या बहु पंक्ति में पुराने मूल्य के बराबर है, तो समाधान 1 अनुसूची तालिका में सभी अद्यतन पंक्ति को अद्यतन करता है, लेकिन समाधान 2 केवल अनुसूची पंक्तियों को अद्यतन करता है जो पुराने मान नए के बराबर नहीं है मूल्य।


यह उल्लेख नहीं करने के लिए क्षमा करें कि यह SQLServer था। मुझे हटाए गए तालिका का उपयोग करने की आवश्यकता है। मैंने एक अलग तालिका (एक इतिहास को बनाए रखने के लिए) के लिए लिखना समाप्त कर दिया।
वाल्टर डी जोंग

9
# 2 दृष्टिकोण बेहतर है, यदि आप नहीं चाहते कि आपके ट्रिगर को आग लगे तो कॉलम को उसी मान में बदला जा रहा है।
21

2
मुझे लगता है कि मुझे कुछ याद आ रहा है - लेकिन दृष्टिकोण # 1 काम नहीं करेगा, क्योंकि यह अपडेट के बाद है, इसलिए वर्तमान पंक्ति में हमेशा डालने वाली पंक्ति के समान मूल्य होगा। आप चाहिए आपको अपडेट के बाद उपयोग कर रहे हैं नष्ट कर दिया करने के लिए शामिल होने के
रोब

5
@Rob "IF UPDATE" स्टेटमेंट एक ऐसी प्रक्रिया को लागू कर रहा है जिसमें कॉलम की कॉलम सूची तक पहुंच है जिसे क्वेरी के भाग के रूप में अपडेट किया गया था और इस प्रकार पिछले मानों को जानने की आवश्यकता नहीं है। (हम अपने वातावरण में बस इस बात की पुष्टि करते हैं और पुष्टि करते हैं कि "IF UPDATE" "AFTER UPDATE" क्लॉज की परवाह किए बिना सम्मानित किया गया है)
TChadwick

3
आप insertedदूसरी क्वेरी में तालिका क्यों शामिल करते हैं ? यह टेबल के समान ही होना चाहिए, है ना?
टेरान

22

मैं जिस कोड को समाप्त करता हूं, वह है:

IF UPDATE (QtyToRepair)
    begin
        INSERT INTO tmpQtyToRepairChanges (OrderNo, PartNumber, ModifiedDate, ModifiedUser, ModifiedHost, QtyToRepairOld, QtyToRepairNew)
        SELECT S.OrderNo, S.PartNumber, GETDATE(), SUSER_NAME(), HOST_NAME(), D.QtyToRepair, I.QtyToRepair FROM SCHEDULE S
        INNER JOIN Inserted I ON S.OrderNo = I.OrderNo and S.PartNumber = I.PartNumber
        INNER JOIN Deleted D ON S.OrderNo = D.OrderNo and S.PartNumber = D.PartNumber 
        WHERE I.QtyToRepair <> D.QtyToRepair
end

1
मुझे यह मददगार लगा क्योंकि 2- उपयोग में शामिल होने के लिए ऊपर दिए गए उत्तर के बीच में काम कभी नहीं किया, जहां मापदंड WHERE S.QtyToRepair <> I.QtyToRepair AND D.QtyToRepair <> I.QtyToRepairकभी भी फायरिंग / मिलान नहीं करते थे क्योंकि पहला मानदंड कभी सच नहीं था - सम्मिलित तालिका हमेशा वास्तविक तालिका मान से मेल खाती थी। `WHERE I.QtyToRepair <> D.QtyToRepair` का उपयोग करना मेरे लिए महत्वपूर्ण था। साथ ही IF UPDATE (field)कई ट्रिगर्स फायरिंग से मदद मिलती है।
फायरगार्डन

13

अगर QtyToRepairपहली बार में अपडेट किया गया है, तो उसे जांचना चाहिए ।

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS 
BEGIN
SET NOCOUNT ON;
    IF UPDATE (QtyToRepair) 
    BEGIN
        UPDATE SCHEDULE 
        SET modified = GETDATE()
           , ModifiedUser = SUSER_NAME()
           , ModifiedHost = HOST_NAME()
        FROM SCHEDULE S INNER JOIN Inserted I 
            ON S.OrderNo = I.OrderNo and S.PartNumber =    I.PartNumber
        WHERE S.QtyToRepair <> I.QtyToRepair
    END
END

6

आप निम्नलिखित करना चाहते हैं:

ALTER TRIGGER [dbo].[tr_SCHEDULE_Modified]
   ON [dbo].[SCHEDULE]
   AFTER UPDATE
AS 
BEGIN
SET NOCOUNT ON;

    IF (UPDATE(QtyToRepair))
    BEGIN
        UPDATE SCHEDULE SET modified = GETDATE()
            , ModifiedUser = SUSER_NAME()
            , ModifiedHost = HOST_NAME()
        FROM SCHEDULE S
        INNER JOIN Inserted I ON S.OrderNo = I.OrderNo AND S.PartNumber = I.PartNumber
        WHERE S.QtyToRepair <> I.QtyToRepair
    END
END

कृपया ध्यान दें कि यह ट्रिगर हर बार फायर करेगा जब आप कॉलम को अपडेट करते हैं, भले ही मूल्य समान हो या न हो।


2

जब भी किसी रिकॉर्ड ने अपडेट किया है तो एक रिकॉर्ड "डिलीट" हो जाता है। यहाँ मेरा उदाहरण है:

ALTER TRIGGER [dbo].[UpdatePhyDate]
   ON  [dbo].[M_ContractDT1]
   AFTER UPDATE
AS 
BEGIN
    -- on ContarctDT1 PhyQty is updated 
    -- I want system date in Phytate automatically saved
    SET NOCOUNT ON;

    declare @dt1ky as int   

    if(update(Phyqty))
    begin
        select @dt1ky = dt1ky from deleted

        update M_ContractDT1 set PhyDate=GETDATE() where Dt1Ky=  @dt1ky     

    end

END

यह बढ़िया काम करता है

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