डिफ़ॉल्ट रूप से, लेन-देन, अधिकांश समय होता है, जब कोई त्रुटि होती है, तो स्वचालित रूप से रोल-बैक / रद्द नहीं किया जाता है। यह आमतौर पर एक समस्या नहीं है जब तक आपके पास उचित त्रुटि से निपटने और ROLLBACKअपने आप को कॉल करने के लिए नहीं है । हालांकि, कभी-कभी चीजें जटिल हो जाती हैं, जैसे कि बैच-एबॉर्टिंग त्रुटियों के मामले में, या जब OPENQUERY(या सामान्य रूप से लिंक्ड सर्वर) का उपयोग करते हुए और रिमोट सिस्टम पर कोई त्रुटि होती है। हालांकि अधिकांश त्रुटियों का उपयोग करके फंसे हुए हो सकते हैं TRY...CATCH, दो ऐसे हैं जो उस तरह से नहीं फंस सकते हैं (यह याद नहीं है कि इस समय कौन से हैं, हालांकि - शोध)। इन मामलों में, आपको SET XACT_ABORT ONलेन-देन को ठीक से रोलबैक करने के लिए उपयोग करना चाहिए ।
SET XACT_ABORT के कारण SQL सर्वर तुरंत किसी भी Transaction (यदि कोई सक्रिय है) को वापस कर देता है और कोई भी त्रुटि होने पर बैच को निरस्त कर देता है। SQL सर्वर 2005 से पहले यह सेटिंग मौजूद थी, जिसने TRY...CATCHनिर्माण शुरू किया था। अधिकांश भाग के लिए, TRY...CATCHअधिकांश स्थितियों को संभालता है और इसलिए ज्यादातर इसकी आवश्यकता को पूरा करता है XACT_ABORT ON। हालांकि, जब उपयोग OPENQUERY(और संभवतः एक अन्य परिदृश्य जिसे मैं इस समय याद नहीं कर सकता हूं), तो आपको अभी भी उपयोग करने की आवश्यकता होगी SET XACT_ABORT ON;।
आपके पास हमेशा उचित त्रुटि हैंडलिंग होनी चाहिए, विशेष रूप से लेन-देन का उपयोग करते समय। TRY...CATCHनिर्माण, SQL सर्वर 2005 में शुरू की, लगभग सभी स्थितियों, के लिए परीक्षण पर एक स्वागत सुधार से निपटने में एक साधन प्रदान करता @@ERRORप्रत्येक बयान है, जो बैच-निरस्त त्रुटियों के साथ ज्यादा मदद नहीं की है।
TRY...CATCHहालांकि, एक नया "राज्य" शुरू किया। जब नहीं का उपयोग कर TRY...CATCHनिर्माण, अगर आप एक सक्रिय लेन-देन है और एक त्रुटि तब होती है, तो कई रास्ते है कि लिया जा सकता है:
XACT_ABORT OFFऔर कथन-निरस्त करने की त्रुटि: लेन-देन अभी भी सक्रिय है और यदि कोई हो, तो अगले कथन के साथ प्रसंस्करण जारी है ।
XACT_ABORT OFFऔर सबसे बैच-गर्भपात की त्रुटियां: लेन-देन अभी भी सक्रिय है और अगले बैच के साथ प्रसंस्करण जारी है , यदि कोई हो।
XACT_ABORT OFFऔर कुछ बैच-गर्भपात की त्रुटियां: लेन-देन लुढ़का हुआ है और अगले बैच के साथ प्रसंस्करण जारी है , यदि कोई हो।
XACT_ABORT ONऔर कोई त्रुटि: लेन-देन लुढ़का हुआ है और अगले बैच के साथ प्रसंस्करण जारी है , यदि कोई हो।
जब भी, TRY...CATCHबैच-गर्भपात की त्रुटियों का उपयोग करते हुए , बैच को निरस्त न करें, बल्कि CATCHब्लॉक पर नियंत्रण स्थानांतरित करें । कब XACT_ABORTहै OFF, लेन-देन अभी भी अधिकांश समय तक सक्रिय रहेगा, और आपको COMMITसबसे अधिक संभावना होगी , या ROLLBACK। लेकिन जब कुछ बैच-एबॉर्टिंग एरर (जैसे कि OPENQUERY), या जब XACT_ABORTहो ON, का सामना करना पड़ता है , तो ट्रांजेक्शन एक नई स्थिति में होगा, "अनबिकेबल"। इस अवस्था में आप COMMITन तो कोई DML ऑपरेशन कर सकते हैं और न ही कर सकते हैं। आप सभी कर सकते हैं ROLLBACKऔर SELECTबयान। हालाँकि, इस "असुविधाजनक" स्थिति में, लेन-देन त्रुटि होने पर वापस ले लिया गया था, और इसे जारी करना ROLLBACKकेवल एक औपचारिकता है, लेकिन एक ऐसा किया जाना चाहिए।
एक फ़ंक्शन, XACT_STATE , का उपयोग यह निर्धारित करने के लिए किया जा सकता है कि क्या लेन-देन सक्रिय , असुविधाजनक है या मौजूद नहीं है। यह CATCHनिर्धारित करने के लिए कि -1परीक्षण के बजाय परिणाम (यानी असुविधाजनक) है, तो यह निर्धारित करने के लिए ब्लॉक में इस फ़ंक्शन की जांच करने के लिए (कुछ, कम से कम) की सिफारिश की जाती है @@TRANCOUNT > 0। लेकिन इसके साथ XACT_ABORT ON, यह एकमात्र संभव राज्य होना चाहिए, इसलिए ऐसा लगता है कि इसके लिए परीक्षण @@TRANCOUNT > 0और XACT_STATE() <> 0समकक्ष हैं। दूसरी ओर, जब XACT_ABORTहोता है OFFऔर एक सक्रिय लेनदेन होता है, तो 1या तो या ब्लॉक -1में एक राज्य होना संभव है CATCH, जो COMMITइसके बजाय जारी करने की संभावना के लिए अनुमति देता है ROLLBACK(हालांकि, मैं किसी के लिए एक मामले के बारे में नहीं सोच सकता करना चाहेगाCOMMITयदि लेनदेन सराहनीय है)। अधिक जानकारी और प्रयोग पर अनुसंधान XACT_STATE()एक के भीतर CATCHके साथ ब्लॉक XACT_ABORT ON: निम्नलिखित DBA.SE सवाल का मेरा उत्तर में पाया जा सकता में क्या मामलों एक सौदे कैच ब्लॉक के अंदर से प्रतिबद्ध किया जा सकता है जब XACT_ABORT चालू पर सेट है? । कृपया ध्यान दें कि इसके साथ एक मामूली बग है XACT_STATE()जो इसे 1कुछ परिदृश्यों में गलत तरीके से वापस करने का कारण बनता है: XACT_STATE () रिटर्न 1 जब कुछ सिस्टम चर के साथ चयन में उपयोग किया जाता है, लेकिन बिना खंड से
spNewBilling3एक त्रुटि फेंकता है, लेकिन आप रोल वापस नहीं करना चाहताspNewBilling2याspNewBilling1, तो बस हटाने[begin|rollback|commit] transaction createSavebillinginvoiceसेspSavesomename।