Не удается увидеть ожидаемый вывод PRINT или RAISERROR при возникновении более поздней ошибки

Я получаю сообщение об ошибке в хранимой процедуре, в котором говорится, что я не могу вставить значение NULL в таблицу, тогда как я должен получать ошибки ранее в коде, если значение равно null.

Вот соответствующая часть хранимой процедуры:

CREATE PROCEDURE [dbo].[udp_AddUpdateStaffVariable] 
    -- Add the parameters for the stored procedure here
    @StaffID int=null,
    @VariableTypeID int,
    @VariableIntValue int=null,
    @VariableVarcharValue varchar(max)=null,
    @VariableDatetimeValue datetime=null,
    @VariableDecimalValue decimal=null
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here
BEGIN TRY  
    DECLARE @PrintOutput varchar(150)
    SET @PrintOutput = '@StaffID = ' + CASE WHEN @StaffID = NULL THEN 'Null' ELSE CONVERT(varchar(20), @StaffID) END
    RAISERROR (@PrintOutput, 10, 1) WITH NOWAIT

    IF (@StaffID = NULL)    -- If the staffid of the current user was not supplied, find it in the Staff table
    BEGIN
        DECLARE @CurrentUser nvarchar(255) = SUSER_SNAME();
        SELECT @StaffID = [StaffID] FROM [dbo].[Staff] WHERE [UserName] = @CurrentUser;
        SET @PrintOutput = '@StaffID = ' + CASE WHEN @StaffID = NULL THEN 'Null' ELSE CONVERT(varchar(20), @StaffID) END
        RAISERROR (@PrintOutput, 10, 1) WITH NOWAIT
        IF @StaffID = NULL -- raise error if staffid wasn't found
        BEGIN
            RAISERROR (50001 --error number
                , 16 -- severity
                , 1 --state
                , @CurrentUser -- parameter
                )
        END
    END

    -- Get the variable data type (used to determine where the variable is stored)
    DECLARE @VarDataTypeDesc varchar(20)
    DECLARE @StaffVarID int

    SELECT @VarDataTypeDesc = dt.[StaffVariableDataType] 
    FROM [list].[DataTypes] dt INNER JOIN [list].[StaffVariableTypes] svt ON dt.DataTypeID = svt.DataTypeID 
    WHERE svt.VariableTypeID = @VariableTypeID

    -- update or add the staff variable
    IF EXISTS (SELECT 1 FROM [dbo].[StaffVariables] WHERE StaffID = @StaffID AND [VariableTypeID] = @VariableTypeID) -- update
    BEGIN
        IF @VarDataTypeDesc = 'int'
        BEGIN -- only update here - other data types are updated further down
            UPDATE [dbo].[StaffVariables] SET VariableIntValue = @VariableIntValue WHERE StaffID = @StaffID AND VariableTypeID = @VariableTypeID
        END
        ELSE -- StaffVariableID is only needed if the variable type is not int
        BEGIN
            SELECT @StaffVarID = StaffVariableID FROM [dbo].[StaffVariables] WHERE StaffID = @StaffID AND [VariableTypeID] = @VariableTypeID
        END
    END
    ELSE -- insert
    BEGIN
        IF @VarDataTypeDesc = 'int'
        BEGIN
            INSERT INTO [dbo].[StaffVariables] (StaffID, VariableTypeID, VariableIntValue) 
            VALUES (@StaffID, @VariableTypeID, @VariableIntValue)
        END
        ELSE -- StaffVariableID is only needed if the variable type is not int
        BEGIN
            DECLARE @StaffVarIDTbl table(ID int)
            INSERT INTO [dbo].[StaffVariables] (StaffID, VariableTypeID, VariableIntValue) 
            OUTPUT INSERTED.[StaffVariableID] INTO @StaffVarIDTbl 
            VALUES (@StaffID, @VariableTypeID, @VariableIntValue)

            SELECT @StaffVarID = ID FROM @StaffVarIDTbl
        END
    END

-- Cutting out the section where I deal with other variable types besides int here - not relevant to this problem

END TRY  
BEGIN CATCH  
    DECLARE @ErrorMessage NVARCHAR(4000);  
    DECLARE @ErrorSeverity INT;  
    DECLARE @ErrorState INT;  

    SELECT   
        @ErrorMessage = ERROR_MESSAGE(),  
        @ErrorSeverity = ERROR_SEVERITY(),  
        @ErrorState = ERROR_STATE();  

    -- Use RAISERROR inside the CATCH block to return error  
    -- information about the original error that caused  
    -- execution to jump to the CATCH block.  
    RAISERROR (@ErrorMessage, -- Message text.  
               @ErrorSeverity, -- Severity.  
               @ErrorState -- State.  
               );  
END CATCH;  
END

Вот код запуска тестовой процедуры:

DECLARE @return_value int

EXEC    @return_value = [dbo].[udp_AddUpdateStaffVariable]
        @VariableTypeID = 1,
        @VariableIntValue = 10

SELECT  'Return Value' = @return_value

GO

...и вот ответ:

Msg 50000, Level 16, State 2, Procedure dbo.udp_AddUpdateStaffVariable, Line 130 [Batch Start Line 2]
Cannot insert the value NULL into column 'StaffID', table 'SnippingDbName.dbo.StaffVariables'; column does not allow nulls. INSERT fails.

(1 row affected)

Completion time: 2020-06-01T21:17:08.2049072-05:00

Итак... вот вопрос. Ошибка, по-видимому, указывает на то, что он либо никогда не выполнял всю часть кода if @StaffID = NULL, либо выполнял, но не нашел StaffID и не установил переменную @StaffID. Но если это так, то почему я не вижу результатов своих предыдущих операторов RAISERROR?

Сначала я попробовал PRINT и переключился на RAISERROR, когда PRINT не работал.

SQL Server 2017 Developer Edition, SSMS 15.0.18183.0


person Katerine459    schedule 02.06.2020    source источник
comment
Это не будет вашей ошибкой, но вы должны быть последовательны и использовать throw для возврата информации об ошибке в приложение. raiserror это старый стиль.   -  person Dale K    schedule 02.06.2020
comment
Я ни в коем случае не гуру кодирования, но я думаю, что ваш IF ( @StaffId = NULL ) должен быть IF ( @StaffId IS NULL ). Я не думаю, что ваш идентификатор персонала может когда-либо равняться NULL, он может быть только NULL (если это имеет смысл). Точно так же, непосредственно перед оператором RAISERROR.   -  person MattM    schedule 02.06.2020
comment
^^^ что они сказали... вы сравниваете с нулевым значением, используя IS, а не =   -  person Dale K    schedule 02.06.2020
comment
Ой! Да, исправление = NULL в IS NULL удалило все ошибки. :) Запустим быстрый тест, чтобы посмотреть, что произойдет, если он не найдет текущего пользователя в таблице Staff...   -  person Katerine459    schedule 02.06.2020
comment
Ура! Это сработало! :) Спасибо всем.   -  person Katerine459    schedule 02.06.2020
comment
На самом деле я все еще немного смущен тем, почему я изначально не видел вывод первого оператора RAISERROR (@PrintOutput, 10, 1) WITH NOWAIT. Есть два таких утверждения, и я начал видеть их после того, как ошибка Cannot insert the value NULL into column была исправлена... но я должен был увидеть первое RAISERROR до этого, не так ли?   -  person Katerine459    schedule 02.06.2020


Ответы (1)


Это была синтаксическая ошибка, которую поняли люди, комментирующие вопрос. IF (@StaffID = NULL) должно было быть, IF (@StaffID IS NULL) Исправление этого во всех местах процедуры устранило проблему, а изменение моей тестовой записи персонала таким образом, чтобы имя пользователя не совпадало с SUSER_SNAME(), привело к ожидаемой ошибке.

person Katerine459    schedule 02.06.2020
comment
Пожалуйста, отметьте это как ответ, так что это будет полезно для людей в будущем - person Venkataraman R; 02.06.2020
comment
Я буду, но на самом деле я все еще чего-то не понимаю во всем этом (это в комментарии, который я только что сделал под исходным вопросом). - person Katerine459; 02.06.2020