sql:在字段名前面加上子查询标识符是否会强制首先计算子查询?

snz8szmq  于 2021-07-26  发布在  Java
关注(0)|答案(1)|浏览(553)

我的问题不在于理解在下面的查询中发生了什么(可能在不同的实现中)。而是要理解sql标准是否定义了正确的行为。
包含负整数和正整数的简单表格:

CREATE TABLE x (n INTEGER);

INSERT INTO x VALUES (-2);
INSERT INTO x VALUES (-1);
INSERT INTO x VALUES (0);
INSERT INTO x VALUES (1);
INSERT INTO x VALUES (2);

首先执行此查询:

select n
from x 
where n <> 0 
and   1/n = 1;

显然,人们所期望的智能计算顺序与查询中所写的完全相同,以避免计算1/0,这将导致错误。
然而,sql是一种声明性查询语言,正如在几个问题中已经探讨过的那样,where子句的顺序无关紧要,因此可以按任何顺序对它们进行求值,这意味着可能会发生被0除的错误。这很清楚。
第二个例子:

select nonzero.n
from (select n from x where n <> 0) as nonzero
where 1/nonzero.n = 1;

就表上的where子句而言,这在逻辑上是相同的 x ,但它们的组织方式不同。这次我定义了一个不能有0的关系。主查询显式计算 1/nonzero.n ,因此我直觉上希望引擎在这里强制执行求值顺序,而不会看到任何除以0的结果。
请注意,这不是我在实践中看到的唯一评估选项。一些sql引擎会首先将第二个查询展平到第一个查询。
不管不同的实现做什么,我的问题是:当我编写sql时,sql标准是否以任何方式强制执行 nonzero.n 那么 n 真的是从关系中取出来的 nonzero 而不是来自 x ,这显然是不等价的?如果是这样的话,你会知道这是在哪里正式表达的任何指针吗?

7gs2gvoe

7gs2gvoe1#

该标准没有明确规定要做什么。它在错误处理方面相当薄弱。
更重要的是,该标准非常明确,没有强制执行表达式和查询组件的求值顺序——子查询或查询中的表达式没有顺序 select . 查询作为一个整体来描述结果集,而不是创建结果集的分步说明。
这是故意的。编写标准的人知道执行计划通常是一个有向无环图(dag),它与原始查询无关(除了实现它!)。
请注意,有些情况下 1/0 一点也不评估。一些数据库访问:

where exists (select 1 / 0
              from t
              where . . .
             )

exists只关心是否返回行,而不关心这些行上的值是什么。

相关问题