SQL Server-WHERE子句中的零除错误(即使条件除数> 0)

时间:2018-10-04 13:35:12

标签: sql sql-server divide-by-zero

使用WHERE子句测试涉及除法的SQL查询时,我遇到了一个看似奇怪的错误。任务是在以下 any 为真的情况下查找发票中的错误:

  • AmountTax均为零(不是两个);
  • AmountTax都不为零,但它们不满足某些算术条件。

所以我想出的查询如下:

SELECT InvoiceNumber, InvoiceDate, Amount, Tax
FROM Invoices
    WHERE (Amount <> 0 AND Tax = 0)
    OR (Amount = 0 AND Tax <> 0)
    OR (Amount <> 0 AND Tax <> 0 AND ABS(Tax / Amount - 0.18) > 0.005)

为了使事情更奇怪,此查询可以正常运行:

SELECT InvoiceNumber, InvoiceDate, Amount, Tax
FROM Invoices
    WHERE Amount <> 0 AND Tax <> 0 AND ABS(Tax / Amount - 0.18) > 0.005

我猜想SQL Server条件子句中的布尔值评估不能像C#中那样工作(我可以期望懒惰的评估防止零错误除法)。

如何使该查询正确?

注意: :有数千万条记录,因此嵌套的SELECT语句可能会影响性能。

2 个答案:

答案 0 :(得分:3)

不要依赖于查询中子句或条件的求值顺序。期。 优化器保留重新安排所有内容以提高性能的权利。好的,不是全部。 CASE表达式具有确定的求值顺序。

解决方案非常简单。使用NULLIF()

WHERE (Amount <> 0 AND Tax = 0) OR
      (Amount = 0 AND Tax <> 0) OR
      (Amount <> 0 AND Tax <> 0 AND ABS(Tax / NULLIF(Amount, 0) - 0.18) > 0.005)

WHERE Amount <> 0 AND Tax <> 0 AND ABS(Tax / NULLIF(Amount, 0) - 0.18) > 0.005

答案 1 :(得分:-1)

您尝试使用括号

 SELECT InvoiceNumber, InvoiceDate, Amount, Tax
FROM Invoices
    WHERE (Amount <> 0 AND Tax = 0)
    OR (Amount = 0 AND Tax <> 0)
    OR (Amount <> 0 AND Tax <> 0 AND ABS(Tax / Amount - 0.18) > 0.005)

在处理多个条件(或/和)时,请尝试使用“()”进行分隔。

运算符的逻辑顺序是

  • 算术
  • 串联
  • 比较条件
  • IS [NOT]为NULL,类似[NOT] IN
  • [不]之间
  • 不等于
  • AND
  • OR

您可以使用括号来处理此规则。