我对SQL标准有疑问,我希望SQL language lawyer可以提供帮助。
某些表达式不起作用。例如62 / 0
。 SQL标准指定了表达式可能以类似方式出错的几种方式。许多语言使用特殊的异常流量控制或bottom伪值来处理这些表达式。
我有一个表格t
,其中包含({only)两列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的一个偶数值时,允许实现返回前几百万个结果,然后在接近结束时发现除零。 y的零值?是否需要缓冲?
还有更糟糕的情况,思考这个,根据语义可能会破坏布尔短路或在限制中需要四值布尔逻辑:
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
看起来这个值应该是一个错误,因为它取决于结果的空虚或非空洞,这是一个错误,但采用这些语义似乎会禁止优化器在这里短路表扫描。这种存在查询是否需要证明存在一个非触底行,或者是否存在触底行?
我很感激这里的指导,因为我似乎无法找到规范的相关部分。
答案 0 :(得分:1)
我使用的所有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
。它没有,因此它不包括列计算中的记录,并将其保留在原来的位置。