2009-11-17 13 views
141

हमारे पास क्लाइंट ऐप है जो SQL सर्वर 2005 पर कुछ SQL चला रहा है जैसे कि निम्न:एसक्यूएल सर्वर - लेनदेन त्रुटि पर वापस रोल?

BEGIN TRAN; 
INSERT INTO myTable (myColumns ...) VALUES (myValues ...); 
INSERT INTO myTable (myColumns ...) VALUES (myValues ...); 
INSERT INTO myTable (myColumns ...) VALUES (myValues ...); 
COMMIT TRAN; 

यह एक लंबे स्ट्रिंग कमांड द्वारा भेजा जाता है।

यदि कोई आवेषण विफल रहता है, या कमांड का कोई भी भाग विफल रहता है, तो क्या SQL सर्वर लेनदेन को वापस ले जाता है? अगर यह रोलबैक नहीं करता है, तो क्या मुझे इसे वापस रोल करने के लिए दूसरा आदेश भेजना होगा?

मैं एपीआई और भाषा के बारे में विशिष्ट जानकारी दे सकता हूं, लेकिन मुझे लगता है कि एसक्यूएल सर्वर को किसी भी भाषा के लिए इसका जवाब देना चाहिए।

+0

http://stackoverflow.com/questions/1150032/what-is-the-benefit-of-using-set- xact-abort-on-in-a-store-process – zloctb

उत्तर

157

इस प्रकार एक TRY CATCH ब्लॉक में इस लपेट कर सकते हैं आप गलती की स्थिति में अपने लेन-देन से पहले set xact_abort on डाल सकते हैं वापस स्वचालित रूप से यकीन है कि एसक्यूएल रोल बनाने के लिए।

+1

क्या यह एमएस एसक्यूएल 2 के और उच्चतर पर काम करेगा? यह सबसे आसान समाधान लगता है। – jonathanpeppers

+1

यह 2000, 2005 और 2008 के दस्तावेज़ों में दिखाई देता है इसलिए मुझे हां लगता है। हम इसे 2008 में उपयोग कर रहे हैं। – DyingCactus

+0

क्या नेटवर्क टाइमआउट या सामान्य रूप से नेटवर्क त्रुटियों पर रोलबैक करने का कोई विकल्प है? या यह विकल्प सभी को एक में संभालता है? – jonathanpeppers

10

यदि कोई आवेषण विफल रहता है, या कमांड का कोई भी भाग विफल रहता है, तो क्या SQL सर्वर लेनदेन को वापस ले जाता है?

नहीं, ऐसा नहीं है।

यदि यह रोलबैक नहीं है, तो क्या मुझे इसे वापस रोल करने के लिए दूसरा आदेश भेजना होगा?

निश्चित रूप से, आपको COMMIT के बजाय ROLLBACK जारी करना चाहिए।

आप तय करने के लिए प्रतिबद्ध है या लेनदेन रोलबैक के लिए कि क्या चाहते हैं, आप COMMIT वाक्य बयान से बाहर है, को दूर आवेषण के परिणामों की जांच और उसके बाद चेक के परिणामों के आधार या तो COMMIT या ROLLBACK जारी करना चाहिए।

+0

तो अगर मुझे कोई त्रुटि मिलती है, तो "प्राथमिक कुंजी संघर्ष" कहें, मुझे रोलबैक पर दूसरी कॉल भेजने की आवश्यकता है?मुझे लगता है यह सार्थक बात है। क्या होता है यदि कोई नेटवर्क से संबंधित त्रुटि है जैसे कनेक्शन बहुत लंबे समय तक चलने वाले SQL कथन के दौरान अलग हो जाता है? – jonathanpeppers

+2

जब कनेक्शन कनेक्शन समाप्त होता है, अंतर्निहित नेटवर्क प्रोटोकॉल (ई। जी। 'नामित पाइप्स' या 'टीसीपी') कनेक्शन को तोड़ देता है। जब कोई कनेक्शन टूटा जाता है, तो 'SQL सर्वर' वर्तमान में चल रहे सभी आदेशों को रोकता है और लेनदेन को रोलबैक करता है। – Quassnoi

+1

तो मरने कैक्टस का समाधान ऐसा लगता है कि यह मेरी समस्या को हल करता है, मदद के लिए धन्यवाद। – jonathanpeppers

154

आप सही हैं कि पूरा लेनदेन वापस लुढ़का जाएगा। आपको इसे वापस रोल करने के लिए कमांड जारी करना चाहिए।

आप के रूप

BEGIN TRY 
    BEGIN TRANSACTION 

     INSERT INTO myTable (myColumns ...) VALUES (myValues ...); 
     INSERT INTO myTable (myColumns ...) VALUES (myValues ...); 
     INSERT INTO myTable (myColumns ...) VALUES (myValues ...); 

    COMMIT TRAN -- Transaction Success! 
END TRY 
BEGIN CATCH 
    IF @@TRANCOUNT > 0 
     ROLLBACK TRAN --RollBack in case of Error 

    -- you can Raise ERROR with RAISEERROR() Statement including the details of the exception 
    RAISERROR(ERROR_MESSAGE(), ERROR_SEVERITY(), 1) 
END CATCH 
+1

मुझे मरिंग कैक्टस का समाधान बेहतर पसंद है, वह बदलने के लिए कोड की 1 पंक्ति है। यदि आपका कारण कुछ कारणों से बेहतर (या अधिक विश्वसनीय) मुझे बताएं। – jonathanpeppers

+9

कोशिश करने की पकड़ आपको त्रुटि को पकड़ने (और संभवतः ठीक करने) की क्षमता देता है और यदि आवश्यक हो तो कस्टम त्रुटि संदेश बढ़ाता है। –

+0

चूंकि हम वास्तव में एसक्यूएल के भीतर विशेष रूप से त्रुटि को संभालने की परवाह नहीं करते हैं, मुझे लगता है कि हम मरिंग कैक्टस के समाधान के साथ जा रहे हैं। – jonathanpeppers

15

एमडीएसएन आलेख से, Controlling Transactions (Database Engine)

यदि बैच में रन-टाइम कथन त्रुटि (जैसे बाधा उल्लंघन) होता है, तो डेटाबेस इंजन में डिफ़ॉल्ट व्यवहार केवल उस कथन को रोल करना है जो त्रुटि उत्पन्न करता है। आप SET XACT_ABORT कथन का उपयोग करके इस व्यवहार को बदल सकते हैं। SET XACT_ABORT ON निष्पादित होने के बाद, किसी भी रन-टाइम कथन त्रुटि वर्तमान लेनदेन के स्वचालित रोलबैक का कारण बनती है। संकलन त्रुटियों, जैसे वाक्यविन्यास त्रुटियां, SET XACT_ABORT से प्रभावित नहीं हैं। अधिक जानकारी के लिए, SET XACT_ABORT (ट्रांजैक्ट-एसक्यूएल) देखें।

आपके मामले में यह किसी भी प्रविष्टि में विफल होने पर पूर्ण लेनदेन को वापस ले जाएगा।

+1

वाक्यविन्यास त्रुटियों को संभालने के लिए हमें क्या चाहिए? या त्रुटियों को संकलित करें? यदि उनमें से कोई भी पूरा लेनदेन वापस लेना चाहिए – MonsterMMORPG

7
यहाँ

त्रुटि MSSQL सर्वर 2016 के साथ काम कर संदेश मिल के साथ कोड:

BEGIN TRY 
    BEGIN TRANSACTION 
     -- Do your stuff that might fail here 
    COMMIT 
END TRY 
BEGIN CATCH 
    IF @@TRANCOUNT > 0 
     ROLLBACK TRAN 

     DECLARE @ErrorMessage NVARCHAR(4000) = ERROR_MESSAGE() 
     DECLARE @ErrorSeverity INT = ERROR_SEVERITY() 
     DECLARE @ErrorState INT = ERROR_STATE() 

    -- Use RAISERROR inside the CATCH block to return error 
    -- information about the original error that caused 
    -- execution to jump to the CATCH block. 
    RAISERROR (@ErrorMessage, -- Message text. 
       @ErrorSeverity, -- Severity. 
       @ErrorState -- State. 
       ); 
END CATCH 
+1

मुझे 'DECLARE @VAR TYPE का उपयोग करना पड़ा; एसईटी @ वार = त्रुटि; 'एसक्यूएल सर्वर 2005 में त्रुटियों को बढ़ाने के लिए। अन्यथा त्रुटियों को बढ़ाने के लिए उपरोक्त कोड पुराने डीबी के लिए भी काम करता है। किसी स्थानीय चर के लिए डिफ़ॉल्ट मान असाइन करने का प्रयास करना समस्या उत्पन्न कर रहा था। – jtlindsey

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