2010-01-24 8 views
17

क्या आपको लगता है कि टी-एसक्यूएल में लेनदेन लिखने का एक बेहतर तरीका है? क्या कोई बेहतर दृष्टिकोण है जो इस लेनदेन का उपयोग करने वाले अनुप्रयोग की रखरखाव और प्रदर्शन में सुधार करता है?टी-एसक्यूएल में एक लेनदेन लिखना और त्रुटि प्रबंधन

-- Description: Insert email Receiver under specified subject 
-- ============================================= 
ALTER PROCEDURE [Contact].[Receiver_stpInsert] 
    @First_Name nvarchar(30), 
    @Last_Name nvarchar(30), 
    @Email varchar(60), 
    @Subject_Id int 
AS 
BEGIN 
    SET NOCOUNT ON; 

    DECLARE @error_num int; 


    BEGIN TRANSACTION 

    INSERT INTO Contact.Receiver(First_Name, Last_Name, Email) VALUES(@First_Name, @Last_Name, @Email); 

    SET @error_num = @@ERROR; 
    IF (@error_num <> 0) 
     BEGIN 
      ROLLBACK; 
      RETURN; 
     END 

    DECLARE @rec_record_id int; 
    SET @rec_record_id = (SELECT Record_Id FROM Contact.Receiver WHERE Email = @Email); 

    SET @error_num = @@ERROR; 
    IF (@error_num <> 0) 
     BEGIN 
      ROLLBACK; 
      RETURN; 
     END 

    INSERT INTO Contact.Receiver_Subject(Receiver_Id, Subject_Id) VALUES(@rec_record_id, @Subject_Id); 

    SET @error_num = @@ERROR; 
    IF (@error_num <> 0) 
     BEGIN 
      ROLLBACK; 
      RETURN; 
     END 

    SET @error_num = @@ERROR; 
    IF (@error_num <> 0) 
     BEGIN 
      ROLLBACK; 
      RETURN; 
     END 
    ELSE 
     BEGIN 
      Commit; 

     END 

END 

उत्तर

33

आप एसक्यूएल 2005 उपयोग कर रहे हैं या बाद में, आप TRY...CATCH ब्लॉक का उपयोग कर सकते, इस तरह:

BEGIN TRY 
    BEGIN TRANSACTION; 

    INSERT INTO Contact.Receiver(First_Name, Last_Name, Email) VALUES (@First_Name, @Last_Name, @Email); 
    ... other inserts etc 
    ... 
    COMMIT TRANSACTION; 
END TRY 
BEGIN CATCH 
    IF @@TRANCOUNT > 0 
     ROLLBACK TRANSACTION; 
END CATCH; 

इस तरह, आप कोड की जाँच का एक ही ब्लॉक दोहरा नहीं रखते @ @ERROR। त्रुटि की संख्या देता है

  • ERROR_NUMBER(): यदि आप को पता है कि त्रुटि हुई चाहते हैं, शुरू पकड़ने ब्लॉक में आप विभिन्न बिट्स की जानकारी का मिल सकता है।
  • ERROR_SEVERITY() गंभीरता देता है।
  • ERROR_STATE() त्रुटि स्थिति संख्या देता है।
  • ERROR_PROCEDURE() संग्रहीत प्रक्रिया का नाम देता है या ट्रिगर करता है जहां त्रुटि हुई।
  • ERROR_LINE() उस दिनचर्या के भीतर लाइन नंबर देता है जिसने त्रुटि उत्पन्न की है।
  • ERROR_MESSAGE() त्रुटि संदेश का पूरा पाठ देता है। पाठ में प्रतिस्थापन पैरामीटर, जैसे लंबाई, ऑब्जेक्ट नाम या समय के लिए प्रदान किए गए मान शामिल हैं।
+13

मैं COMTIT ट्रांज़ेक्शन को BEGIN TRY में डाल दूंगा .... अंत TRY ब्लॉक - पूरे कथन के बाद नहीं। क्या यह आसान और अधिक सटीक नहीं होगा? –

+0

'BEGIN TRYACTION' के बाद 'BEGIN TRANSACTION' क्यों नहीं डालें? –

+0

यह 6 साल पहले था .... मैं जो सोच रहा था उसे याद नहीं कर सकता;) लेकिन हाँ, मैं लेनदेन को BEGIN TRY के अंदर रखूंगा। मैंने जवाब अपडेट कर लिया है। – AdaTheDev

5

आप एसक्यूएल सर्वर 2000 या इससे पहले कि है, तो हाँ - जाँच @@ERROR मूल्य मूल रूप से तुम सब कर सकते हैं।

SQL सर्वर 2005 के साथ, माइक्रोसॉफ्ट का प्रयास करें ... कैच करें संरचना है जो यह एक बहुत आसान बना देता है की शुरुआत की: आप एसक्यूएल 2005 या अधिक उपयोग कर रहे हैं

BEGIN TRY 
    ...... 
    -- your T-SQL code here 
    ...... 
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 

    -- do other steps, if you want 
END CATCH 
2

आप TRY CATCH दृष्टिकोण पर विचार करना चाहिए

2

आप इसे सभी को पकड़ने की कोशिश में लपेट सकते हैं, और फिर आपको केवल एक ही स्थान पर रोलबैक को कोड करने की आवश्यकता है। अधिक जानकारी के लिए this देखें।

4

बहुत पहले नहीं पूछा गया। My answer एक TRY/CATCH टेम्पलेट

10

लंबे समय से अब मैं TRY/CATCH and nested transactions in stored procedures के उपयोग की वकालत कर रहा हूं।

यह पैटर्न आप न केवल आज़माएं/कैच ब्लॉक के बहुत सरलीकृत त्रुटि हैंडलिंग @@ त्रुटि की जांच के साथ तुलना में देता है, लेकिन यह भी सभी या कुछ भी नहीं प्रक्रिया आमंत्रण के लिए अर्थ विज्ञान नेस्ट देता है।

प्रक्रिया एक सौदे के संदर्भ पर कहा जाता है, तो प्रक्रिया वापस रोल केवल अपने स्वयं के परिवर्तन और क्या एम्बेडिंग लेनदेन रोलबैक करने के लिए या एक वैकल्पिक त्रुटि पथ की कोशिश करने का फैसला करने के लिए फोन करने वाले छोड़ देता है।

create procedure [usp_my_procedure_name] 
as 
begin 
    set nocount on; 
    declare @trancount int; 
    set @trancount = @@trancount; 
    begin try 
     if @trancount = 0 
      begin transaction 
     else 
      save transaction usp_my_procedure_name; 

     -- Do the actual work here 

lbexit: 
     if @trancount = 0 
      commit; 
    end try 
    begin catch 
     declare @error int, @message varchar(4000), @xstate int; 
     select @error = ERROR_NUMBER(), @message = ERROR_MESSAGE(), @xstate = XACT_STATE(); 
     if @xstate = -1 
      rollback; 
     if @xstate = 1 and @trancount = 0 
      rollback 
     if @xstate = 1 and @trancount > 0 
      rollback transaction usp_my_procedure_name; 

     raiserror ('usp_my_procedure_name: %d: %s', 16, 1, @error, @message) ; 
     return; 
    end catch 
end 

इस दृष्टिकोण का ड्रा पीठ कर रहे हैं:

  • यह वितरित लेन-देन के साथ काम नहीं करता। क्योंकि लेनदेन सेवपॉइंट वितरित लेनदेन के साथ असंगत हैं, इसलिए वितरित लेनदेन की आवश्यकता होने पर आप इस पैटर्न का उपयोग नहीं कर सकते हैं। आईएमएचओ वितरित लेनदेन बुरा हैं और वैसे भी कभी भी इस्तेमाल नहीं किया जाना चाहिए।
  • यह मूल त्रुटि को बदल देता है। यह समस्या TRY/CATCH ब्लॉक में निहित है और इसके बारे में आप कुछ भी नहीं कर सकते हैं। मूल SQL सर्वर त्रुटि कोड (जैसे 1202, 1205, 2627 इत्यादि) से निपटने के लिए तैयार किया गया एक अनुप्रयोग ट्रांजैक्ट-एसक्यूएल कोड द्वारा उठाए गए उपरोक्त 50000 रेंज में त्रुटि कोड से निपटने के लिए बदला जाना होगा जो TRY/CATCH का उपयोग करता है ।
इसके अलावा

SET XACT_ABORT ON के उपयोग के बारे सावधानी के एक शब्द। यह सेटिंग बैच को किसी भी त्रुटि पर लेनदेन को रद्द करने का कारण बन जाएगी। इससे मूल रूप से बेकार किसी भी TRY/CATCH लेनदेन को संभाला जाता है और मैं इससे बचने की सलाह देता हूं।

+0

तीसरी कमी अत्यधिक प्रतिलिपि और पेस्टिंग होगी ... वास्तव में इच्छा है कि सभी पुनरावृत्ति से बचने का एक तरीका था। – Aaronaught

+1

@ हारून: दुर्भाग्यवश यह ट्रांजैक्ट-एसक्यूएल के संबंध में कला का संत है। कोड पुन: उपयोग और संक्षिप्तता के लिए अनुकूल भाषा नहीं है। उपकरण के माध्यम से कोड उत्पन्न करना (उदाहरण के लिए एक्सएसटीएल + एक्सएमएल) टी-एसक्यूएल लिखने की दोहराव और त्रुटि प्रवण प्रकृति को दूर करके उस समस्या को कम करने का एक लंबा रास्ता तय करता है। –

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