处理SQL标准中的错误值

时间:2009-07-16 23:44:45

标签: sql error-handling language-design semantics

我对SQL标准有疑问,我希望SQL language lawyer可以提供帮助。

某些表达式不起作用。例如62 / 0。 SQL标准指定了表达式可能以类似方式出错的几种方式。许多语言使用特殊的异常流量控制或bottom伪值来处理这些表达式。

我有一个表格t,其中包含({only)两列xy,每列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

看起来这个值应该是一个错误,因为它取决于结果的空虚或非空洞,这是一个错误,但采用这些语义似乎会禁止优化器在这里短路表扫描。这种存在查询是否需要证明存在一个非触底行,或者是否存在触底行?

我很感激这里的指导,因为我似乎无法找到规范的相关部分。

1 个答案:

答案 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。它没有,因此它不包括列计算中的记录,并将其保留在原来的位置。