2011-02-14 15 views
7

में कैच ब्लॉक का प्रयास करें मुझे एक संग्रहीत प्रक्रिया का सामना करना पड़ा जिसमें अद्यतन प्रयास के तुरंत बाद निम्न त्रुटि हैंडलिंग ब्लॉक था। निम्नलिखित एसपी की आखिरी पंक्तियां थीं।टी-एसक्यूएल

क्या ऐसा करने का कोई फायदा है? ऐसा लगता है कि यह कोड सिर्फ उसी त्रुटि को पुनर्स्थापित कर रहा है, जिसे बिना किसी मूल्य के पकड़ा गया है और यदि कोड को पूरी तरह से ओमेट किया गया तो कोड संभावित रूप से 100% व्यवहार करेगा।

यदि TRY ब्लॉक को हटा दिया गया तो परिणामस्वरूप एसपी के व्यवहार में कोई अंतर होगा?

BEGIN CATCH 

SELECT @ErrMsg = ERROR_MESSAGE(), @ErrSev = ERROR_SEVERITY(), @ErrState = ERROR_STATE() 
     RAISERROR (@ErrMsg, @ErrSev, @ErrState) 

END CATCH 
+0

एकमात्र अंतर जो मैं सोच सकता हूं वह यह होगा कि लाइन नंबर की जानकारी और त्रुटि संख्या की जानकारी 'कैच' के बिना एक नया अपवाद फेंकने के बिना अधिक सटीक होगी, इसलिए यह वास्तव में मूल्य को घटाना प्रतीत होता है जहां तक ​​मैं देख सकता हूं। .. –

+0

मैं हमेशा एसक्यूएल जेनरेट त्रुटि संदेशों के बजाय फ्रंट एंड में एक कस्टम त्रुटि संदेश पसंद करना पसंद करता हूं। इस तरह से आपको तार्किक और साथ ही तकनीकी त्रुटि भी मिल जाएगी, जिसे आपने समझा और उल्लेख किया है। – Chris

उत्तर

2

इस तथ्य को छोड़कर कि किसी भी संदेश के हिस्से में "लाइन त्रुटि उत्पन्न हुई" रिजर्वर लाइन का संदर्भ देगी, न कि वास्तव में जिस त्रुटि पर त्रुटि हुई थी, वहां कोई अंतर नहीं होगा। ऐसा करने का मुख्य कारण @Chris कहते हैं, ताकि आप त्रुटि डेटा का प्रोग्रामेटिक रूप से उपयोग/कुशलतापूर्वक उपयोग कर सकें।

+0

त्रुटि संख्या भी खो जाएगी और '50000' –

+0

डैंग, आपके दाएं के रूप में रिपोर्ट की जाएगी। मैंने इसे बारीकी से नहीं पढ़ा, और माना [डह!] कि जो भी ऐसा करता है वह वास्तविक त्रुटि संख्या को जाल और ट्रैक करेगा। –

2

क्या हम आम तौर पर हमारे संग्रहीत प्रक्रिया में क्या इस

BEGIN CATCH 
    DECLARE @i_intErrorNo int   
    DECLARE @i_strErrorMsg nvarchar(1000)   
    DECLARE @i_strErrorProc nvarchar(1000)   
    DECLARE @i_intErrorLine int   

    SELECT @i_intErrorNo=Error_Number()   
    SELECT @i_strErrorMsg=Error_Message()   
    SELECT @i_strErrorProc=Error_Procedure()   
    SELECT @i_intErrorLine=Error_Line() 

    INSERT INTO error table ////// Insert statement. 

END CATCH 

तरह कैच ब्लॉक लिखने के लिए यह कुछ हम त्रुटि स्टोर करने के लिए ऐसा करने के लिए का उपयोग है। उपयोगकर्ता को उचित संदेश के लिए, मैं हमेशा त्रुटि के विस्तृत/आवश्यक कारण को दिखाने के लिए संग्रहीत प्रक्रिया में आउटपुट पैरामीटर का उपयोग करता हूं।

1

अगर आप msdn page for RAISERROR पर देखो तो आप इस सामान्य विवरण देखें:

एक त्रुटि संदेश उत्पन्न करता है और सत्र के लिए त्रुटि प्रसंस्करण आरंभ करता है। RAISERROR या तो उपयोगकर्ता द्वारा परिभाषित संदेश को sys.messages कैटलॉग में संग्रहीत किया जा सकता है या गतिशील रूप से एक संदेश बना सकता है। संदेश को कॉलिंग एप्लिकेशन या किसी संबंधित कैच को TRY के ब्लॉक में त्रुटि संदेश के रूप में वापस भेजा गया है ... कैच निर्माण।

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

+0

ERROR_MESSAGE() द्वारा लौटाई गई स्ट्रिंग के भीतर "अतिरिक्त जानकारी" शामिल है। इसे खराब करने के लिए, आपको इसे अपने स्वयं के कम-विस्तारित त्रुटि संदेश से बदलना होगा, जो यह दिनचर्या नहीं करता है। –

0

नीचे दिखाए गए एक सूक्ष्म अंतर है।

पहले सेटअप निम्नलिखित:

CREATE TABLE TMP 
(ROW_ID int NOT NULL, 
    ALTER TABLE TMP ADD CONSTRAINT PK_TMP PRIMARY KEY CLUSTERED (ROW_ID) 
) 
GO 
CREATE PROC pTMP1 
AS 
BEGIN TRY 
    INSERT INTO TMP VALUES(1) 
    INSERT INTO TMP VALUES(1) 
    INSERT INTO TMP VALUES(2) 
END TRY 
BEGIN CATCH 
    DECLARE @ErrMsg varchar(max)= ERROR_MESSAGE(), 
      @ErrSev int = ERROR_SEVERITY(), 
      @ErrState int = ERROR_STATE() 
     RAISERROR (@ErrMsg, @ErrSev, @ErrState) 
END CATCH 
GO 
CREATE PROC pTMP2 
AS 
    INSERT INTO TMP VALUES(1) 
    INSERT INTO TMP VALUES(1) 
    INSERT INTO TMP VALUES(2) 
GO 

अब चलाने के निम्नलिखित:

SET NOCOUNT ON 
DELETE TMP 
exec pTMP1 
SELECT * FROM TMP 
DELETE TMP 
exec pTMP2 
SELECT * FROM TMP 
SET NOCOUNT OFF 
--Cleanup 
DROP PROCEDURE pTMP1 
DROP PROCEDURE pTMP2 
DROP TABLE TMP 

आप निम्न परिणाम प्राप्त करना चाहिए:

Msg 50000, Level 14, State 1, Procedure pTMP1, Line 12 
Violation of PRIMARY KEY constraint 'PK_TMP'. Cannot insert duplicate key in object 'dbo.TMP'. The duplicate key value is (1). 
ROW_ID 
----------- 
1 

Msg 2627, Level 14, State 1, Procedure pTMP2, Line 4 
Violation of PRIMARY KEY constraint 'PK_TMP'. Cannot insert duplicate key in object 'dbo.TMP'. The duplicate key value is (1). 
The statement has been terminated. 
ROW_ID 
----------- 
1 
2 

सूचना है कि TRY..CATCH संस्करण निष्पादित नहीं हुआ तीसरा INSERT कथन, जबकि pTMP2 proc किया। ऐसा इसलिए होता है क्योंकि जैसे ही त्रुटि होती है, नियंत्रण CATCH पर कूद जाता है।

नोट: pTMP2 का व्यवहार XACT_ABORT सेटिंग से प्रभावित होता है।

निष्कर्ष

प्रदर्शन के रूप में TRY..CATCH उपयोग करने का लाभ कैसे आप अपने लेन-देन सीमाओं का प्रबंधन पर निर्भर करता है।

  • यदि आप किसी भी त्रुटि पर रोल-बैक करते हैं, तो परिवर्तन पूर्ववत हो जाएंगे। लेकिन यह दुष्प्रभावों जैसे साइड इफेक्ट्स को खत्म नहीं करता है। नोट: यदि WITH(NOLOCK) का उपयोग करते हुए एक अलग सत्र TMP से पूछताछ करता है तो यह अस्थायी परिवर्तन का भी निरीक्षण कर सकता है।
  • हालांकि, यदि आप किसी लेन-देन को वापस रोल करने का इरादा नहीं रखते हैं, तो आप पाएंगे कि पहले त्रुटि के बावजूद कुछ डेटा परिवर्तन लागू होने से रोकने के लिए तकनीक काफी महत्वपूर्ण है।
संबंधित मुद्दे