परिचय
हम अनुप्रयोगों को डिजाइन और विकसित करने के लिए कितनी भी कोशिश कर लें, त्रुटियां हमेशा होती रहेंगी। दो सामान्य श्रेणियां हैं - सिंटैक्स या तार्किक त्रुटियां या तो प्रोग्रामेटिक त्रुटियां या गलत डेटाबेस डिज़ाइन के परिणाम हो सकती हैं। अन्यथा, गलत उपयोगकर्ता इनपुट के कारण आपको त्रुटि मिल सकती है।
टी-एसक्यूएल (एसक्यूएल सर्वर प्रोग्रामिंग भाषा) दोनों प्रकार की त्रुटि को संभालने की अनुमति देता है। आप एप्लिकेशन को डिबग कर सकते हैं और तय कर सकते हैं कि भविष्य में बग से बचने के लिए आपको क्या करना है।
अधिकांश अनुप्रयोगों के लिए आवश्यक है कि आप त्रुटियों को लॉग करें, उपयोगकर्ता के अनुकूल त्रुटि-रिपोर्टिंग लागू करें, और जब संभव हो, त्रुटियों को संभालें और एप्लिकेशन निष्पादन जारी रखें।
उपयोगकर्ता कथन स्तर पर त्रुटियों को संभालते हैं। इसका मतलब है कि जब आप SQL कमांड का एक बैच चलाते हैं, और समस्या अंतिम स्टेटमेंट में होती है, तो उस समस्या से पहले की हर चीज डेटाबेस के लिए निहित लेनदेन के रूप में प्रतिबद्ध हो जाएगी। यह वह नहीं हो सकता जो आप चाहते हैं।
रिलेशनल डेटाबेस बैच स्टेटमेंट निष्पादन के लिए अनुकूलित हैं। इस प्रकार, आपको एक इकाई के रूप में बयानों के एक बैच को निष्पादित करने की आवश्यकता है और यदि एक कथन विफल हो जाता है तो सभी कथनों को विफल कर दें। आप लेनदेन का उपयोग करके इसे पूरा कर सकते हैं। यह लेख त्रुटि प्रबंधन और लेन-देन दोनों पर ध्यान केंद्रित करेगा, क्योंकि ये विषय दृढ़ता से जुड़े हुए हैं।
SQL त्रुटि प्रबंधन
अपवादों को अनुकरण करने के लिए, हमें उन्हें दोहराने योग्य तरीके से उत्पन्न करने की आवश्यकता है। आइए सबसे सरल उदाहरण से शुरू करें - शून्य से भाग:
SELECT 1/0
आउटपुट फेंकी गई त्रुटि का वर्णन करता है - आने वाली शून्य त्रुटि से विभाजित करें . लेकिन इस त्रुटि को उपयोगकर्ता के अनुकूल संदेश उत्पन्न करने के लिए नियंत्रित, लॉग या अनुकूलित नहीं किया गया था।
अपवाद प्रबंधन की शुरुआत उन बयानों को डालने से होती है जिन्हें आप BEGIN TRY…END TRY ब्लॉक में निष्पादित करना चाहते हैं।
SQL सर्वर BEGIN CATCH…END CATCH ब्लॉक में त्रुटियों को संभालता है (कैच) करता है, जहां आप त्रुटि लॉगिंग या प्रसंस्करण के लिए कस्टम तर्क दर्ज कर सकते हैं।
BEGIN CATCH स्टेटमेंट को END TRY स्टेटमेंट के तुरंत बाद फॉलो करना होता है। पहली त्रुटि होने पर निष्पादन को TRY ब्लॉक से CATCH ब्लॉक में भेज दिया जाता है।
यहां आप तय कर सकते हैं कि त्रुटियों को कैसे संभालना है, क्या आप उठाए गए अपवादों के बारे में डेटा लॉग करना चाहते हैं या उपयोगकर्ता के अनुकूल संदेश बनाना चाहते हैं।
SQL सर्वर में अंतर्निहित कार्य हैं जो आपको त्रुटि विवरण निकालने में मदद कर सकते हैं:
- ERROR_NUMBER():SQL त्रुटियों की संख्या लौटाता है।
- ERROR_SEVERITY():गंभीरता का स्तर लौटाता है जो सामने आई समस्या के प्रकार और उसके स्तर को दर्शाता है। 11 से 16 के स्तर को उपयोगकर्ता द्वारा नियंत्रित किया जा सकता है।
- ERROR_STATE ():त्रुटि स्थिति संख्या देता है और फेंके गए अपवाद के बारे में अधिक विवरण देता है। आप विशिष्ट त्रुटि विवरण के लिए Microsoft ज्ञानकोष को खोजने के लिए त्रुटि संख्या का उपयोग करते हैं।
- ERROR_PROCEDURE():उस प्रक्रिया या ट्रिगर का नाम देता है जिसमें त्रुटि उत्पन्न हुई थी, या यदि प्रक्रिया या ट्रिगर में त्रुटि नहीं हुई तो NULL देता है।
- ERROR_LINE():वह लाइन नंबर देता है जिस पर त्रुटि हुई। यह प्रक्रियाओं की पंक्ति संख्या या ट्रिगर या बैच में पंक्ति संख्या हो सकती है।
- ERROR_MESSAGE():त्रुटि संदेश का पाठ लौटाता है।
निम्न उदाहरण दिखाता है कि त्रुटियों को कैसे संभालना है। पहले उदाहरण में शून्य से भाग . है त्रुटि, जबकि दूसरा कथन सही है।
BEGIN TRY
PRINT 1/0
SELECT 'Correct text'
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ERR_NO
, ERROR_SEVERITY() AS ERR_SEV
, ERROR_STATE() AS ERR_STATE
, ERROR_LINE() AS ERR_LINE
, ERROR_MESSAGE() AS ERR_MESSAGE
END CATCH
यदि दूसरा कथन त्रुटि प्रबंधन के बिना निष्पादित किया जाता है ('सही पाठ' चुनें), यह सफल होगा।
चूंकि हम TRY-CATCH ब्लॉक में कस्टम एरर हैंडलिंग को लागू करते हैं, प्रोग्राम का निष्पादन पहले स्टेटमेंट में त्रुटि के बाद CATCH ब्लॉक को पास कर दिया जाता है, और दूसरा स्टेटमेंट कभी भी निष्पादित नहीं किया गया था।
इस तरह, आप उपयोगकर्ता को दिए गए पाठ को संशोधित कर सकते हैं और नियंत्रित कर सकते हैं कि यदि कोई त्रुटि बेहतर होती है तो क्या होता है। उदाहरण के लिए, हम आगे के विश्लेषण के लिए लॉग टेबल में त्रुटियों को लॉग करते हैं।
लेन-देन का उपयोग करना
व्यावसायिक तर्क यह निर्धारित कर सकता है कि दूसरा कथन विफल होने पर पहले कथन का सम्मिलन विफल हो जाता है, या आपको दूसरे कथन की विफलता पर पहले कथन के परिवर्तनों को दोहराने की आवश्यकता हो सकती है। लेन-देन का उपयोग करने से आप बयानों के एक बैच को एक इकाई के रूप में निष्पादित कर सकते हैं जो या तो विफल हो जाता है या सफल हो जाता है।
निम्नलिखित उदाहरण लेनदेन के उपयोग को दर्शाता है।
सबसे पहले, हम संग्रहीत डेटा का परीक्षण करने के लिए एक तालिका बनाते हैं। फिर हम TRY-CATCH ब्लॉक के अंदर दो लेन-देन का उपयोग करते हैं ताकि लेन-देन का एक हिस्सा विफल होने पर होने वाली चीजों का अनुकरण किया जा सके।
हम CATCH स्टेटमेंट का उपयोग XACT_STATE () स्टेटमेंट के साथ करेंगे। XACT_STATE () फ़ंक्शन का उपयोग यह जांचने के लिए किया जाता है कि लेनदेन अभी भी मौजूद है या नहीं। यदि लेन-देन स्वचालित रूप से वापस आ जाता है, तो रोलबैक लेनदेन एक नया अपवाद उत्पन्न करेगा।
नीचे दिए गए कोड पर लूटपाट करें:
-- CREATE TABLE TEST_TRAN(VALS INT)
BEGIN TRY
BEGIN TRANSACTION
INSERT INTO TEST_TRAN(VALS) VALUES(1);
COMMIT TRANSACTION
BEGIN TRANSACTION
INSERT INTO TEST_TRAN(VALS) VALUES(2);
INSERT INTO TEST_TRAN(VALS) VALUES('A');
INSERT INTO TEST_TRAN(VALS) VALUES(3);
COMMIT TRANSACTION
END TRY
BEGIN CATCH
IF XACT_STATE() > 0 ROLLBACK TRANSACTION
SELECT ERROR_NUMBER() AS ERR_NO
, ERROR_SEVERITY() AS ERR_SEV
, ERROR_STATE() AS ERR_STATE
, ERROR_LINE() AS ERR_LINE
, ERROR_MESSAGE() AS ERR_MESSAGE
END CATCH
SELECT * FROM TEST_TRAN
-- DROP TABLE TEST_TRAN
छवि TEST_TRAN तालिका और त्रुटि संदेशों में मान दिखाती है:
जैसा कि आप देखते हैं, केवल पहला मूल्य प्रतिबद्ध था। दूसरे लेन-देन में, हमें दूसरी पंक्ति में एक प्रकार की रूपांतरण त्रुटि हुई। इस प्रकार, पूरा बैच वापस लुढ़क गया।
इस तरह, आप नियंत्रित कर सकते हैं कि कौन सा डेटा डेटाबेस में प्रवेश करता है और बैचों को कैसे संसाधित किया जाता है।
SQL में कस्टम त्रुटि संदेश जनरेट करना
कभी-कभी, हम कस्टम त्रुटि संदेश बनाना चाहते हैं। आमतौर पर, वे परिदृश्यों के लिए होते हैं जब हम जानते हैं कि कोई समस्या हो सकती है। हम यह कहते हुए अपने स्वयं के कस्टम संदेश तैयार कर सकते हैं कि तकनीकी विवरण दिखाए बिना कुछ गलत हुआ है। उसके लिए, हम THROW कीवर्ड का उपयोग कर रहे हैं।
BEGIN TRY
IF ( SELECT COUNT(sys.all_objects) > 1 )
THROW ‘More than one object is ALL_OBJECTS system table’
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ERR_NO
, ERROR_SEVERITY() AS ERR_SEV
, ERROR_STATE() AS ERR_STATE
, ERROR_LINE() AS ERR_LINE
, ERROR_MESSAGE() AS ERR_MESSAGE
END CATCH
या, हम त्रुटि निगरानी और रिपोर्टिंग के वर्गीकरण और निरंतरता के लिए कस्टम त्रुटि संदेशों की एक सूची चाहते हैं। SQL सर्वर हमें त्रुटि संदेश कोड, गंभीरता और स्थिति को पूर्वनिर्धारित करने की अनुमति देता है।
कस्टम त्रुटि संदेशों को जोड़ने के लिए "sys.sp_addmessage" नामक एक संग्रहीत कार्यविधि का उपयोग किया जाता है। हम इसका उपयोग कई स्थानों पर त्रुटि संदेश को कॉल करने के लिए कर सकते हैं।
हम RAISERROR को कॉल कर सकते हैं और एक ही त्रुटि विवरण को कोड में कई स्थानों पर हार्ड-कोडिंग करने के बजाय एक पैरामीटर के रूप में संदेश संख्या भेज सकते हैं।
नीचे से चयनित कोड को निष्पादित करके, हम SQL सर्वर में कस्टम त्रुटि जोड़ रहे हैं, इसे बढ़ा रहे हैं, और फिर sys.sp_dropmessage का उपयोग कर रहे हैं निर्दिष्ट उपयोगकर्ता-परिभाषित त्रुटि संदेश को छोड़ने के लिए:
exec sys.sp_addmessage @msgnum=55000, @severity = 11,
@msgtext = 'My custom error message'
GO
RAISERROR(55000,11,1)
GO
exec sys.sp_dropmessage @msgnum=55000
GO
साथ ही, हम नीचे दिए गए क्वेरी फॉर्म को निष्पादित करके SQL सर्वर में सभी संदेशों को देख सकते हैं। हमारा कस्टम त्रुटि संदेश परिणामसेट में पहले आइटम के रूप में दिखाई देता है:
SELECT * FROM master.dbo.sysmessages
त्रुटियों को लॉग करने के लिए एक सिस्टम बनाएं
बाद में डिबगिंग और प्रोसेसिंग के लिए त्रुटियों को लॉग करना हमेशा उपयोगी होता है। आप इन लॉग टेबल पर ट्रिगर भी डाल सकते हैं और यहां तक कि एक ईमेल खाता भी सेट कर सकते हैं और त्रुटि होने पर लोगों को सूचित करने के तरीके में थोड़ा रचनात्मक हो सकते हैं।
त्रुटियों को लॉग करने के लिए, हम DBError_Log . नामक एक तालिका बनाते हैं , जिसका उपयोग लॉग विवरण डेटा को संग्रहीत करने के लिए किया जा सकता है:
CREATE TABLE DBError_Log
(
DBError_Log_ID INT IDENTITY(1, 1) PRIMARY KEY,
UserName VARCHAR(100),
ErrorNumber INT,
ErrorState INT,
ErrorSeverity INT,
ErrorLine INT,
ErrorProcedure VARCHAR(MAX),
ErrorMessage VARCHAR(MAX),
ErrorDateTime DATETIME
);
लॉगिंग तंत्र का अनुकरण करने के लिए, हम GenError . बना रहे हैं संग्रहीत कार्यविधि जो शून्य से भाग . उत्पन्न करती है त्रुटि करता है और त्रुटि को DBError_Log . में लॉग करता है तालिका:
CREATE PROCEDURE dbo.GenError
AS
BEGIN TRY
SELECT 1/0
END TRY
BEGIN CATCH
INSERT INTO dbo.DBError_Log
VALUES
(SUSER_SNAME(),
ERROR_NUMBER(),
ERROR_STATE(),
ERROR_SEVERITY(),
ERROR_LINE(),
ERROR_PROCEDURE(),
ERROR_MESSAGE(),
GETDATE()
);
END CATCH
GO
EXEC dbo.GenError
SELECT * FROM dbo.DBError_Log
DBError_Log तालिका में त्रुटि को डीबग करने के लिए आवश्यक सभी जानकारी है। साथ ही, यह उस प्रक्रिया के बारे में अतिरिक्त जानकारी प्रदान करता है जिसके कारण त्रुटि हुई। हालांकि यह एक मामूली उदाहरण की तरह लग सकता है, आप इस तालिका को अतिरिक्त फ़ील्ड के साथ बढ़ा सकते हैं या इसे कस्टम-निर्मित अपवादों से भरने के लिए इसका उपयोग कर सकते हैं।
निष्कर्ष
यदि हम अनुप्रयोगों को बनाए रखना और डिबग करना चाहते हैं, तो हम कम से कम रिपोर्ट करना चाहते हैं कि कुछ गलत हो गया है और इसे हुड के नीचे भी लॉग इन करना है। जब हमारे पास लाखों उपयोगकर्ताओं द्वारा उपयोग किया जाने वाला उत्पादन-स्तर का एप्लिकेशन होता है, तो लगातार और रिपोर्ट करने योग्य त्रुटि प्रबंधन रनटाइम में मुद्दों को डीबग करने की कुंजी है।
जबकि हम मूल त्रुटि को डेटाबेस त्रुटि लॉग में लॉग कर सकते हैं, उपयोगकर्ताओं को एक अधिक अनुकूल संदेश देखना चाहिए। इस प्रकार, कस्टम त्रुटि संदेशों को लागू करना एक अच्छा विचार होगा जो कॉलिंग एप्लिकेशन पर फेंके जाते हैं।
आप जो भी डिज़ाइन लागू करते हैं, आपको लॉग इन करना होगा और उपयोगकर्ता और सिस्टम अपवादों को संभालना होगा। SQL सर्वर के साथ यह कार्य मुश्किल नहीं है, लेकिन आपको शुरुआत से ही इसकी योजना बनानी होगी।
पहले से ही उत्पादन में चल रहे डेटाबेस पर त्रुटि प्रबंधन संचालन जोड़ने से गंभीर कोड रीफैक्टरिंग और हार्ड-टू-फाइंड प्रदर्शन समस्याएं शामिल हो सकती हैं।