THROW

2015-05-17 6 views
6

का उपयोग करते समय SQL सर्वर मेरे लेन-देन को वापस चलाता है मेरे पास मेरी एक तालिका में एक INSERT ट्रिगर है जो एक डुप्लिकेट पाता है जब थ्रू को जारी करता है। समस्या यह है कि मेरे लेन-देन इस बिंदु पर पूरी तरह से लुढ़कते प्रतीत होते हैं - यह एक समस्या है, जब मैं लेनदेन वापस ले जाता हूं तो मैं नियंत्रण करना चाहता हूं।THROW

मुद्दा इस स्क्रिप्ट के साथ फिर से बनाया जा सकता है:

CREATE TABLE xTable (
     id int identity not null 
) 
go 
create trigger xTrigger on xTable after insert as 
print 'inserting...'; 
throw 1600000, 'blah', 1 
go 

begin tran 
insert into xTable default values 
rollback tran 

go 
drop table xTable 

आप रोलबैक ट्रॅन चलाते हैं - यह आपको बता वहाँ कोई शुरू है ट्रॅन होगा।

यदि मैं 'सामान्य' अपवाद (जैसे SELECT 1/0) के लिए THROW को स्वैप करता हूं तो लेनदेन वापस नहीं चलाया जाता है।

मैंने xact_abort ध्वज की जांच की है - और यह बंद है।

SSMS

सराहना की किसी भी मदद की, धन्यवाद के माध्यम से

एसक्यूएल सर्वर 2012 और परीक्षण का उपयोग करना।

संपादित लेख @Dan गुज़मान द्वारा पोस्ट की पढ़ने के बाद, मैं निम्नलिखित निष्कर्ष/सारांश के लिए आया था ...

एसक्यूएल सर्वर स्वचालित रूप से चलाता में XACT_ABORT पर तय करता है।

मेरा उदाहरण (ऊपर) मेरी स्थिति को स्पष्ट नहीं करता है - असल में मैं एक ट्रिगर का उपयोग करके एक विस्तारित बाधा बना रहा हूं।

मेरा उपयोग केस विकसित हुआ था, मैं समान इकाई परीक्षण (वास्तविक दुनिया की स्थिति नहीं, और अच्छी इकाई परीक्षण अभ्यास नहीं) में कई स्थितियों का परीक्षण करने की कोशिश कर रहा था।

विस्तारित बाधा की जांच और ट्रिगर में त्रुटि फेंकना सही है, हालांकि कोई वास्तविक स्थिति नहीं है जिसमें मैं लेनदेन को रोलबैक नहीं करना चाहता।

यह किसी विशेष मामले के लिए ट्रिगर के अंदर SET XACT_ABORT OFF के लिए उपयोगी हो सकता है; लेकिन आपका लेनदेन अभी भी सामान्य बैच-निरस्त करने वाली त्रुटियों (जैसे डेडलॉक्स) द्वारा कमजोर हो जाएगा।

ऐतिहासिक कारणों को छोड़कर, मैं SQL सर्वर के प्रबंधन से सहमत नहीं हूं; सिर्फ इसलिए कि कोई मौजूदा स्थिति नहीं है जिसमें आप लेनदेन जारी रखना चाहते हैं, इसका मतलब यह नहीं है कि ऐसी स्थिति उत्पन्न नहीं हो सकती है। मैं लेनदेन की अखंडता को बनाए रखने के लिए SQL सर्वर सेट करने में सक्षम एक देखना चाहता हूं, यदि आपके चुने हुए आर्किटेक्चर के पास मूल रूप से लेन-देन को सख्ती से प्रबंधित करना है, यानी "वह अकेला लेनदेन शुरू करता है, इसे पूरा करना होगा"। यह, सामान्य विफल-सुरक्षित से अलग, उदा। यदि सिस्टम विफलता इत्यादि के कारण आपका कोड कभी नहीं पहुंचा है।

उत्तर

4

THROWTRY/CATCH (https://msdn.microsoft.com/en-us/library/ee677615.aspx) के दायरे के बाहर बैच को समाप्त कर देगा। यहां निहितार्थ यह है कि सम्मिलित होने के बाद बयानों सहित बैच की कोई और प्रक्रिया नहीं होती है। आपको के साथ अपने INSERT को घेरने की आवश्यकता होगी या THROW के बजाय RAISERROR का उपयोग करें।

टी-एसक्यूएल त्रुटि प्रबंधन एक बड़ा और जटिल विषय है। मेरा सुझाव है कि आप एरलैंड सोमरस्कोग द्वारा त्रुटि-हैंडलिंग लेखों की श्रृंखला को समझें: http://www.sommarskog.se/error_handling/Part1.html। यहां सबसे प्रासंगिक विषय Can I Prevent the Trigger from Rolling Back the Transaction?http://www.sommarskog.se/error_handling/Part3.html#Triggers है। सर्वोत्तम प्रथाओं के दृष्टिकोण से दूर लेना यह है कि यदि आप रोलबैक के बिना ट्रिगर में व्यवसाय नियमों को लागू करते हैं तो ट्रिगर सही समाधान नहीं होते हैं।

+0

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

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

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