2009-09-11 5 views
15

चलो कहते हैं कि मैं इस तरह एक ट्रिगर मिल गया है दो:T-SQL: अद्यतन ट्रिगर में बंद करने के लिए/पुनःआवंटन कर्सर एक उचित तरीके से

CREATE TRIGGER trigger1 
    ON [dbo].[table1] 
    AFTER UPDATE 
AS 
BEGIN    
    --declare some vars 
    DECLARE @Col1 SMALLINT 
    DECLARE @Col1 TINYINT 

    --declare cursor   
    DECLARE Cursor1 CURSOR FOR 
    SELECT Col1, Col2 FROM INSERTED    

    --do the job 
    OPEN Cursor1 
    FETCH NEXT FROM Cursor1 INTO @Col1, @Col2 

    WHILE @@FETCH_STATUS = 0 
    BEGIN 
     IF ...something... 
     BEGIN   
      EXEC myProc1 @param1 = @Col1, @Param2 = @Col2 
     END    
     ELSE 
     IF ...something else... 
     BEGIN   
      EXEC myProc2 @param1 = @Col1, @Param2 = @Col2 
     END  

     FETCH NEXT FROM Cursor1 INTO @Col1, @Col2    
    END 

    --clean it up  
    CLOSE Cursor1 
    DEALLOCATE Cursor1     
END 

मुझे यकीन है कि Cursor1 हमेशा बंद कर दिया और पुनः आवंटित की जाती है होना चाहता हूँ। यहां तक ​​कि myProc1 या myProc2 विफल रहता है।

क्या मैं कोशिश/पकड़ ब्लॉक का उपयोग करूंगा?

+0

[आवश्यक पढ़ने] (http://www.sommarskog.se/error-handling-I.html)। –

उत्तर

15

हां, TRY/CATCH का उपयोग करें, लेकिन सुनिश्चित करें कि आप आदि को रद्द कर दें। दुर्भाग्यवश, SQL सर्वर में कोई अंत में नहीं है।

हालांकि, मैं एक और ट्राई/कैच

CREATE TRIGGER trigger1 ON [dbo].[table1] AFTER UPDATE 
AS 
BEGIN       
    --declare some vars 
    DECLARE @Col1 SMALLINT, @Col1 TINYINT 

    BEGIN TRY 
     --declare cursor    
     DECLARE Cursor1 CURSOR FOR 
     SELECT Col1, Col2 FROM INSERTED      

     --do the job 
     OPEN Cursor1 
     FETCH NEXT FROM Cursor1 INTO @Col1, @Col2 

     WHILE @@FETCH_STATUS = 0 
     BEGIN 
      IF ...something... 
        EXEC myProc1 @param1 = @Col1, @Param2 = @Col2 
      ELSE 
      IF ...something else... 
        EXEC myProc2 @param1 = @Col1, @Param2 = @Col2 

      FETCH NEXT FROM Cursor1 INTO @Col1, @Col2        
     END 
    END TRY 
    BEGIN CATCH 
     --do what you have to 
    END CATCH 

    BEGIN TRY 
     --clean it up    
     CLOSE Cursor1 
     DEALLOCATE Cursor1         
    END TRY 
    BEGIN CATCH 
     --do nothing 
    END CATCH 
END 

चाहे ट्रिगर में एक कर्सर एक अच्छा विचार एक अलग बात है में इस लपेटकर का सुझाव देते हैं ...

+0

कैच क्लीनअप को कैप्चर करने के लिए आपका तर्क क्या है जब कैच कुछ भी नहीं करता है? –

+4

@NickDeVore: क्योंकि कर्सर पहले से ही बंद हो सकता है, इस पर निर्भर करता है कि proc1 या proc2 कैसे विफल होता है (ट्रिगर में, शायद कोशिश/पकड़ आदि)। माफी से अधिक सुरक्षित। – gbn

+0

क्या आप ट्रिगर में TRY/CATCH वाक्यविन्यास का उपयोग कर सकते हैं? मुझे क्या पता है कि जब एक ट्रिगर में कोई त्रुटि होती है तो पूरा लेनदेन विफल रहता है, चाहे कोशिश करें/पकड़ें या नहीं। –

1

आपको क्या करना चाहिए कभी भी एक ट्रिगर में कर्सर का उपयोग कभी नहीं करना चाहिए। इसके बजाए सही सेट-आधारित कोड लिखें। अगर किसी ने 100,000 नए रिकॉर्ड की अपनी तालिका में डेटा का आयात किया है तो आप घंटों तक टेबल लॉक कर लेंगे और अपने डेटाबेस को चिल्लाते हुए रोक देंगे। एक ट्रिगर में कर्सर का उपयोग करने के लिए यह एक बहुत ही खराब अभ्यास है।

+1

अगर किसी ने 100,000 नए रिकॉर्ड की इस तालिका में डेटा का आयात किया है तो यह मेरी तालिका को बिल्कुल लॉक नहीं करेगा (क्योंकि यह अद्यतन के बाद एक ट्रिगर है;) लेकिन गंभीरता से। मुझे गलत मत समझो। मैं पूरी तरह समझता हूं कि आपका क्या मतलब है और आप सही हैं। मैं कभी भी ट्रिगर में कर्सर का उपयोग नहीं करता जब तक कि यह बिल्कुल जरूरी नहीं है और मेरे मामले में यह है। सिद्धांत में केवल कुछ पंक्तियां मेरे ऐप से एक ही समय में अपडेट की जा सकती हैं (जब तक कोई प्रबंधन स्टूडियो से अपडेट नहीं करेगा)। सब कुछ पूरी तरह से काम करता है (और तेज़) लेकिन मैं सोच रहा हूं कि अगर मेरे एसपी में से एक विफल रहता है। क्या मुझे चिंता करनी चाहिए? – Novitzky

+0

मैं आपको proc या डेटा डालने में परिवर्तन करके परीक्षण का सुझाव दूंगा जो गारंटी देगा कि proc विफल हो जाएगी। तब आपको पता चलेगा कि क्या होगा। – HLGEM

+0

धन्यवाद। यह वही है जो मैं करने जा रहा हूं। जैसा कि मैंने कर्सर का उपयोग करने से पहले कहा था (अन्यथा यह मेरे ऐप में बहुत अधिक बदलाव होगा) लेकिन मैं अपने एसपी बदल सकता हूं। फिर भी धन्यवाद। – Novitzky

35

आप CURSOR_STATUS इस्तेमाल कर सकते हैं() समारोह।

if CURSOR_STATUS('global','cursor_name') >= 0 
begin 
close cursor_name 
    deallocate cursor_name 
end 

संदर्भ: http://msdn.microsoft.com/en-us/library/ms177609.aspx

+2

+1 के लिए व्यवहार को अधिक अनुमानित बनाता है इस बारे में नहीं पता था – gbn

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

  • कोई संबंधित समस्या नहीं^_^