SQL 服务器 - 在 WHERE 子句中除以零错误(即使条件除数 > 0)
SQL Server - divide by zero error in WHERE clause (even with condition divisor > 0)
我在使用涉及除法的 WHERE
子句测试 SQL 查询时遇到了一个看似奇怪的错误。任务是查找发票中的错误,其中 任何 为真:
Amount
或 Tax
中的一个为零(不能同时为零);
Amount
和Tax
都不为零,但不满足一定的运算条件
所以我提出的查询如下:
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
我在使用涉及除法的 WHERE
子句测试 SQL 查询时遇到了一个看似奇怪的错误。任务是查找发票中的错误,其中 任何 为真:
Amount
或Tax
中的一个为零(不能同时为零);Amount
和Tax
都不为零,但不满足一定的运算条件
所以我提出的查询如下:
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