2009-04-07 12 views
27

हमारे पास एक बड़ा एप्लीकेशन मुख्य रूप से SQL Server 7.0 में लिखा गया है, जहां सभी डेटाबेस कॉल संग्रहीत प्रक्रियाओं के लिए हैं। अब हम SQL Server 2005 चला रहे हैं, जो अधिक टी-एसक्यूएल सुविधाएं प्रदान करता है।एसक्यूएल सर्वर टी-एसक्यूएल त्रुटि हैंडलिंग का सबसे अच्छा अभ्यास उपयोग क्या है?

बस हर चयन, INSERT, अद्यतन, और हटाएं, @@ ROWCOUNT और @@ ERROR स्थानीय चर में कब्जा कर लिया गया है और समस्याओं के लिए मूल्यांकन किया गया है।

  • त्रुटि संदेश उत्पादन पैरामीटर सेट कर दिया जाता
  • रोलबैक (यदि आवश्यक हो) किया जाता है
  • जानकारी लिखा है (सम्मिलित करें) तालिका लॉग इन करने के
  • एक साथ वापसी: यदि कोई समस्या निम्नलिखित किया जाता है त्रुटि संख्या, इस प्रक्रिया के लिए अद्वितीय

वे सभी पंक्तियों की जांच नहीं करते (केवल जब यह जाना जाता है) (सकारात्मक यदि घातक, नकारात्मक चेतावनी है) और कुछ कम या ज्यादा लॉग/डिबग जानकारी के साथ भिन्न होते हैं। साथ ही, पंक्ति तर्क कुछ समय तर्क त्रुटि से विभाजित होता है (उन अद्यतनों पर जहां WHERE खंड में एक समवर्ती क्षेत्र की जांच की जाती है, पंक्ति = 0 का अर्थ है कि किसी और ने डेटा अपडेट किया है)।

SELECT, INSERT, UPDATE, or DELETE 

SELECT @[email protected]@ERROR, @[email protected]@ROWCOUNT 
IF @Rows!=1 OR @Error!=0 
BEGIN 
    SET @ErrorMsg='ERROR 20, ' + ISNULL(OBJECT_NAME(@@PROCID), 'unknown') 
           + ' - unable to ???????? the ????.' 
    IF @@TRANCOUNT >0 
    BEGIN 
     ROLLBACK 
    END 

    SET @LogInfo=ISNULL(@LogInfo,'')+'; '+ISNULL(@ErrorMsg,'')+ 
     + ' @YYYYY='  +dbo.FormatString(@YYYYY) 
     +', @XXXXX='  +dbo.FormatString(@XXXXX) 
     +', Error='   +dbo.FormatString(@Error) 
     +', Rows='   +dbo.FormatString(@Rows) 

    INSERT INTO MyLogTable (...,Message) VALUES (....,@LogInfo) 

    RETURN 20 

END 

मैं की जगह हम कैसे TRY-पकड़ने T-SQL के साथ ऐसा कर रहा हूँ में: हालांकि, यहां एक काफी सामान्य उदाहरण है। मैंने TRY...CATCH (Transact-SQL) वाक्यविन्यास के बारे में पढ़ा है, इसलिए बस इसके कुछ सारांश पोस्ट न करें। मैं किसी भी अच्छे विचारों की तलाश में हूं और सर्वोत्तम हमारी त्रुटि हैंडलिंग विधियों को करने या सुधारने के लिए। इसे टी-एसक्यूएल त्रुटि प्रबंधन के किसी भी अच्छे या सर्वोत्तम अभ्यास के उपयोग की कोशिश करने की ज़रूरत नहीं है।

उत्तर

29

आप इस पढ़ना चाहिए:

http://www.sommarskog.se/error-handling-I.html

मुझे लगता है कि लिंक अत्यधिक पर्याप्त की अनुशंसा नहीं कर सकते हैं। यह थोड़ा लंबा है, लेकिन एक अच्छे तरीके से।

सामने एक अस्वीकरण है कि इसे मूल रूप से SQL Server 2000 के लिए लिखा गया था, लेकिन इसमें SQL Server 2005+ में नई कोशिश/पकड़ त्रुटि प्रबंधन क्षमताओं को भी शामिल किया गया है।

+0

मुझे लगता है कि यह SQL सर्वर 2005 सामग्री पर छोड़ देता है, लेकिन वैसे भी उत्कृष्ट है। और बाकी की अपनी साइट भी। – gbn

+0

SQL सर्वर 2005+ के लिए यहां प्रारंभ करें http://www.sommarskog.se/error_handling/Part1.html –

3

ऐसा लगता है कि आपके पास पहले से ही बहुत अच्छा संभाल है। मुझे संदेह है कि आप वहां से 95% से अधिक SQL प्रोग्रामर कर रहे हैं।

आप कुछ रोचक जानकारी यहाँ मिल चाहिए:

एक [असंबंधित] सुझाव: '! =' के बजाय '<>' का उपयोग शुरू करें।

[* एसक्यूएल जंकियां चली गई हैं, इसलिए दूसरा लेख उपलब्ध नहीं है। मैं इसे कहीं भी पुनः प्रकाशित करने और लिंक को अपडेट करने का प्रयास करूंगा।]

+0

'! =' के बजाय '<>' का उपयोग क्यों करें? –

+1

एएनएसआई स्पेक <> निर्दिष्ट करता है। कई डीबी भी समर्थन करते हैं! =, लेकिन यह मानक नहीं है। –

+0

http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt अनुभाग देखें 5.2 –

6

त्रुटि प्रबंधन के लिए पत्थर सर्वोत्तम प्रथाओं में कोई सेट नहीं है। यह सब आपकी आवश्यकताओं के अनुरूप आता है और सुसंगत है।

यहां एक तालिका का एक नमूना है और संग्रहित प्रक्रिया है जो फोन नंबर स्टोर करती है।

SET ANSI_NULLS ON 
    GO 
    SET QUOTED_IDENTIFIER ON 
    GO 
    SET ANSI_PADDING ON 
    GO 
    CREATE TABLE [dbo].[Phone](
     [ID] [int] IDENTITY(1,1) NOT NULL, 
     [Phone_Type_ID] [int] NOT NULL, 
     [Area_Code] [char](3) NOT NULL, 
     [Exchange] [char](3) NOT NULL, 
     [Number] [char](4) NOT NULL, 
     [Extension] [varchar](6) NULL, 
    CONSTRAINT [PK_Phone] PRIMARY KEY CLUSTERED 
    (
     [ID] ASC 
    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
    ) ON [PRIMARY] 

    GO 
    SET ANSI_PADDING OFF 
    GO 
    /**/ 

    CREATE PROCEDURE [dbo].[usp_Phone_INS] 
     @Customer_ID INT 
     ,@Phone_Type_ID INT 
     ,@Area_Code CHAR(3) 
     ,@Exchange CHAR(3) 
     ,@Number CHAR(4) 
     ,@Extension VARCHAR(6) 
    AS 
    BEGIN 
     SET NOCOUNT ON; 

     DECLARE @Err INT, @Phone_ID INT 

     BEGIN TRY 
      INSERT INTO Phone 
       (Phone_Type_ID, Area_Code, Exchange, Number, Extension) 
      VALUES 
       (@Phone_Type_ID, @Area_Code, @Exchange, @Number, @Extension) 
      SET @Err = @@ERROR 
      SET @Phone_ID = SCOPE_IDENTITY() 
      /* 
       Custom error handling expected by the application. 
       If Err = 0 then its good or no error, if its -1 or something else then something bad happened. 
      */ 
      SELECT ISNULL(@Err,-1) AS Err, @Phone_ID 
     END TRY 
     BEGIN CATCH 
      IF (XACT_STATE() <> 0) 
       BEGIN 
        ROLLBACK TRANSACTION 
       END 

      /* 
       Add your own custom error handling here to return the passed in paramters. 
       I have removed my custom error halding code that deals with returning the passed in parameter values. 
      */ 

      SELECT ERROR_NUMBER() AS Err, ISNULL(@Phone_ID,-1) AS ID 
     END CATCH 
    END 
17

वर्तमान में हम (आप लेन-देन सामान बाहर छोड़ सकता, यदि आप एक DDL कथन जैसे में इसकी आवश्यकता नहीं है) है कि हम किसी भी प्रश्न पर अमल के लिए इस टेम्पलेट का उपयोग करें:

BEGIN TRANSACTION 
BEGIN TRY 
    // do your SQL statements here 

    COMMIT TRANSACTION 
END TRY 
BEGIN CATCH 
    SELECT 
     ERROR_NUMBER() AS ErrorNumber, 
     ERROR_SEVERITY() AS ErrorSeverity, 
     ERROR_STATE() AS ErrorState, 
     ERROR_PROCEDURE() AS ErrorProcedure, 
     ERROR_LINE() AS ErrorLine, 
     ERROR_MESSAGE() AS ErrorMessage 

    ROLLBACK TRANSACTION 
END CATCH 
बेशक

, आप आसानी से पकड़े गए अपवाद को अपनी त्रुटि लॉग तालिका में डाल सकते हैं।

यह हमारे लिए वास्तव में अच्छा काम करता है। आप कोड जनरेशन (उदा। कोडस्मिथ) या कुछ कस्टम सी # कोड का उपयोग करके अपने पुराने संग्रहित प्रोसेस से कुछ रूपांतरण को स्वचालित रूप से स्वचालित रूप से स्वचालित कर सकते हैं।

+10

TRY ब्लॉक के बाहर लेनदेन क्यों शुरू करें, क्या कोई फायदा है? एमएसडीएन के सभी उदाहरण BEGIN TRAN को TRY http://technet.microsoft.com/en-us/library/ms179296%28v=sql.105%29.aspx – Davos

+2

XACT_STATE के अंदर पहले कथन के रूप में दिखाते हैं, तो इसका उपयोग करने पर भी विचार किया जाना चाहिए लेनदेन: https://msdn.microsoft.com/en-us/library/ms189797.aspx –

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