我有一个关于 SQL 标准的问题,我希望得到一个 SQL language lawyer可以帮忙。
某些表达方式是行不通的。 62 / 0
, 例如。 SQL 标准规定了许多表达式可能以类似方式出错的方式。许多语言使用特殊的异常流控制或 bottom 来处理这些表达式。伪值。
我有一张 table ,t
,(仅)两列,x
和 y
每个类型 int
.我怀疑这无关紧要,但为了明确起见,我们假设 (x,y)
是 t
的主键.此表包含(仅)以下值:
x y
7 2
3 0
4 1
26 5
31 0
9 3
SELECT
的 SQL 标准要求什么行为?在此表上操作的表达式可能涉及除以零?或者,如果不需要任何一种行为,那么允许哪些行为?例如,以下 select 语句需要什么行为?
最简单的:
SELECT x, y, x / y AS quot
FROM t
一个更难的:
SELECT x, y, x / y AS quot
FROM t
WHERE y != 0
一个更难的:
SELECT x, y, x / y AS quot
FROM t
WHERE x % 2 = 0
是否允许实现(例如,在此查询的更复杂版本上未能意识到限制可以在扩展内移动的实现)响应此查询而产生除以零错误,因为假设它试图分
3
通过 0
在执行限制和意识到 3 % 2 = 1
之前作为扩展的一部分?这可能变得很重要,例如,扩展是在一个小表上但结果——当与一个大表连接并基于大表中的数据进行限制时——最终限制了所有行要求除以零。如果 t 有数百万行,并且最后一个查询是通过表扫描执行的,那么当遇到一个具有零值的偶数 x 时,是否允许实现在接近末尾发现除以零之前返回前几百万个结果你的?是否需要缓冲?
还有更糟糕的情况,考虑一下这个,这取决于语义可能会破坏 bool 短路或在限制中需要四值 bool 逻辑:
SELECT x, y
FROM t
WHERE ((x / y) >= 2) AND ((x % 2) = 0)
如果表很大,这个短路问题会变得非常疯狂。想象一下这个表有一百万行,其中一个有一个 0 除数。标准会说的是以下语义:
SELECT CASE
WHEN EXISTS
(
SELECT x, y, x / y AS quot
FROM t
)
THEN 1
ELSE 0
END AS what_is_my_value
看起来这个值可能应该是一个错误,因为它取决于一个错误结果的空性或非空性,但采用这些语义似乎会禁止优化器在此处短路表扫描。此存在查询是否需要证明存在一个非底部行,或者还需要证明不存在底部行?
我很感激这里的指导,因为我似乎找不到规范的相关部分。
最佳答案
我使用过的所有 SQL 实现都将除以 0 视为立即 NaN
或 #INF
.该划分应该由前端处理,而不是由实现本身处理。查询不应触底,但结果集需要返回NaN
在这种情况下。因此,它与结果集同时返回,不会向用户显示特殊警告或消息。
无论如何,要正确处理此问题,请使用以下查询:
select
x, y,
case y
when 0 then null
else x / y
end as quot
from
t
为了回答你的最后一个问题,这个声明:
SELECT x, y, x / y AS quot
FROM t
会返回这个:
x y quot
7 2 3.5
3 0 NaN
4 1 4
26 5 5.2
31 0 NaN
9 3 3
所以,你的
exists
将找到 t
中的所有行,不管他们的商是多少。此外,我再次阅读您的问题并意识到我没有讨论
where
条款(耻辱!)。 where
子句,或 predicate
, 应始终在计算列之前应用。想想这个查询:
select x, y, x/y as quot from t where x%2 = 0
如果我们有记录 (3,0),它将应用
where
条件,并检查是否 3 % 2 = 0
.它没有,因此它不会在列计算中包含该记录,并将其保留在原处。
关于sql - SQL标准中错误值的处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1140860/