2008-09-16 16 views
77

मुझे बस टीएसक्यूएल में कुछ आश्चर्य हुआ। मैंने सोचा कि अगर XACT_ABORT पर था,जब xact_abort चालू होता है तो एसक्यूएल सर्वर raiserror के बाद निष्पादन क्यों करता है?

raiserror('Something bad happened', 16, 1); 

की तरह कुछ बुला संग्रहीत प्रक्रिया (या किसी भी बैच) के निष्पादन बंद कर देंगे।

लेकिन मेरा एडीओ.NET त्रुटि संदेश सिर्फ विपरीत साबित हुआ। मुझे अपवाद संदेश में राइजर आतंक त्रुटि संदेश मिला, साथ ही इसके बाद टूटने वाली अगली चीज़।

यह मेरा वैकल्पिक हल (जो मेरी आदत वैसे भी है) है, लेकिन यह नहीं लगता है जैसे कि यह आवश्यक होना चाहिए:

जब सेट XACT_ABORT है:

if @somethingBadHappened 
    begin; 
     raiserror('Something bad happened', 16, 1); 
     return; 
    end; 

डॉक्स यह कहना चालू, यदि एक ट्रांजैक्ट-एसक्यूएल कथन एक रन-टाइम त्रुटि उठाता है, तो पूरा लेनदेन समाप्त हो जाता है और वापस लुढ़का जाता है।

क्या इसका मतलब है कि मुझे एक स्पष्ट लेनदेन का उपयोग करना चाहिए?

+0

बस परीक्षण किया गया और 'RAISERROR' वास्तव में निष्पादन को समाप्त कर देगा यदि तीव्रता 16 या 18 के बजाय, 1712 के लिए निर्धारित है। – reformed

उत्तर

43

इस डिजाइन टीएम तक है, जैसा कि आप एक ऐसी ही सवाल का एसक्यूएल सर्वर टीम की प्रतिक्रिया से Connect पर देख सकते हैं:

आपकी प्रतिक्रिया के लिए धन्यवाद। डिज़ाइन द्वारा, XACT_ABORT सेट विकल्प RAISERROR कथन के व्यवहार को प्रभावित नहीं करता है। SQL सर्वर की भावी रिलीज के लिए हम इस व्यवहार को संशोधित करने के लिए आपकी प्रतिक्रिया पर विचार करेंगे।

हाँ, यह कुछ है जो एक उच्च गंभीरता के साथ RAISERROR आशा व्यक्त की के लिए एक मुद्दा का एक सा (जैसे 16) एक SQL निष्पादन त्रुटि के रूप में ही होता है - यह नहीं है।

आपका कामकाज सिर्फ इतना है कि आपको क्या करना है, और स्पष्ट लेनदेन का उपयोग करने से उस व्यवहार पर कोई प्रभाव नहीं पड़ता है जिसे आप बदलना चाहते हैं।

+0

धन्यवाद फिलिप। आपके द्वारा संदर्भित लिंक अनुपलब्ध प्रतीत होता है। –

+2

लिंक ठीक काम कर रहा है, अगर आपको कभी भी इसकी खोज करने की ज़रूरत है, शीर्षक "XACT_ABORT के साथ रेज़रर काम करें", लेखक "जोरंडुर", आईडी: 275308 – JohnC

22

यदि आप कोशिश/पकड़ ब्लॉक का उपयोग करते हैं तो तीव्रता 11-19 के साथ एक राइजर आतंक त्रुटि संख्या को पकड़ने के लिए निष्पादन का कारण बन जाएगा।

16 से ऊपर कोई गंभीरता एक सिस्टम त्रुटि है। निम्नलिखित कोड आज़माएं/कैच ब्लॉक सेट और एक संग्रहीत प्रक्रिया है कि हम असफल हो जायेगी मान कार्यान्वित प्रदर्शित करने के लिए:।

मान हम एक मेज [dbo] है [त्रुटियाँ] त्रुटियों मान हम एक संग्रहीत प्रक्रिया है धारण करने के लिए [ dbo]। [AssumeThisFails] असफल हो जायेगी जो जब हम तुरंत RAISERROR() के बाद निष्पादित यह

-- first lets build a temporary table to hold errors 
if (object_id('tempdb..#RAISERRORS') is null) 
create table #RAISERRORS (ErrorNumber int, ErrorMessage varchar(400), ErrorSeverity int, ErrorState int, ErrorLine int, ErrorProcedure varchar(128)); 

-- this will determine if the transaction level of the query to programatically determine if we need to begin a new transaction or create a save point to rollback to 
declare @tc as int; 
set @tc = @@trancount; 
if (@tc = 0) 
begin transaction; 
else 
save transaction myTransaction; 

-- the code in the try block will be executed 
begin try 
declare @return_value = '0'; 
set @return_value = '0'; 
declare 
    @ErrorNumber as int, 
    @ErrorMessage as varchar(400), 
    @ErrorSeverity as int, 
    @ErrorState as int, 
    @ErrorLine as int, 
    @ErrorProcedure as varchar(128); 


-- assume that this procedure fails... 
exec @return_value = [dbo].[AssumeThisFails] 
if (@return_value <> 0) 
    raiserror('This is my error message', 17, 1); 

-- the error severity of 17 will be considered a system error execution of this query will skip the following statements and resume at the begin catch block 
if (@tc = 0) 
    commit transaction; 
return(0); 
end try 


-- the code in the catch block will be executed on raiserror("message", 17, 1) 
begin catch 
    select 
    @ErrorNumber = ERROR_NUMBER(), 
    @ErrorMessage = ERROR_MESSAGE(), 
    @ErrorSeverity = ERROR_SEVERITY(), 
    @ErrorState = ERROR_STATE(), 
    @ErrorLine = ERROR_LINE(), 
    @ErrorProcedure = ERROR_PROCEDURE(); 

    insert #RAISERRORS (ErrorNumber, ErrorMessage, ErrorSeverity, ErrorState, ErrorLine, ErrorProcedure) 
    values (@ErrorNumber, @ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorLine, @ErrorProcedure); 

    -- if i started the transaction 
    if (@tc = 0) 
    begin 
    if (XACT_STATE() <> 0) 
    begin 
    select * from #RAISERRORS; 
    rollback transaction; 
    insert into [dbo].[Errors] (ErrorNumber, ErrorMessage, ErrorSeverity, ErrorState, ErrorLine, ErrorProcedure) 
    select * from #RAISERRORS; 
    insert [dbo].[Errors] (ErrorNumber, ErrorMessage, ErrorSeverity, ErrorState, ErrorLine, ErrorProcedure) 
    values (@ErrorNumber, @ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorLine, @ErrorProcedure); 
    return(1); 
    end 
    end 
    -- if i didn't start the transaction 
    if (XACT_STATE() = 1) 
    begin 
    rollback transaction myTransaction; 
    if (object_id('tempdb..#RAISERRORS') is not null) 
    insert #RAISERRORS (ErrorNumber, ErrorMessage, ErrorSeverity, ErrorState, ErrorLine, ErrorProcedure) 
    values (@ErrorNumber, @ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorLine, @ErrorProcedure); 
    else 
    raiserror(@ErrorMessage, @ErrorSeverity, @ErrorState); 
    return(2); 
    end 
    else if (XACT_STATE() = -1) 
    begin 
    rollback transaction; 
    if (object_id('tempdb..#RAISERRORS') is not null) 
    insert #RAISERRORS (ErrorNumber, ErrorMessage, ErrorSeverity, ErrorState, ErrorLine, ErrorProcedure) 
    values (@ErrorNumber, @ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorLine, @ErrorProcedure); 
    else 
    raiserror(@ErrorMessage, @ErrorSeverity, @ErrorState); 
    return(3); 
    end 
end catch 
end 
19

उपयोग RETURN और यह प्रक्रिया आगे निष्पादित नहीं होगा।

+8

आप 'वापसी' कॉल करने से पहले 'रोलबैक लेनदेन' को कॉल करना चाहते हैं। –

+1

शायद आपको अपने कैच ब्लॉक – sqluser

12

MSDN पर THROW कथन के अनुसार RAISERROR के बजाय कथन का उपयोग किया जाना चाहिए।

दो व्यवहार slightly differently। लेकिन जब XACT_ABORT चालू है, तो आपको हमेशा THROW कमांड का उपयोग करना चाहिए।

+24

में कुछ करने की आवश्यकता हो सकती है यदि आपके पास 2k12 (या इससे ऊपर आने पर ऊपर) नहीं है, तो वहां कोई थ्रॉव स्टेटमेंट नहीं है। –

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

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