2011-11-08 88 views
0

在下面的程序,我發現here重新拋出一個T-SQL錯誤

ALTER PROCEDURE [dbo].[usp_RethrowError] 
AS -- Return if there is no error information to retrieve. 
    IF ERROR_NUMBER() IS NULL 
     RETURN; 

    DECLARE @ErrorMessage   NVARCHAR(4000), 
      @OriginalErrorNumber INT, 
      @RethrownErrorNumber INT, 
      @ErrorSeverity   INT, 
      @ErrorState    INT, 
      @ErrorLine    INT, 
      @ErrorProcedure   NVARCHAR(200); 

    -- Assign variables to error-handling functions that 
    -- capture information for RAISERROR. 
    SELECT 
     @OriginalErrorNumber = ERROR_NUMBER() 
     ,@ErrorSeverity   = ERROR_SEVERITY() 
     ,@ErrorSeverity   = ERROR_SEVERITY() 
     ,@ErrorState    = ERROR_STATE() 
     ,@ErrorLine    = ERROR_LINE() 
     ,@ErrorProcedure   = ISNULL(ERROR_PROCEDURE(),'-'); 

    --Severity levels from 0 through 18 can be specified by any user. 
    --Severity levels from 19 through 25 can only be specified by members of the sysadmin fixed server role or users with ALTER TRACE permissions 
    IF @OriginalErrorNumber < 19 
     SET @RethrownErrorNumber = @OriginalErrorNumber 
    ELSE 
     SET @RethrownErrorNumber = 18 

    -- Building the message string that will contain original 
    -- error information. 
    SELECT 
     @ErrorMessage = N'Error %d, Level %d, State %d, Procedure %s, Line %d, ' + 'Message: ' + ERROR_MESSAGE(); 


    -- Raise an error: msg_str parameter of RAISERROR will contain 
    -- the original error information. 
    RAISERROR (@ErrorMessage, 
       @ErrorSeverity, 
       @ErrorState, 
       @RethrownErrorNumber,  -- parameter: original error number or 18, if the original was >=19. 
       @ErrorSeverity,    -- parameter: original error severity. 
       @ErrorState,     -- parameter: original error state. 
       @ErrorProcedure,    -- parameter: original error procedure name. 
       @ErrorLine     -- parameter: original error line number. 
      ); 

有人可以解釋以下行:

SELECT 
     @ErrorMessage = N'Error %d, Level %d, State %d, Procedure %s, Line %d, ' + 'Message: ' + ERROR_MESSAGE(); 

我意識到,%的出現次數是一個佔位符有符號整數(%d)和一個嚴格(%s),但我不明白哪些變量映射到這些佔位符。他們似乎並沒有映射到RAISERROR調用中指定的參數:我做了兩個小的改動子程序,一個降低的嚴重程度,如果> 19,另一個使用原來的狀態,而不是總是

RAISERROR (@ErrorMessage, 
      @ErrorSeverity, 
      @ErrorState, 
      @RethrownErrorNumber,  -- parameter: original error number or 18, if the original was >=19. 
      @ErrorSeverity,    -- parameter: original error severity. 

     @ErrorState,     -- parameter: original error state. 
     @ErrorProcedure,    -- parameter: original error procedure name. 
     @ErrorLine     -- parameter: original error line number. 
     ); 

通過1.

如果你們不打這個例行程序,我的小小的變化太糟糕了,我會在重新投擲之前將日誌記錄錯誤信息添加到用戶表中。

要撥打:

DECLARE @Zero INT 
SET @Zero = 0 

BEGIN TRY 
SELECT 5/@Zero 
END TRY 
BEGIN CATCH 
PRINT 'We have an error...' 
EXEC usp_RethrowError 
END CATCH 

後續問題:

1)上面的鏈接提到,這個程序不會死鎖工作。任何理由?

2)我添加了「IF @OriginalErrorNumber < 19」部分。我並不擔心如果發生錯誤> 18的錯誤將會重新出現錯誤,嚴重程度將爲18.無論如何,我都會放棄並重新記錄原始嚴重性。這個例程還有什麼我需要擔心的嗎?

+0

注意:'ERROR_MESSAGE()'有可能在其中有'printf()'類型的替換字符串,例如'%s'。我建議在''RAISERROR()'調用的參數列表的末尾添加'ERROR_MESSAGE當替換字符不經過替換時,'ERROR_MESSAGE()'中的'-style替換字符將被TSQL替換爲字符串'(null)'。 – binki

回答

3

希望這會有所幫助!

您處於正確的軌道上,ErrorMessage是由RAISERROR消耗的模式字符串。綜觀RAISERROR的語法結構將清理的混亂:

RAISERROR ({ msg_id | msg_str | @local_variable } 
    { ,severity ,state } 
    [ ,argument [ ,...n ] ]) 
    [ WITH option [ ,...n ] ] 

前三個所需的參數爲所述消息模式字符串(msg_str),嚴重程度和狀態。接下來是可選參數,它們將替換msg_str中的替換參數。

因此,代碼讓:

msg_str是的ErrorMessage

嚴重性ErrorSeverity

狀態是ErrorState

論據是RethrownErrorNumber,ErrorSeverity,ErrorState,ErrorProcedure,ErrorLine

參考http://msdn.microsoft.com/en-us/library/ms178592.aspx

+0

我認爲%佔位符與您指定的*參數*一致,從* 4th *參數開始,@ RethrownErrorNumber,我傳遞給RAISERROR例程。前3個參數必須用於重新拋出錯誤。佔位符分別指參數params(第4參數)。謝謝! – ChadD