【问题标题】:Supercede null results in stored procedure and VBA在存储过程和 VBA 中取代 null 结果
【发布时间】:2017-09-29 05:45:58
【问题描述】:

我写了一个简单的存储过程,我似乎无法覆盖空返回值。

ALTER PROC [dbo].[rt_sp_rstk_OpticComplete]
    @serial varchar(50) OUTPUT,     
    @remaining int OUTPUT
AS
    SET NOCOUNT ON
BEGIN
    UPDATE [ROBOTICS_OPTICS_MECHUAT].[dbo].[RESTOCK_OPTICS]  
    SET [SELECTED] = 'False', 
        [COMPLETED] = 'True' 
    WHERE [SERIAL_NUMBER] = @serial     

    UPDATE [ROBOTICS_OPTICS_MECHUAT].[dbo].[RESTOCK_JOB_QUEUE] 
    SET [QUANTITY_REMAINING] = [QUANTITY_REMAINING] - 1 
    WHERE [SELECTED] = 'True'   

    SET @remaining = (SELECT [QUANTITY_REMAINING] 
                      FROM [ROBOTICS_OPTICS_MECHUAT].[dbo].[RESTOCK_JOB_QUEUE] 
                      WHERE [SELECTED] = 'True')

    RETURN ISNULL(@remaining, 0)
END

我已经尝试使用IF NULLIF(@serial, '') IS NULL 验证该过程,但它似乎并不重要。问题是函数“可以”在不经意间被执行(极端情况)。我无法真正避免它,因为我在多个方向上使用该函数,所以我能做的最好的事情就是当 select 语句导致 null 时返回一个“0”。

Function restockOpticComplete(serial As String) As Integer
    Dim remaining As Integer
    Dim opticSerNo As String

    errorPosition = "queryForOptics.restockOpticComplete"
    On Error GoTo errorTrap
    Err.Clear

    Set conn = New ADODB.Connection
    Set cmd = New ADODB.Command
    constr = "Provider=sqloledb;data source=i.p.add.ress;initial catalog=CATALOG;user id=USER;password=PASS"
    conn.Open constr
    cmd.ActiveConnection = conn

    With cmd
        .ActiveConnection = conn
        .CommandType = adCmdStoredProc
        .CommandText = "rt_sp_rstk_OpticComplete"
        .CommandTimeout = 2
        .NamedParameters = True
        .Parameters.Append .CreateParameter("@serial", adVarChar, adParamInputOutput, 50, serial)
        .Parameters.Append .CreateParameter("@remaining", adInteger, adParamOutput, , 0)
        .execute
    End With

    Set eTag = ThisDisplay.tagDisplay.item("_Eventwatcher").EGroup.item("Restock\activeOpticSerial")
    eTag.Value = ""
    Set eTag = ThisDisplay.tagDisplay.item("_Eventwatcher").EGroup.item("Restock\activeOpticStack")
    eTag.Value = 0
    Set eTag = ThisDisplay.tagDisplay.item("_Eventwatcher").EGroup.item("Restock\activeOpticTray")
    eTag.Value = 0
    Set eTag = ThisDisplay.tagDisplay.item("_Eventwatcher").EGroup.item("Restock\activeOpticPosition")
    eTag.Value = 0
    remaining = cmd.Parameters("@remaining").Value
    Set eTag = ThisDisplay.tagDisplay.item("_Eventwatcher").EGroup.item("Restock\activeJobRemaining")
    eTag.Value = remaining

    restockOpticComplete = remaining

    GoTo cleanExit

cleanExit:
    On Error Resume Next
    conn.Close

    Exit Function

errorTrap:
    LogDiagnosticsMessage "Restock.gfx, Position: " & errorPosition & " , Error Code: [ " & Hex(Err.Number) & "], Description: " & Err.Description & ""
    Resume cleanExit

End Function

我错过了什么?

【问题讨论】:

  • 啊错过了 VBA 部分......那么实际的问题是什么?您遇到了问题,但我不知道问题是什么。
  • @SeanLange 虽然我使用的是 ISNULL,但我仍然得到空值。
  • 您正在使用剩余的值,但在您的代码中您没有将其设置为不为空。相反,您将返回一个数字。最简单的解决方法是将单词“RETURN”更改为“SELECT”。他们的编码方式你需要检查 RETURN_VALUE 但诚实地使用输出参数是首选方法。

标签: sql sql-server vba stored-procedures


【解决方案1】:

尝试将 ISNULL 条件放在 "set @remaining =" ... 之后。

            ALTER PROC [dbo].[rt_sp_rstk_OpticComplete]
                @serial varchar(50) OUTPUT,     
                @remaining int OUTPUT
            AS
                SET NOCOUNT ON
            BEGIN
                UPDATE [ROBOTICS_OPTICS_MECHUAT].[dbo].[RESTOCK_OPTICS]  
                SET [SELECTED] = 'False', 
                    [COMPLETED] = 'True' 
                WHERE [SERIAL_NUMBER] = @serial     

                UPDATE [ROBOTICS_OPTICS_MECHUAT].[dbo].[RESTOCK_JOB_QUEUE] 
                SET [QUANTITY_REMAINING] = [QUANTITY_REMAINING] - 1 
                WHERE [SELECTED] = 'True'   

                SET @remaining = ISNULL((SELECT [QUANTITY_REMAINING] 
                                  FROM [ROBOTICS_OPTICS_MECHUAT].[dbo].[RESTOCK_JOB_QUEUE] 
                                  WHERE [SELECTED] = 'True'),0)

                RETURN @remaining
            END

测试

                --- test 1
                CREATE PROC [dbo].[rt_sp_rstk_OpticComplete_test]
                    @val INT,  
                    @remaining int OUTPUT 
                AS
                    SET NOCOUNT ON
                BEGIN
                    SET @remaining = @val
                    RETURN   isnull(@remaining,0)

                END

                GO

                DECLARE  @remaining INT 
                EXEC [dbo].[rt_sp_rstk_OpticComplete_test]null,@remaining OUTPUT

                SELECT @remaining

                GO

                DROP PROC [dbo].[rt_sp_rstk_OpticComplete_test]
                GO

                --- test 2
                CREATE PROC [dbo].[rt_sp_rstk_OpticComplete_test]
                    @val INT,  
                    @remaining int OUTPUT 
                AS
                    SET NOCOUNT ON
                BEGIN


                    SET @remaining = isnull(@val,0)
                    RETURN  @remaining
                END

                GO


                DECLARE  @remaining INT 
                EXEC [dbo].[rt_sp_rstk_OpticComplete_test]null,@remaining OUTPUT
                SELECT @remaining

                GO

                DROP PROC [dbo].[rt_sp_rstk_OpticComplete_test]
                GO

结果:

        -----------
        NULL

        (1 row(s) affected)


        -----------
        0

        (1 row(s) affected)

【讨论】:

  • 当我回到我的这部分代码时,我会玩这个。我可以发誓我已经尝试过了,但谁记得:P
猜你喜欢
  • 1970-01-01
  • 2017-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-05
相关资源
最近更新 更多