पंक्तियों को एक टेबल से दूसरे पर ले जाना


9

मैं संग्रह करने की प्रक्रिया के एक भाग के रूप में एक डेटाबेस से दूसरे में रिकॉर्ड ले जा रहा हूं। मैं पंक्तियों को गंतव्य तालिका में कॉपी करना चाहता हूं और फिर स्रोत तालिका से उन्हीं पंक्तियों को हटा देना चाहता हूं।

मेरा सवाल यह है कि अगर चेक पहले पंक्तियों को हटाने से पहले सफल था, तो सबसे प्रभावी तरीका क्या है।

मेरा विचार यह है, लेकिन मुझे लगता है कि एक बेहतर तरीका है:

@num_records=select count(ID) from Source_Table where (criteria for eligible rows)

insert * into Destination_Table where (criteria for eligible rows)

if ((select count(ID) from Destination_Table where (criteria) )=@numrecords)

delete * from Source_Table where (criteria)

क्या RAISERROR फ़ंक्शन के साथ संयोजन करना बेहतर / संभव है? धन्यवाद!

जवाबों:


13

मैं स्पष्ट लेनदेन के साथ TRY / CATCH सिंटैक्स की सिफारिश करूंगा । इस समाधान के लिए मेरी धारणा यह है कि इन्सर्ट फेल होने का कारण कुछ प्रकार की ट्रैपबल एसक्यूएल त्रुटि (जैसे कि एक मुख्य उल्लंघन, डेटाटाइप मिसमैच / कन्वर्ज़न एरर, इत्यादि) है। संरचना इस तरह दिखेगी:

BEGIN TRAN

BEGIN TRY
  INSERT INTO foo(col_a,col_b,col_c,recdate)
  SELECT col_a,col_b,col_c,recdate
  FROM bar
  WHERE recdate BETWEEN @startdate AND @enddate

  DELETE FROM bar
  WHERE recdate BETWEEN @startdate AND @enddate

  COMMIT TRAN
END TRY
BEGIN CATCH
  ROLLBACK TRAN
END CATCH

जिस तरह से यह संरचना काम करती है, अगर INSERT या DELETE में कोई त्रुटि होती है, तो पूरी कार्रवाई वापस चालू हो जाती है। यह गारंटी देता है कि पूरी कार्रवाई सफल होनी चाहिए। आप महसूस किया कि यह जरूरी हो गया था, तो आप इसके साथ जोड़ सकता फेंको 2012 या के लिए RAISERROR 2008 में और अतिरिक्त तर्क जोड़ सकते हैं और यदि उस तर्क को पूरा नहीं किया गया था एक रोलबैक के लिए मजबूर करने के लिए पिछले।

SET XACT_ABORT ON को देखने के लिए एक और विकल्प है , हालांकि मुझे लगता है कि TRY / CATCH सिंटैक्स आपको अधिक विविधता प्रदान करता है।


19

अगर आपकी आर्काइव टेबल नहीं है

  • इस पर परिभाषित ट्रिगर्स को सक्षम किया है।
  • एक पूर्व प्रमुख बाधा के दोनों ओर भाग लें।
  • चेक बाधाओं या सक्षम नियम हैं।

आप इसे एक क़ानून में भी कर सकते हैं।

DELETE FROM source_table
OUTPUT deleted.Foo,
       deleted.Bar,
       SYSUTCDATETIME()
INTO archive_table(Foo, Bar, archived)
WHERE  Foo = 1; 

यह या तो एक इकाई के रूप में सफल होगा या विफल होगा INSERTऔर संग्रह के बीच में जोड़ी जा रही पंक्तियों के साथ संभावित दौड़ की स्थिति से भी बचता है और DELETE(हालांकि आपका WHEREक्लॉज इस तरह से भी संभव नहीं है)।


इनमे से कोई भी नहीं। मुझे लगता है कि मैं उस मार्ग पर जा सकता हूं, मुझे कोड अतिसूक्ष्मवाद पसंद है। अगर किसी कारणवश इन्सर्ट फेल होता है तो मैं सिर्फ रिकॉर्ड नहीं खोना चाहता। (यानी: टेबल लॉकिंग, टाइमआउट, आदि) धन्यवाद!
दीना

@ डीना - क्या आप संकेत दे रहे थे कि यह OUTPUTक्लॉज के साथ संभव है ? ऐसा नहीं है क्योंकि यह सब एक बयान है। इसके अलावा दो बार पंक्तियों को पढ़ने के मुद्दे को टालता है (और संभवतः उन पंक्तियों को खो देता है जो सम्मिलित करने और हटाने के लिए पढ़ने के बीच जोड़े गए थे)
मार्टिन स्मिथ

हां, मेरा यही मतलब है। धन्यवाद, मैं आपकी बात देख रहा हूं।
दीना

एफडब्ल्यूआईडब्ल्यू - यह विधि मूल तालिका के आकार के करीब लॉगफाइल वृद्धि का कारण बनेगी। सुनिश्चित करें कि आप उसके साथ रह सकते हैं। यदि आप नहीं कर सकते, तो इसे DELETE TOP (N) और थोड़ी देर के लूप के साथ बैचों में तोड़ दें जो @@ rowcount वैरिएबल को चेक करता है।
Wjdavis5

1

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

और मैं कोशिश / कैच का उपयोग करने पर माइक से सहमत हूं।


1

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

INSERT dbo.newtable(
      name,
      department,
      Salary
) SELECT 
            name,
            FirstName,
            Lastname
      FROM    (
           DELETE dbo.oldtable
           OUTPUT
                   DELETED.name,
                   DELETED.department,
                   DELETED.Salary
           WHERE ID  IN ( 1001, 1003, 1005 )
      ) AS RowsToMove;

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