SQL 服务器 - 在 WHERE 子句中除以零错误(即使条件除数 > 0)

SQL Server - divide by zero error in WHERE clause (even with condition divisor > 0)

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

所以我提出的查询如下:

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 服务器条件子句中的布尔值求值与 C# 中的不同(我希望惰性求值可以防止被零除错误)。

如何使这个查询正确?

NOTE:记录数千万条,嵌套SELECT语句可能会影响性能

你试过使用括号吗

 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)

在处理多个条件时 (Or/And) 尝试使用“()”分隔。

运算符的逻辑顺序是

  • 算术
  • 串联
  • 比较条件
  • IS [NOT] NULL, LIKE, [NOT] IN
  • [不]在
  • 之间
  • 不等于
  • 不是

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

不依赖于查询中子句或条件的评估顺序。时期。 优化器保留重新安排所有内容以提高性能的权利。好吧,不是所有内容。 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