TL, DR / कार्यकारी सारांश: प्रश्न के इस भाग के बारे में:
मैं क्या मामलों नियंत्रण के अंदर पारित किया जा सकता में नहीं दिख रहा है CATCH
एक सौदे कि प्रतिबद्ध किया जा सकता है के साथ जब XACT_ABORT
के लिए निर्धारित हैON
।
मैं काफी अब इस पर परीक्षण का एक सा किया है और मैं किसी भी मामले हैं, जहां नहीं मिल सकता है XACT_STATE()
रिटर्न 1
एक के अंदर CATCH
ब्लॉक जब @@TRANCOUNT > 0
और के सत्र संपत्ति XACT_ABORT
है ON
। और वास्तव में, सेट XACT_ABORT के लिए वर्तमान MSDN पृष्ठ के अनुसार :
जब SET XACT_ABORT चालू होता है, यदि कोई Transact-SQL स्टेटमेंट रन-टाइम त्रुटि उठाता है, तो पूरा लेनदेन समाप्त हो जाता है और वापस चला जाता है।
यह कथन आपकी अटकलों और मेरे निष्कर्षों के साथ सहमति से प्रतीत होता है।
MSDN लेख के बारे SET XACT_ABORT
में एक उदाहरण है जब लेनदेन के अंदर कुछ स्टेटमेंट सफलतापूर्वक निष्पादित होते हैं और कुछ XACT_ABORT
सेट होने पर विफल हो जाते हैंOFF
सच है, लेकिन उस उदाहरण में बयान एक ब्लॉक के भीतर नहीं हैं TRY
। TRY
ब्लॉक के भीतर वही कथन अभी भी त्रुटि के कारण होने वाले किसी भी बयान के लिए निष्पादन को रोकेंगे, लेकिन यह मानते हुए कि जब ब्लॉक को नियंत्रण पारित किया जाता XACT_ABORT
है OFF
, तो CATCH
लेन-देन अभी भी भौतिक रूप से मान्य है, जिसमें सभी पूर्व परिवर्तन त्रुटि के बिना हुआ था। और कर सकते हैं , प्रतिबद्ध रहें कि यदि इच्छा है, या वे लुढ़का वापसी हो सकती है। दूसरी ओर, यदि XACT_ABORT
है ON
तो किसी भी पूर्व परिवर्तन स्वचालित रूप से लुढ़का वापस कर रहे हैं, और उसके बाद या तो आप के लिए विकल्प दिए गए हैं: क) इस मुद्दे को एकROLLBACK
जो कि लेन-देन के पहले से ही केवल एक स्थिति की स्वीकृति है क्योंकि लेन-देन पहले से ही शून्य पर रीसेट किया @@TRANCOUNT
गया था 0
, या b) एक त्रुटि मिली। बहुत पसंद नहीं है, है ना?
इस पहेली के लिए संभवतः एक महत्वपूर्ण विवरण जो उस प्रलेखन में स्पष्ट नहीं SET XACT_ABORT
है, वह यह है कि इस सत्र की संपत्ति, और उदाहरण के लिए कोड भी SQL सर्वर 2000 (प्रलेखन संस्करणों के बीच लगभग समान है) के बाद से हो गया है, जो TRY...CATCH
निर्माण से पहले था एसक्यूएल सर्वर 2005 में शुरू की है कि प्रलेखन को देखते हुए फिर से और (उदाहरण को देखकर बिनाTRY...CATCH
) का उपयोग कर XACT_ABORT ON
का कारण बनता है एक तत्काल लेन-देन का रोल-बैक: वहाँ "uncommittable" (कृपया ध्यान दें की कोई लेन-देन राज्य में कोई जिक्र नहीं है कि वहाँ है सभी "अप्रतिस्पर्धी" उस SET XACT_ABORT
दस्तावेज़ में लेन-देन की स्थिति )।
मुझे लगता है कि यह निष्कर्ष निकालना उचित है:
TRY...CATCH
SQL Server 2005 में निर्माण की शुरूआत ने एक नए लेन-देन की स्थिति (यानी "uncommittable") और XACT_STATE()
उस जानकारी को प्राप्त करने के लिए फ़ंक्शन की आवश्यकता पैदा की ।
- यदि वास्तव में निम्न में से दोनों सत्य हैं, तो ब्लॉक
XACT_STATE()
में जाँच करना CATCH
ही मायने रखता है:
XACT_ABORT
है OFF
(और XACT_STATE()
हमेशा लौटना चाहिए -1
और @@TRANCOUNT
आपकी ज़रूरत होगी)
- आपके पास
CATCH
ब्लॉक में तर्क है , या कहीं न कहीं श्रृंखला है, यदि कॉल नेस्टेड हैं, जो एक करने के बजाय एक परिवर्तन ( COMMIT
या यहां तक कि किसी भी डीएमएल, डीडीएल, आदि बयान) करता है । (यह एक बहुत ही atypical उपयोग का मामला है) ** कृपया नीचे देखें नोट पर, UPDATE 3 अनुभाग में, Microsoft द्वारा अनौपचारिक अनुशंसा के संबंध में हमेशा इसके बजाय जाँच करने के लिए , और परीक्षण से पता चलता है कि उनका तर्क पैन नहीं करता है।ROLLBACK
XACT_STATE()
@@TRANCOUNT
TRY...CATCH
SQL सर्वर 2005 में निर्माण की शुरूआत , अधिकांश भाग के लिए, XACT_ABORT ON
सत्र संपत्ति को मानती है क्योंकि यह लेन-देन पर अधिक से अधिक नियंत्रण प्रदान करती है (आपके पास कम से कम विकल्प है COMMIT
, बशर्ते कि XACT_STATE()
वापस न आए -1
)।
इसे देखने का एक और तरीका है, SQL सर्वर 2005 से पहले , XACT_ABORT ON
एक त्रुटि होने पर प्रसंस्करण को रोकने के लिए एक आसान और विश्वसनीय तरीका प्रदान किया गया, जैसा कि @@ERROR
प्रत्येक कथन के बाद जाँचने के लिए है ।
- इसके लिए प्रलेखन उदाहरण कोड
XACT_STATE()
गलत है, या सबसे भ्रामक है, जिसमें यह पता चलता है कि XACT_STATE() = 1
कब XACT_ABORT
है ON
।
लंबा हिस्सा ;-)
हां, MSDN पर वह उदाहरण कोड थोड़ा भ्रामक है (यह भी देखें: @@ TRANCOUNT (रोलबैक) बनाम XACT_STATE ) ;-) और, मैं यह क्योंकि यह या तो पता चलता है कुछ है कि कोई मतलब नहीं (कारण यह है कि आप पूछ रहे हैं के बारे में के लिए: यदि आप भी एक "committable" लेन-देन हो सकता है बनाता है भ्रामक है महसूस CATCH
ब्लॉक जब XACT_ABORT
है ON
), या यहाँ तक कि यह संभव है, तो यह अभी भी एक तकनीकी संभावना पर ध्यान केंद्रित करता है जो कुछ लोग कभी भी चाहते हैं या आवश्यकता होगी, और इस कारण की अनदेखी करते हैं कि इसकी आवश्यकता होने की अधिक संभावना है।
यदि TRY ब्लॉक के अंदर एक गंभीर पर्याप्त त्रुटि है, तो नियंत्रण CATCH में पारित हो जाएगा। इसलिए, अगर मैं CATCH के अंदर हूं, तो मुझे पता है कि लेन-देन में एक समस्या है और वास्तव में इस मामले में एकमात्र समझदार बात यह है कि इसे वापस लेना है, है न?
मुझे लगता है कि अगर हमें यह सुनिश्चित करने में मदद मिलेगी कि हम एक ही पृष्ठ पर हैं तो कुछ शब्दों और अवधारणाओं से क्या मतलब है:
"गंभीर पर्याप्त त्रुटि": बस स्पष्ट होने के लिए, TRY ... CATCH अधिकांश त्रुटियों को फंसा देगा। जो नहीं पकड़ा जाएगा, उसकी सूची उस लिंक किए गए MSDN पृष्ठ पर "त्रुटी से अप्रभावित एक TRY ... CATCH निर्माण" खंड के अंतर्गत सूचीबद्ध है।
"अगर मैं CATCH के अंदर हूं, तो मुझे पता है कि लेन-देन में कोई समस्या है" (उन्हें चरण जोड़ा गया है): यदि "लेन-देन" से आपका मतलब है कि एक स्पष्ट लेनदेन में बयानों को समूह द्वारा आपके द्वारा निर्धारित कार्य की तार्किक इकाई है, तो सबसे अधिक संभावना हां। मुझे लगता है कि हम में से अधिकांश लोग डीबी के लोगों को इस बात से सहमत करते हैं कि रोलिंग-बैक "करने के लिए एकमात्र समझदारी वाली बात है" क्योंकि हम संभवतः एक समान दृष्टिकोण रखते हैं कि हम स्पष्ट लेनदेन का उपयोग कैसे और क्यों करते हैं और एक परमाणु इकाई बनाने के लिए क्या कदम उठाने चाहिए काम की।
लेकिन, अगर आप काम की वास्तविक इकाइयों से मतलब रखते हैं जिन्हें स्पष्ट लेनदेन में वर्गीकृत किया जा रहा है, तो नहीं, आप नहीं जानते कि लेन-देन अपने आप में एक समस्या है। आप केवल यह जानते हैं कि स्पष्ट रूप से परिभाषित लेन-देन के भीतर निष्पादित करने वाले एक बयान में त्रुटि हुई है। लेकिन यह डीएमएल या डीडीएल बयान नहीं हो सकता है। और यहां तक कि अगर यह एक डीएमएल बयान था, तो लेन-देन स्वयं अभी भी सराहनीय हो सकता है।
ऊपर दिए गए दो बिंदुओं को देखते हुए, हमें संभवतः लेनदेन के बीच एक अंतर निकालना चाहिए जिसे आप "कमिट" नहीं कर सकते हैं, और जिन्हें आप "नहीं" चाहते हैं।
जब कोई XACT_STATE()
रिटर्न देता है 1
, तो इसका मतलब है कि लेन-देन "सराहनीय" है, कि आपके पास एक विकल्प है COMMIT
या ROLLBACK
। आप शायद इसे कमिट नहीं करना चाहते हैं , लेकिन अगर कुछ कठिन-से-आने-के-साथ-साथ-एक-उदाहरण-के लिए-आप कारण चाहते थे, तो कम से कम आप कर सकते थे क्योंकि लेन-देन के कुछ हिस्सों ने सफलतापूर्वक पूरा किया।
लेकिन जब कोई XACT_STATE()
रिटर्न देता है -1
, तो आपको वास्तव में इसकी आवश्यकता है ROLLBACK
क्योंकि लेन-देन का कुछ हिस्सा खराब स्थिति में चला गया। अब, मैं इस बात से सहमत हूँ कि अगर नियंत्रण को केटच ब्लॉक में पारित कर दिया गया है, तो यह सिर्फ जांच करने के लिए पर्याप्त है @@TRANCOUNT
, क्योंकि अगर आप लेन-देन कर सकते हैं, तो आप क्यों करना चाहते हैं?
लेकिन यदि आप उदाहरण के शीर्ष पर नोटिस करते हैं, तो XACT_ABORT ON
चीजों को थोड़ा बदलने की सेटिंग । आप एक नियमित त्रुटि हो सकता है, ऐसा करने के बाद BEGIN TRAN
कि पकड़ने ब्लॉक करने के लिए नियंत्रण पारित करेंगे जब XACT_ABORT
है OFF
और XACT_STATE () वापस आ जाएगी 1
। लेकिन, अगर XACT_ABORT है ON
, तो किसी भी 'ol' त्रुटि के लिए Transaction "निरस्त" (यानी अमान्य) है और फिर XACT_STATE()
वापस आ जाएगा -1
। इस मामले में, ब्लॉक के XACT_STATE()
भीतर जांच करना बेकार लगता है CATCH
क्योंकि यह हमेशा लगता है कि -1
कब वापस लौटना XACT_ABORT
है ON
।
तो फिर किस XACT_STATE()
लिए है? कुछ सुराग हैं:
TRY...CATCH
"अपरिवर्तनीय लेनदेन और XACT_STATE" अनुभाग के तहत MSDN पृष्ठ के लिए , कहते हैं:
एक त्रुटि जो TRY ब्लॉक के बाहर लेन-देन को समाप्त कर देती है, एक TRY ब्लॉक के अंदर त्रुटि होने पर लेन-देन के लिए एक अपरिहार्य स्थिति में प्रवेश करती है।
"रिमार्क्स" अनुभाग के तहत सेट XACT_ABORT के लिए MSDN पृष्ठ कहता है:
जब सेट XACT_ABORT बंद होता है, तो कुछ मामलों में केवल त्रुटि उत्पन्न करने वाले Transact-SQL स्टेटमेंट को वापस ले लिया जाता है और लेन-देन संसाधित हो जाता है।
तथा:
XACT_ABORT को SQL सर्वर सहित अधिकांश OLE DB प्रदाताओं के विरुद्ध एक अंतर्निहित या स्पष्ट लेनदेन में डेटा संशोधन विवरणों के लिए चालू होना चाहिए।
"रिमार्क्स" अनुभाग के तहत BEGIN परिवहन के लिए MSDN पृष्ठ कहता है:
BEGIN ट्रांजेक्शन स्टेटमेंट द्वारा शुरू किया गया लोकल ट्रांजेक्शन एक डिस्ट्रीब्यूटेड ट्रांजैक्शन के लिए बढ़ा दिया जाता है, यदि स्टेटमेंट करने या रोल बैक करने से पहले निम्नलिखित एक्शन किए जाते हैं:
- एक INSERT, DELETE, या अद्यतन कथन जो किसी लिंक किए गए सर्वर पर दूरस्थ तालिका का संदर्भ देता है। INSERT, UPDATE, या DELETE स्टेटमेंट विफल हो जाता है यदि लिंक किए गए सर्वर तक पहुँचने के लिए उपयोग किए जाने वाले OLE DB प्रदाता ITransactionJoin इंटरफ़ेस का समर्थन नहीं करता है।
सबसे अधिक उपयोग लिंक्ड सर्वर डीएमएल स्टेटमेंट के संदर्भ में होता है। और मुझे विश्वास है कि मैं खुद सालों पहले इसमें भाग गया था। मुझे सभी विवरण याद नहीं हैं, लेकिन इसका दूरस्थ सर्वर के उपलब्ध न होने से कुछ लेना-देना था, और किसी कारण से, यह त्रुटि TRY ब्लॉक के भीतर नहीं पकड़ी गई और कभी CATCH को नहीं भेजी गई और इसलिए इसने ऐसा किया यह नहीं होना चाहिए जब एक टिप्पणी। बेशक, यह जांच में विफल होने या संभवतः दोनों के बजाय सेट नहीं होने का मुद्दा हो सकता है । और मुझे याद है कि आपने जो कुछ कहा है, अगर आप लिंक्ड सर्वर और / या वितरित लेनदेन का उपयोग करते हैं, तो आपको उपयोग करने और / या करने की आवश्यकता है , लेकिन मैं अब उस दस्तावेज़ को ढूंढ नहीं सकता। अगर मुझे यह नहीं मिला, तो मैं इसे लिंक के साथ अपडेट कर दूंगा।XACT_ABORT
ON
XACT_STATE()
XACT_ABORT ON
XACT_STATE()
फिर भी, मैंने कई चीजों की कोशिश की है और एक परिदृश्य को खोजने में असमर्थ हूं जो रिपोर्टिंग के साथ ब्लॉक पर XACT_ABORT ON
नियंत्रण रखता है और पास करता है ।CATCH
XACT_STATE()
1
के प्रभाव को देखने के लिए ये उदाहरण आज़माएं XACT_ABORT
के मूल्य पर XACT_STATE()
:
SET XACT_ABORT OFF;
BEGIN TRY
BEGIN TRAN;
SELECT 1/0 AS [DivideByZero]; -- error, yo!
COMMIT TRAN;
END TRY
BEGIN CATCH
SELECT @@TRANCOUNT AS [@@TRANCOUNT],
XACT_STATE() AS [XactState],
ERROR_MESSAGE() AS [ErrorMessage]
IF (@@TRANCOUNT > 0)
BEGIN
ROLLBACK;
END;
END CATCH;
GO ------------------------------------------------
SET XACT_ABORT ON;
BEGIN TRY
BEGIN TRAN;
SELECT 1/0 AS [DivideByZero]; -- error, yo!
COMMIT TRAN;
END TRY
BEGIN CATCH
SELECT @@TRANCOUNT AS [@@TRANCOUNT],
XACT_STATE() AS [XactState],
ERROR_MESSAGE() AS [ErrorMessage]
IF (@@TRANCOUNT > 0)
BEGIN
ROLLBACK;
END;
END CATCH;
GO ------------------------------------------------
SET XACT_ABORT ON;
BEGIN TRY
SELECT 1/0 AS [DivideByZero]; -- error, yo!
END TRY
BEGIN CATCH
SELECT @@TRANCOUNT AS [@@TRANCOUNT],
XACT_STATE() AS [XactState],
ERROR_MESSAGE() AS [ErrorMessage]
END CATCH;
अपडेट करें
इस प्रश्न पर इन टिप्पणियों के आधार पर मूल प्रश्न का हिस्सा नहीं है:
मैं पर Erland के लेख के माध्यम से पढ़ने किया गया है त्रुटि और लेन-देन हैंडलिंग वह जहां का कहना है कि XACT_ABORT
है OFF
विरासत कारणों के लिए डिफ़ॉल्ट रूप से और सामान्य रूप से हम करने के लिए यह निर्धारित करना चाहिए ON
।
...
"... यदि आप अनुशंसा का पालन करते हैं और SET XACT_ABORT ON के साथ चलते हैं, तो लेनदेन हमेशा ख़त्म हो जाएगा।"
XACT_ABORT ON
हर जगह उपयोग करने से पहले , मैं सवाल करता हूं: वास्तव में यहां क्या प्राप्त किया जा रहा है? मुझे ऐसा करने के लिए आवश्यक नहीं पाया गया है और आम तौर पर वकील करते हैं कि आपको इसका उपयोग केवल आवश्यक होने पर ही करना चाहिए। आप या नहीं चाहते हैं ROLLBACK
@ रेमस के उत्तर में दिखाए गए टेम्पलेट का उपयोग करके आसानी से संभाल सकते हैं , या जो मैं वर्षों से उपयोग कर रहा हूं वह अनिवार्य रूप से एक ही चीज है लेकिन बिना सेव पॉइंट के, जैसा कि इस उत्तर में दिखाया गया है (जो कि नेस्टेड कॉल संभालती है):
क्या हमें C # कोड में लेन-देन के साथ-साथ संग्रहीत कार्यविधि को भी संभालने की आवश्यकता है
अद्यतन २
मैंने थोड़ा और परीक्षण किया, इस बार एक छोटा .NET कंसोल ऐप बनाकर, ऐप लेयर में एक ट्रांज़ैक्शन बनाकर, किसी भी SqlCommand
ऑब्जेक्ट (यानी के माध्यम से using (SqlTransaction _Tran = _Connection.BeginTransaction()) { ...
) को निष्पादित करने से पहले , साथ ही एक बयान के बजाय बैच-एबॉर्टिंग त्रुटि का उपयोग करके। -बेटिंग त्रुटि, और पाया कि:
- एक "असुविधाजनक" लेनदेन वह है जो अधिकांश भाग के लिए पहले से ही लुढ़का हुआ है (परिवर्तन पूर्ववत किया गया है), लेकिन
@@TRANCOUNT
अभी भी> 0 है।
- जब आपके पास "असम्मानजनक" लेन-देन होता है, तो आप इसे जारी नहीं कर सकते हैं
COMMIT
जो उत्पन्न करेगा और यह कहते हुए त्रुटि करेगा कि लेन-देन "अप्रचलित" है। आप इसे अनदेखा भी नहीं कर सकते / कुछ भी नहीं हो सकता है जब बैच समाप्त होता है, तो यह कहते हुए एक त्रुटि उत्पन्न होगी कि बैच एक लेन-देन के साथ पूरा हो गया है, लेन-देन रहित है और इसे वापस रोल किया जाएगा (इसलिए, उम, अगर यह ऑटो-रोल-बैक वैसे भी होगा क्यों त्रुटि फेंक परेशान?)। तो आपको एक स्पष्ट जारी करना होगाROLLBACK
, शायद तत्काल CATCH
ब्लॉक में नहीं , लेकिन बैच समाप्त होने से पहले।
- एक में
TRY...CATCH
निर्माण, जब XACT_ABORT
है OFF
, त्रुटियों कि लेन-देन को समाप्त होगा स्वचालित रूप से वे एक के बाहर हुआ था TRY
इस तरह के बैच-निरस्त त्रुटियों के रूप में ब्लॉक के रूप में "uncommitable" यह छोड़ रहा है, काम पूर्ववत नहीं बल्कि Tranasction को समाप्त कर देगा। जारी ROLLBACK
करना लेनदेन को बंद करने के लिए आवश्यक औपचारिकता अधिक है, लेकिन काम पहले से ही लुढ़का हुआ है।
- जब
XACT_ABORT
है ON
, सबसे त्रुटियों बैच-निरस्त किया जा रहा के रूप में कार्य है, और सीधे ऊपर (# 3) बुलेट बिंदु में वर्णित के रूप इसलिए व्यवहार करते हैं।
XACT_STATE()
कम से कम एक CATCH
ब्लॉक में, -1
बैच-गर्भपात त्रुटियों के लिए दिखाएगा यदि त्रुटि के समय एक सक्रिय लेनदेन था।
XACT_STATE()
कभी-कभी 1
तब भी लौटता है जब कोई सक्रिय लेनदेन नहीं होता है। यदि @@SPID
(अन्य लोगों के साथ) SELECT
सूची में है XACT_STATE()
, तो XACT_STATE()
1 तब वापस आएगा जब कोई सक्रिय लेनदेन नहीं होगा। यह व्यवहार SQL Server 2012 में प्रारंभ हुआ, और 2014 पर मौजूद है, लेकिन मैंने 2016 पर परीक्षण नहीं किया है।
उपरोक्त बिंदुओं को ध्यान में रखकर:
- यह देखते हुए अंक # 4 और # 5, सबसे (या सभी?) के बाद से त्रुटियों एक लेन-देन "uncommitable" प्रस्तुत करना होगा, यह पूरी तरह जांच करने के लिए व्यर्थ लगता है
XACT_STATE()
में CATCH
ब्लॉक जब XACT_ABORT
है ON
लौटे हमेशा रहेंगे मूल्य के बाद से -1
।
- जाँच हो रही है
XACT_STATE()
में CATCH
ब्लॉक जब XACT_ABORT
है OFF
और अधिक समझ में आता है क्योंकि वापसी मान कम से कम कुछ बदलाव करना होगा क्योंकि यह वापस आ जाएगी 1
बयान-निरस्त त्रुटियों के लिए। हालाँकि, यदि आप हममें से अधिकांश की तरह कोड करते हैं, तो यह अंतर अर्थहीन है क्योंकि आप किसी ROLLBACK
भी तरह से इस तथ्य के लिए कॉल कर रहे होंगे कि कोई त्रुटि हुई है।
- यदि आपको ऐसी स्थिति मिलती है जो ब्लॉक
COMMIT
में वारंट जारी करती CATCH
है, तो उसके मूल्य की जांच करें XACT_STATE()
, और सुनिश्चित करें SET XACT_ABORT OFF;
।
XACT_ABORT ON
लगता है TRY...CATCH
निर्माण पर कोई फायदा नहीं हुआ ।
- मुझे कोई परिदृश्य नहीं मिल रहा है जहाँ जाँच
XACT_STATE()
करने से बस जाँच करने पर सार्थक लाभ मिलता है @@TRANCOUNT
।
- मुझे यह भी पता नहीं है कि ब्लॉक में
XACT_STATE()
रिटर्न कहां है । मुझे लगता है कि यह एक प्रलेखन त्रुटि है।1
CATCH
XACT_ABORT
ON
- हां, आप ऐसा लेन-देन वापस कर सकते हैं जिसे आपने स्पष्ट रूप से शुरू नहीं किया था। और उपयोग करने के संदर्भ में
XACT_ABORT ON
, यह एक म्यूट पॉइंट है क्योंकि TRY
ब्लॉक में होने वाली त्रुटि स्वचालित रूप से परिवर्तनों को रोल-बैक कर देगी।
TRY...CATCH
निर्माण से अधिक लाभ है XACT_ABORT ON
स्वचालित रूप से नहीं पूरे लेन-देन को रद्द करने, और इसलिए लेन-देन (जब तक देने में XACT_STATE()
रिटर्न 1
) के लिए प्रतिबद्ध होना करने के लिए (भले ही यह किनारे से होता है)।
का उदाहरण XACT_STATE()
लौटने -1
जब XACT_ABORT
है OFF
:
SET XACT_ABORT OFF;
BEGIN TRY
BEGIN TRAN;
SELECT CONVERT(INT, 'g') AS [ConversionError];
COMMIT TRAN;
END TRY
BEGIN CATCH
DECLARE @State INT;
SET @State = XACT_STATE();
SELECT @@TRANCOUNT AS [@@TRANCOUNT],
@State AS [XactState],
ERROR_MESSAGE() AS [ErrorMessage];
IF (@@TRANCOUNT > 0)
BEGIN
SELECT 'Rollin back...' AS [Transaction];
ROLLBACK;
END;
END CATCH;
अद्यतन 3
UPDATE 2 अनुभाग में आइटम # 6 से संबंधित ( XACT_STATE()
जब कोई सक्रिय लेन-देन नहीं होने पर संभावित गलत मान लौटाया जाता है):
- SQL सर्वर 2012 (अब तक 2012 SP2 और 2014 SP1 के खिलाफ परीक्षण किया गया) में अजीब / गलत व्यवहार शुरू हुआ
- SQL सर्वर संस्करण 2005, 2008 और 2008 R2 में,
XACT_STATE()
ट्रिगर या INSERT...EXEC
परिदृश्य में उपयोग किए जाने पर अपेक्षित मानों की रिपोर्ट नहीं की जाती है: xact_state () का उपयोग यह निर्धारित करने के लिए मज़बूती से नहीं किया जा सकता है कि क्या लेन-देन घटा है । हालाँकि, इन 3 संस्करणों में (मैंने केवल 2008 R2 पर परीक्षण किया है), गलत तरीके से रिपोर्ट नहींXACT_STATE()
करता है जब एक साथ उपयोग किया जाता है ।1
SELECT
@@SPID
यहां उल्लिखित व्यवहार के खिलाफ एक कनेक्ट बग दर्ज किया गया है, लेकिन "बाय डिजाइन" के रूप में बंद है: XACT_STATE () SQL 2012 में एक गलत लेनदेन स्थिति वापस कर सकता है । हालांकि, परीक्षण एक DMV से चयन करते समय किया गया था और यह निष्कर्ष निकाला गया था कि ऐसा करने से स्वाभाविक रूप से एक सिस्टम उत्पन्न लेनदेन होगा, कम से कम कुछ DMV के लिए। यह एमएस द्वारा अंतिम प्रतिक्रिया में भी कहा गया था कि:
ध्यान दें कि एक IF स्टेटमेंट, और FROM के बिना एक सेलेक्ट भी, एक ट्रांजैक्शन शुरू न करें।
उदाहरण के लिए, SELECT XACT_STATE () चल रहा है यदि आपके पास पहले से मौजूद लेन-देन नहीं है तो 0 वापस आ जाएगा।
उन बयानों को गलत उदाहरण दिया गया है:
SELECT @@TRANCOUNT AS [TRANCOUNT], XACT_STATE() AS [XACT_STATE], @@SPID AS [SPID];
GO
DECLARE @SPID INT;
SET @SPID = @@SPID;
SELECT @@TRANCOUNT AS [TRANCOUNT], XACT_STATE() AS [XACT_STATE], @SPID AS [SPID];
GO
इसलिए, नए कनेक्ट बग:
XACT_STATE () 1 का उपयोग करता है जब कुछ सिस्टम चर के साथ चयन में उपयोग किया जाता है, लेकिन बिना क्लाज के
कृपया ध्यान दें कि "XACT_STATE () SQL 2012 में एक गलत लेनदेन स्थिति लौटा सकता है" कनेक्ट आइटम सीधे ऊपर, Microsoft (अच्छी तरह से, प्रतिनिधि) राज्यों से जुड़ा हुआ है:
@@ ट्रैन्काउंट BEGIN TRAN स्टेटमेंट की संख्या लौटाता है। इस प्रकार यह एक विश्वसनीय संकेतक नहीं है कि क्या कोई सक्रिय लेनदेन है। XACT_STATE () भी 1 लौटाता है यदि एक सक्रिय ऑटोकॉमिट लेनदेन है, और इस प्रकार एक अधिक विश्वसनीय संकेतक है कि क्या कोई सक्रिय लेनदेन है।
हालाँकि, मुझे विश्वास नहीं करने का कोई कारण नहीं मिल सकता है @@TRANCOUNT
। निम्नलिखित परीक्षण से पता चलता है कि @@TRANCOUNT
वास्तव 1
में ऑटो-कमिट लेनदेन में वापस आता है :
--- begin setup
GO
CREATE PROCEDURE #TransactionInfo AS
SET NOCOUNT ON;
SELECT @@TRANCOUNT AS [TranCount],
XACT_STATE() AS [XactState];
GO
--- end setup
DECLARE @Test TABLE (TranCount INT, XactState INT);
SELECT * FROM @Test; -- no rows
EXEC #TransactionInfo; -- 0 for both fields
INSERT INTO @Test (TranCount, XactState)
EXEC #TransactionInfo;
SELECT * FROM @Test; -- 1 row; 1 for both fields
मैंने एक ट्रिगर के साथ एक असली टेबल पर भी परीक्षण किया और ट्रिगर के @@TRANCOUNT
भीतर सटीक रिपोर्ट किया, 1
भले ही कोई स्पष्ट लेनदेन शुरू नहीं हुआ था।
XACT_ABORT
करने के लिएON
याOFF
।