2015-01-07 5 views
5

मैं इस चर ट्रिगर को कई चरों का उपयोग किये बिना कैसे लिखूं?मुझे अपने पहले टी-एसक्यूएल अपडेट ट्रिगर को अनुकूलित करने की आवश्यकता है

मैंने अपना पहला SQL सर्वर ट्रिगर लिखा और यह ठीक काम करता है, लेकिन मुझे लगता है कि, एक आसान समाधान होना चाहिए।

यदि न्यूनतम 5 कॉलम बदल दिए गए हैं तो मैं दूसरी तालिका में दो नई पंक्तियां लिखता हूं। पंक्ति 1 = पुराना फ़हरर (= चालक) और पुराना विस्फोट और अद्यतन-समय पंक्ति 2 = नया फ़हरर और नया विवाद और अद्यतन समय मेरा समाधान केवल फॉक्सप्रो-ट्रिगर की एक प्रति है, लेकिन टी में एक आसान समाधान होना चाहिए -एसक्यूएल यह जांचने के लिए कि एक कोलम बदल गया है या नहीं।

ALTER TRIGGER [dbo].[MyTrigger] 
ON [dbo].[tbldisposaetze] 
AFTER UPDATE 
AS 
SET NOCOUNT ON; 
/*SET XACT_ABORT ON 
SET ARITHABORT ON 
*/ 
DECLARE @oldfahrer varchar(10) 
DECLARE @oldbus varchar(10) 
DECLARE @olddispodat date 
DECLARE @oldvzeit decimal(4,0) 
DECLARE @oldbzeit decimal(4,0) 
DECLARE @oldbeschreibk varchar(255) 

DECLARE @newfahrer varchar(10) 
DECLARE @newbus varchar(10) 
DECLARE @newdispodat date 
DECLARE @newvzeit decimal(4,0) 
DECLARE @newbzeit decimal(4,0) 
DECLARE @newbeschreibk varchar(255) 

    SELECT @oldfahrer = fahrer,@oldbeschreibk=beschreibk,@oldbus=bus,@oldbzeit=bzeit,@olddispodat=dispodat,@oldvzeit=vzeit 
     FROM DELETED D 
    SELECT @newfahrer = fahrer,@newbeschreibk=beschreibk,@newbus=bus,@newbzeit=bzeit,@newdispodat=dispodat,@newvzeit=vzeit 
     FROM inserted I 

if @oldbeschreibk <> @newbeschreibk or @oldbus <> @newbus or @oldbzeit <> @newbzeit or @oldfahrer <> @newfahrer or @oldvzeit <> @newvzeit 
begin 
    IF (SELECT COUNT(*) FROM tbldispofahrer where [email protected] and [email protected]) > 0 
    update tbldispofahrer set laenderung = GETDATE() where [email protected] and [email protected] 
    else 
    INSERT into tbldispofahrer (fahrer,dispodat,laenderung) VALUES (@oldfahrer,@olddispodat,getdate()) 

    IF (SELECT COUNT(*) FROM tbldispofahrer where [email protected] and [email protected]) > 0 
    update tbldispofahrer set laenderung = GETDATE() where [email protected] and [email protected] 
    else 
    INSERT into tbldispofahrer (fahrer,dispodat,laenderung) VALUES (@newfahrer,@newdispodat,getdate()) 
end 
+1

ठीक पहले आप बिल्कुल इस तरह वैरिएबल का उपयोग नहीं किया जाना चाहिए !! कभी भी किसी ट्रिगर में। हटाए गए और सम्मिलित तालिकाओं में एकाधिक रिकॉर्ड हो सकते हैं और आपको उस पर विचार करने के लिए कोड लिखना होगा। – HLGEM

+0

आपके ट्रिगर में ** प्रमुख ** दोष है जिसमें आपको लगता है कि इसे ** प्रति पंक्ति ** ** कहा जाएगा - यह ** ** ** मामला नहीं है। ट्रिगर ** प्रति स्टेटमेंट ** ** पर आग लगाएगा, इसलिए यदि आपके 'अपडेट' स्टेटमेंट 25 पंक्तियों को प्रभावित करते हैं, तो आपको ** एक बार ** ट्रिगर मिलेगा, लेकिन फिर 'सम्मिलित' और 'हटाए गए' प्रत्येक में 25 पंक्तियां होंगी । उन 25 पंक्तियों में से कौन सा आपके 'चयन' कोड का चयन करेगा ?? यह गैर-निर्धारक है। इसे ध्यान में रखने के लिए आपको अपने ट्रिगर को फिर से लिखना होगा! –

+0

आपकी 'tbldispofahrer' तालिका में प्राथमिक कुंजी कॉलम क्या है। –

उत्तर

4

मुझे लगता है कि आपके पास SQL ​​Server 2008 या इससे अधिक है। आप इसे बिना किसी चर के एक कथन में कर सकते हैं।

सभी काम करने के बजाय पहले चर प्राप्त करें और देखें कि वे मेल नहीं खाते हैं, तो आप where खंड के हिस्से में आसानी से ऐसा कर सकते हैं। जैसा कि टिप्पणियों में लोगों ने कहा है, आप सम्मिलित और हटाए गए हिस्से के रूप में कई पंक्तियां प्राप्त कर सकते हैं। यह सुनिश्चित करने के लिए कि आप एक ही अद्यतन पंक्ति के साथ काम कर रहे हैं, आपको प्राथमिक कुंजी से मिलान करना होगा।

पंक्ति डालने या अपडेट करने के लिए, मैं MERGE कथन का उपयोग कर रहा हूं। विलय का स्रोत उपरोक्त खंड के साथ एक संघ है, संघ में शीर्ष तालिका में पुरानी फेहरर है, और नीचे नया फरहर है। आपके भीतर के आईएफ की तरह, मौजूदा पंक्तियों को दूर और विस्फोट से मेल किया जाता है, और उचित रूप से डाला या अपडेट किया जाता है।

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

MERGE tbldispofahrer AS tgt 
USING (
    SELECT d.farher, d.dispodat, GETDATE() [laenderung] 
    INNER JOIN inserted i ON i.PrimaryKey = d.PrimaryKey 
     AND (i.fahrer <> d.fahrer OR i.beschreibk <> d.beschreik ...) 
    UNION 
    SELECT i.farher, i.dispodat, GETDATE() [laenderung] 
    INNER JOIN inserted i ON i.PrimaryKey = d.PrimaryKey 
     AND (i.fahrer <> d.fahrer OR i.beschreibk <> d.beschreik ...) 
) AS src (farher, dispodat, laenderung) 
ON tgt.farher = src.farher AND tgt.dispodat = src.dispodat 
WHEN MATCHED THEN UPDATE SET 
    laenderung = GETDATE() 
WHEN NOT MATCHED THEN 
    INSERT (fahrer,dispodat,laenderung) 
    VALUES (src.fahrer, src.dispodat, src.laenderung) 
1

डैनियल से उत्तर में कुछ छोटी वाक्यविन्यास त्रुटियां थीं। निम्नलिखित कोड ठीक चल रहा है:

MERGE tbldispofahrer AS tgt 
 
USING (
 
    SELECT d.fahrer, d.dispodat, GETDATE() [laenderung] from deleted d 
 
    INNER JOIN inserted i ON i.satznr = d.satznr 
 
     AND (i.fahrer <> d.fahrer OR i.beschreibk <> d.beschreibk or i.bus <> d.bus or i.bzeit <> d.bzeit or i.vzeit <> d.vzeit) 
 
    UNION 
 
    SELECT i.fahrer, i.dispodat, GETDATE() [laenderung] from inserted i 
 
    INNER JOIN deleted d ON i.satznr = d.satznr 
 
     AND (i.fahrer <> d.fahrer OR i.beschreibk <> d.beschreibk or i.bus <> d.bus or i.bzeit <> d.bzeit or i.vzeit <> d.vzeit) 
 
) AS src (fahrer, dispodat, laenderung) 
 
ON tgt.fahrer = src.fahrer AND tgt.dispodat = src.dispodat 
 
WHEN MATCHED THEN UPDATE SET 
 
    laenderung = GETDATE() 
 
WHEN NOT MATCHED THEN 
 
    INSERT (fahrer,dispodat,laenderung) 
 
    VALUES (src.fahrer, src.dispodat, src.laenderung);

संबंधित मुद्दे

 संबंधित मुद्दे