RAISERROR Nulls?

  • Hey all,

    I have a try catch block. In the catch i have this (along with other stuff!):

    DECLARE

    @ErrorMessage NVARCHAR(4000) ,

    @ErrorMessageShort NVARCHAR(4000) ,

    @ErrorNumber INT ,

    @ErrorSeverity INT ,

    @ErrorState INT ,

    @ErrorLine INT ,

    @ErrorProcedure NVARCHAR(200);

    SELECT

    @ErrorNumber = ERROR_NUMBER() ,

    @ErrorSeverity = ERROR_SEVERITY() ,

    @ErrorState = ERROR_STATE() ,

    @ErrorLine = ERROR_LINE() ,

    @ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-') ,

    @ErrorMessageShort = ERROR_MESSAGE();

    INSERT dbo.Audit_Errors

    ( ErrorTime ,

    JobID ,

    JobStepID ,

    StepDescription ,

    ErrorNumber ,

    ErrorSeverity ,

    ErrorState ,

    ErrorProcedure ,

    ErrorLine ,

    ErrorMessage

    )

    SELECT

    GETDATE() AS ErrorTime ,

    @JobID AS JobID ,

    @JobStepID AS JobStepID ,

    @StepDescription AS Process_Step ,

    @ErrorNumber AS ErrorNumber ,

    @ErrorSeverity AS ErrorSeverity ,

    @ErrorState AS ErrorState ,

    @ErrorProcedure AS ErrorProcedure ,

    @ErrorLine AS ErrorLine ,

    @ErrorMessageShort AS ErrorMessage

    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorNumber,@ErrorLine) WITH LOG

    Now in the table the ErrorProcedure, State, line and message are all populated correctly. However the raise error is coming back with stuff like:

    Msg 50000, Level 14, State 1, Line 302

    Error 2627, Level 93, State (null), Procedure (null), Line (null), Message: Violation of PRIMARY KEY constraint.....

    So no proc, and two sets of level etc.

    My audit table is logging (for this error) Errornum 2627, Severity 14, state 1 and the correct name of the error proc.

    What am i doing wrong to make the raiserror do this?

    Many thanks

    Dan

  • Please check the table definition may by primary key on below columns.

    State (null), Procedure (null), Line (null)

    i tested it the with out primary key and it is working fine.The results looks like this.

    [p]DECLARE

    @ErrorMessage NVARCHAR(4000) ,

    @ErrorMessageShort NVARCHAR(4000) ,

    @ErrorNumber INT ,

    @ErrorSeverity INT ,

    @ErrorState INT ,

    @ErrorLine INT ,

    @ErrorProcedure NVARCHAR(200),

    @JobID INT = 100,

    @JobStepID INT = 10,

    @StepDescription VARCHAR(100) = 'NEW JOB';

    SELECT

    @ErrorNumber = ERROR_NUMBER() ,

    @ErrorSeverity = ERROR_SEVERITY() ,

    @ErrorState = ERROR_STATE() ,

    @ErrorLine = ERROR_LINE() ,

    @ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-') ,

    @ErrorMessageShort = ERROR_MESSAGE();

    INSERT dbo.Audit_Errors

    ( ErrorTime ,

    JobID ,

    JobStepID ,

    StepDescription ,

    ErrorNumber ,

    ErrorSeverity ,

    ErrorState ,

    ErrorProcedure ,

    ErrorLine ,

    ErrorMessage

    )

    SELECT

    GETDATE() AS ErrorTime ,

    @JobID AS JobID ,

    @JobStepID AS JobStepID ,

    @StepDescription AS Process_Step ,

    @ErrorNumber AS ErrorNumber ,

    @ErrorSeverity AS ErrorSeverity ,

    @ErrorState AS ErrorState ,

    @ErrorProcedure AS ErrorProcedure ,

    @ErrorLine AS ErrorLine ,

    @ErrorMessageShort AS ErrorMessage

    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorNumber,@ErrorLine) WITH LOG[/p]

    ErrorTime JobID JobStepID StepDescription ErrorNumber ErrorSeverity ErrorState ErrorProcedure ErrorLine ErrorMessage

    2014-05-29 05:59:43.670 100 10 NEW JOB NULL NULL NULL - NULL NULL

    2014-05-29 05:59:51.773 100 10 NEW JOB NULL NULL NULL - NULL NULL

    2014-05-29 06:00:07.920 100 10 NEW JOB NULL NULL NULL - NULL NULL

    2014-05-29 06:00:09.890 100 10 NEW JOB NULL NULL NULL - NULL NULL

  • Hi,

    Sorry i am a little confused. What primary key? The table insert is fine.... its the raiserror that is showing nulls.

    Sorry if i was unclear.

    Dan

  • can u paste the table structure of Audit_Errors.

    Then i will show u the issue.

  • CREATE TABLE [dbo].[Audit_Errors](

    [AuditLogErrorsID] [int] IDENTITY(1,1) NOT NULL,

    [ErrorTime] [datetime] NULL,

    [JobID] [int] NULL,

    [JobStepID] [int] NULL,

    [StepDescription] [varchar](250) NULL,

    [ErrorNumber] [int] NULL,

    [ErrorSeverity] [int] NULL,

    [ErrorState] [int] NULL,

    [ErrorProcedure] [nvarchar](200) NULL,

    [ErrorLine] [int] NULL,

    [ErrorMessage] [nvarchar](4000) NULL,

    CONSTRAINT [PK_Audit_Errors] PRIMARY KEY CLUSTERED

    (

    [AuditLogErrorsID] ASC

    )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]

    ) ON [PRIMARY]

  • So just to clarify - the insert into the audit table is perfect. It has the correct information. The raiserror has the nulls.

  • @ErrorMessage doesn't get populated in the code shown. Can you show how that gets built?

  • danielfountain (5/29/2014)


    Hey all,

    I have a try catch block.

    <snipped>

    What am i doing wrong to make the raiserror do this?

    Many thanks

    Dan

    Unfortunately, RAISERROR in a CATCH block doesn't work like you want it to work (as I understand your scenario):

    1. An error occurs in a TRY block and passes control to the CATCH block.

    2. Some processing occurs in the CATCH block.

    3. A RAISERROR statement raises an error message to the calling application that reflects the original error and processing halts.

    From Books Online:

    [RAISERROR] [g]enerates an error message and initiates error processing for the session. . . . The message is returned as a server error message to the calling application or to an associated CATCH block of a TRY…CATCH construct.

    That's how RAISERROR works in a TRY block (or in code without a TRY...CATCH construct) - it just forces an error situation.

    Once you're in the CATCH block, though, RAISERROR behaves differently depending on how you use it.

    Here's the basic code that is used to demonstrate three scenarios for using RAISERROR in a CATCH block:

    BEGIN TRY

    SELECT 1/0 AS col1

    END TRY

    BEGIN CATCH

    DxECLARE @ErrorMessageLong NVARCHAR(4000) = N'Msg% 0.0d, Level% 0.0d, State% 0.0d, Line% 0.0d

    % 1.255s'

    ,@ErrorMessageShort NVARCHAR(4000) = ERROR_MESSAGE()

    ,@ErrorSeverity INT = ERROR_SEVERITY()

    ,@ErrorState INT = ERROR_STATE()

    ,@ErrorNumber INT = ERROR_NUMBER()

    ,@ErrorLine INT = ERROR_LINE()

    -- RAISERROR statements will go here --

    END CATCH

    The string value assigned to the @ErrorMessageLong variable includes a bunch of codes that instruct the RAISERROR statement to substitute the arguments that begin after the [state] argument for the "%" signs, in the order they're listed. The characters after the "%" sign provide formatting instructions. For example, the code "% 0.0d" means substitute the appropriate argument from the list in this position("%"), pad it with spaces if necessary (" "), print the value with no padding if it is longer than this width ("0"), print all digits of the value (".0"), and format it as a signed integer ("d"). It usually takes me some trial and error to get the string just right to produce the output I expect.

    Here are the three different ways you can use RAISERROR in the CATCH block.

    Scenario 1 - Raise an error with Msg 50000, the severity level and state of the original error, the line number of the RAISERROR statement, and the description only of the original error message and continue processing. Using this RAISERROR statement:

    RAISERROR(@ErrorMessageShort, @ErrorSeverity, @ErrorState)

    with the code above will return this error message:

    Msg 50000, Level 16, State 1, Line 19

    Divide by zero error encountered.

    and processing will continue (add some code after the RAISERROR statement in the CATCH block to see this is true).

    Scenario 2 - Raise an error with Msg 50000, a specified severity level and state, the line number of the RAISERROR statement, and the full text of the original error message and stop processing if warranted by the specified severity level. Using this RAISERROR statement:

    RAISERROR(@ErrorMessageLong, 17, 1, @ErrorNumber, @ErrorSeverity, @ErrorState, @ErrorLine, @ErrorMessageShort)

    raises this error:

    Msg 50000, Level 17, State 1, Line 21

    Msg 8134, Level 16, State 1, Line 3

    Divide by zero error encountered.

    Processing will stop if the specified severity level is greater than 16 (only sysadmins can specify a severity level higher than 18 and only when using the WITH LOG option).

    Scenario 3:

    Print a message that looks like the original error message and continue processing. Using this RAISERROR statement:

    RAISERROR(@ErrorMessageLong, -1, -1, @ErrorNumber, @ErrorSeverity, @ErrorState, @ErrorLine, @ErrorMessageShort)

    returns this message (it's not a true error message, just a message like the output of a PRINT statement):

    Msg 8134, Level 16, State 1, Line 3

    Divide by zero error encountered.

    and processing will continue.

    That's supremely frustrating, but unfortunately, there doesn't seem to be a good workaround to achieve the desired result in SQL Server 2008R2 and earlier versions.

    Starting with SQL Server 2012, the THROW statement provides this functionality. When executed in a CATCH block, THROW returns the error that caused control to drop to the CATCH block and halts processing if warranted by the severity level. On a SQL Server 2012 instance, executing the THROW statement in place of the RAISERROR statement in the code above, like this (it requires that the previous statement be terminated by a semicolon):

    ;

    THROW

    raises this error message:

    Msg 8134, Level 16, State 1, Line 3

    Divide by zero error encountered.

    and processing halts. It's a shame that something this simple isn't available in earlier versions!

    Jason Wolfkill

  • Instead of throw, you could use a simple condition.;-)

    DECLARE @ErrorMessage NVARCHAR(4000) ,

    @ErrorMessageShort NVARCHAR(4000) ,

    @ErrorNumber INT ,

    @ErrorSeverity INT ,

    @ErrorState INT ,

    @ErrorLine INT ,

    @ErrorProcedure NVARCHAR(200);

    BEGIN TRY

    SELECT 1/0 AS col1

    END TRY

    BEGIN CATCH

    SELECT @ErrorNumber = ERROR_NUMBER() ,

    @ErrorSeverity = ERROR_SEVERITY() ,

    @ErrorState = ERROR_STATE() ,

    @ErrorLine = ERROR_LINE() ,

    @ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-') ,

    @ErrorMessage = ERROR_MESSAGE()

    INSERT dbo.Audit_Errors

    (

    ErrorTime ,

    JobID ,

    JobStepID ,

    StepDescription ,

    ErrorNumber ,

    ErrorSeverity ,

    ErrorState ,

    ErrorProcedure ,

    ErrorLine ,

    ErrorMessage

    )

    SELECT

    GETDATE() AS ErrorTime ,

    @JobID AS JobID ,

    @JobStepID AS JobStepID ,

    @StepDescription AS Process_Step ,

    @ErrorNumber AS ErrorNumber ,

    @ErrorSeverity AS ErrorSeverity ,

    @ErrorState AS ErrorState ,

    @ErrorProcedure AS ErrorProcedure ,

    @ErrorLine AS ErrorLine ,

    @ErrorMessageShort AS ErrorMessage

    END CATCH

    IF @ErrorMessage > ''

    BEGIN

    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorNumber,@ErrorLine) WITH LOG

    SET @ErrorMessage = NULL

    END

    Luis C.
    General Disclaimer:
    Are you seriously taking the advice and code from someone from the internet without testing it? Do you at least understand it? Or can it easily kill your server?

    How to post data/code on a forum to get the best help: Option 1 / Option 2
  • Luis Cazares (5/30/2014)


    Instead of throw, you could use a simple condition.;-)

    DxECLARE @ErrorMessage NVARCHAR(4000) ,

    @ErrorMessageShort NVARCHAR(4000) ,

    @ErrorNumber INT ,

    @ErrorSeverity INT ,

    @ErrorState INT ,

    @ErrorLine INT ,

    @ErrorProcedure NVARCHAR(200);

    BEGIN TRY

    SELECT 1/0 AS col1

    END TRY

    BEGIN CATCH

    SELECT @ErrorNumber = ERROR_NUMBER() ,

    @ErrorSeverity = ERROR_SEVERITY() ,

    @ErrorState = ERROR_STATE() ,

    @ErrorLine = ERROR_LINE() ,

    @ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-') ,

    @ErrorMessage = ERROR_MESSAGE()

    INSERT dbo.Audit_Errors

    (

    ErrorTime ,

    JobID ,

    JobStepID ,

    StepDescription ,

    ErrorNumber ,

    ErrorSeverity ,

    ErrorState ,

    ErrorProcedure ,

    ErrorLine ,

    ErrorMessage

    )

    SELECT

    GETDATE() AS ErrorTime ,

    @JobID AS JobID ,

    @JobStepID AS JobStepID ,

    @StepDescription AS Process_Step ,

    @ErrorNumber AS ErrorNumber ,

    @ErrorSeverity AS ErrorSeverity ,

    @ErrorState AS ErrorState ,

    @ErrorProcedure AS ErrorProcedure ,

    @ErrorLine AS ErrorLine ,

    @ErrorMessageShort AS ErrorMessage

    END CATCH

    IF @ErrorMessage > ''

    BEGIN

    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorNumber,@ErrorLine) WITH LOG

    SET @ErrorMessage = NULL

    END

    The problem is that RAISERROR used like that will return the error message but will NOT halt processing unless you ensure that the severity level is set to 17 or higher. Notice that the SELECT I added after the first RAISERROR executes and returns a result set while the SELECT after the second RAISERROR does not:

    DxECLARE @ErrorMessage NVARCHAR(4000) ,

    @ErrorMessageShort NVARCHAR(4000) ,

    @ErrorNumber INT ,

    @ErrorSeverity INT ,

    @ErrorState INT ,

    @ErrorLine INT ,

    @ErrorProcedure NVARCHAR(200);

    BEGIN TRY

    SELECT 1/0 AS col1

    END TRY

    BEGIN CATCH

    SELECT @ErrorNumber = ERROR_NUMBER() ,

    @ErrorSeverity = ERROR_SEVERITY() ,

    @ErrorState = ERROR_STATE() ,

    @ErrorLine = ERROR_LINE() ,

    @ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-') ,

    @ErrorMessage = ERROR_MESSAGE()

    END CATCH

    IF @ErrorMessage > ''

    BEGIN

    RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState, @ErrorNumber,@ErrorLine) WITH LOG

    SELECT 'xxxxxxx' AS junkColumn

    RAISERROR (@ErrorMessage, 17, @ErrorState, @ErrorNumber,@ErrorLine) WITH LOG

    SET @ErrorMessage = NULL

    SELECT 'yyyyyyy' AS junkColumn

    END

    Jason Wolfkill

Viewing 10 posts - 1 through 9 (of 9 total)

You must be logged in to reply to this topic. Login to reply