【问题标题】:SQL -VB - Does it evaluate the else even when the if is true?SQL -VB - 即使 if 为真,它也会评估 else 吗?
【发布时间】:2011-10-25 19:21:29
【问题描述】:

我正在尝试防止 #error 在我正在创建的报告中显示

当我将 2 个数字相除而其中一个为零时会发生这种情况

所以我尝试在进行除法之前使用 if/switch 语句检查 2 个数字中的任何一个是否为 0:

    =IIf(Fields!Field1.Value = 0 
            or Fields!Field2.Value = 0 
            or Not(IsNumeric(Fields!Field1.Value)) 
            or Not(IsNumeric(Fields!Field2.Value)), 
        0, 
        (Fields!Field1.Value/Fields!Field2.Value)*100
    )


    =Switch(
            Fields!Field1.Value = 0 or Fields!Fields.Value = 0, 0,
            IsNumeric(Fields!Field1.Value) or IsNumeric(Fields!Fields.Value), (Fields!Field1.Value/Fields!Fields.Value)*100
    )

这两个仍然抛出错误。即使 if 语句为真,似乎仍然会评估 else 条件

如果我将代码更改为只为 if 和 else 打印 X 或 Y,那么它可以工作 - 所以 if 语句中没有错误

这对我来说似乎很荒谬

请告诉我我做错了什么?当 if 为真时,我不敢相信语言会评估 else

编辑

因此,似乎评估了 else 条件。那么如何避免潜在除以零误差呢?

答案来自: http://www.sqlservercentral.com/Forums/Topic442497-150-1.aspx#bm1115960

另一种选择(特别是如果您的报表包含许多可能导致被零除的表达式,则使用自定义代码函数。

在报告属性的代码选项卡/窗口中,输入如下内容:

Public Function DivideBy(ByVal Exp1, ByVal Exp2)
If Exp2 = 0 Then
DivideBy = 0
Else : DivideBy = Exp1 / Exp2
End If
End Function

然后插入表达式 =code.DivideBy(Field!ToBeDivided.Value,Field!DividingBy.Value) 进入任何可能出现被零除问题的单元格。

【问题讨论】:

    标签: sql sql-server-2005 reporting-services


    【解决方案1】:

    我试图在 RS 2005 中重现此错误,但我不能!我拿了以下数据集:

    select 5 as field1, 0 as field2
    union
    select 10 as field1, 5 as field2
    union
    select null as field1, 5 as field2
    union 
    select 3 as field1, null as field2
    union 
    select null as field1, null as field2
    union 
    select 0 as field1, null as field2
    union
     select null as field1,  0 as field2
    union
     select 11 as field1, 10 as field2
    union
     select PI() as field1, 0 as field2
    union
    select PI() as field1, PI() as field2
    

    并使用了您的表达方式,并在切换时使用了 Jon Egerton 的更正。然后我做了一个纯粹的无检查除法。

    你的两个表达式都有效,即使我除以 0,我也会得到“Infinity”或“Nan”,但不是#Error。

    如果将除法替换为 1/0,会发生什么情况。你得到#Error还是你得到Infinity?

    【讨论】:

      【解决方案2】:

      IIF 是一个函数,一个函数的所有参数都在函数本身被计算之前被计算。

      为防止出现此问题,您需要使用完整的 If/Else 语句。

      同样相关,如果您习惯于对布尔表达式进行短路评估(例如 C 派生语言中的 &&),则需要在 VB.Net 中使用 AndAlso 和 OrElse。

      【讨论】:

      • AndAlso 和 OrElse 在这里没有帮助 - 它们有助于阻止条件的后面部分进行评估,但这里的问题是结果的第二(else)部分正在被评估。跨度>
      • 好点,我的意思是在普通 IF 语句的上下文中...... :(
      【解决方案3】:

      对于 VB 中的 IIF 语句,我认为一切都会被评估,而不管初始条件如何。这是必须在 IIF 语句中解决的问题。

      在第二个语句中,来自第一个 IIF 语句的 Fields!Field**2**.Value 已变为 Fields!Field**s**.Value。该语句中的错误可能是因为 .Value 将导致错误,如果 Fields!Fields 什么都没有

      【讨论】:

      • 不 - 我只是手动更改了此处发布的字段名称以伪装我们的公司名称 - 只是在这样做时打错了
      • 很公平。不会说这是一个狡猾的命名约定! ;-)
      【解决方案4】:

      Iif() 和 Switch() 都是函数调用,因此传递给它们的任何参数都将被计算。它们没有短路能力。

      【讨论】:

      • 我可以使用替代方法来防止除以零错误吗?
      • 我不明白为什么您的 IIf() 会生成 #Error。你真的只需要检查除数 - Field2.Value - 无论如何。值可能是Nothing?
      • 不,恐怕不是,这两个值显示在其他地方的报告中,我可以看到其中一个是零,其中一个是小数。
      【解决方案5】:

      是的,IIf 函数的真假部分都会被评估:

      http://en.wikipedia.org/wiki/IIf#Side_Effects

      副作用
      IIf 的另一个问题是因为它是一个库 函数:与 C 派生的条件运算符不同,truepart 和 falsepart 将被评估,无论哪个实际上是 回来。考虑以下示例:

      value = 10 
      result = IIf(value = 10, TrueFunction, FalseFunction)
      

      虽然 TrueFunction 是要调用的函数,但 IIf 会 导致 TrueFunction 和 FalseFunction 都被执行。

      也考虑一下这个:

      a = 10 
      b = 0 
      result = IIf(b <> 0, a / b, 0) 
      

      当程序员 旨在通过执行除以零来避免引发错误, 只要 b 为零,错误就会实际发生。这是因为 sn-p 中的代码将被读取为

      a = 10 b = 0
      _temp1 = a / b ' Error if b = 0
      _temp2 = 0
      _temp3 = b <> 0 result = IIf(_temp3, _temp1 , _temp2) 
      

      这个问题使得 IIf() 调用不如条件运算符有用。解决 这个问题,微软开发人员曾考虑将 IIf 转换为 内在函数;如果发生这种情况,编译器将是 能够通过替换来执行类型推断和短路 使用内联代码调用函数。

      【讨论】:

      • 哇——我惊呆了。那么防止除以零错误的最佳方法是什么?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-20
      相关资源
      最近更新 更多