以下查询在几乎每个数据库中都是perfectly valid(提供或采用dual
虚拟表),包括Oracle:
select 'A' as x from dual union all
select 'B' from dual
order by x asc
返回:
| X |
|---|
| A |
| B |
现在这个查询仍然是非常标准的SQL,但是Oracle上的doesn't work
select 'A' as x from dual union all
select 'B' from dual union all
select 'C' from dual
order by x asc
我正在
ORA-00904: "X": invalid identifier
但是,works:
select 'A' as x from dual union all
select 'B' as x from dual union all
select 'C' from dual
order by x asc
我一直在玩这个问题,并且发现显然,至少第一个子选择和倒数第二个(??)子选择需要有一个名为{{的列1}}。在第一个例子中,两个子选择似乎只是重合。 Working example:
x
正如您可能已经猜到的那样,wouldn't work:
select 'A' as x from dual union all
select 'B' from dual union all
select 'C' from dual union all
select 'D' from dual union all
select 'E' from dual union all
select 'F' as x from dual union all
select 'G' from dual
order by x asc
派生表似乎没有受到此限制。 This works:
select 'A' as x from dual union all
select 'B' from dual union all
select 'C' from dual union all
select 'D' from dual union all
select 'E' as x from dual union all
select 'F' from dual union all
select 'G' from dual
order by x asc
这是Oracle SQL解析器中的一个(已知?)错误,还是语言语法中有任何非常细微的细节,绝对需要第一个和倒数第二个子选择来保存从select * from (
select 'A' as x from dual union all
select 'B' from dual union all
select 'C' from dual
)
order by x asc
条款?
答案 0 :(得分:8)
这并没有真正回答这个问题,但它似乎是一个解析器错误(或“功能”),而不是语言要求。
根据我的Oracle支持,这似乎已被提出为错误14196463,但没有解决方案关闭。它也在community thread 3561546中提到过。您需要一个MOS帐户或至少一个Oracle帐户来查看其中任何一个。
据我所知,还讨论了in an OTN thread,它需要基本的Oracle登录而不是MOS帐户。这也没有太多的信息,但重复你的发现,并且还表明这种行为至少存在于9.2.0.8,可能还要早得多。
The documentation有点含糊不清,但并未表明预计会出现问题:
对于包含集合运算符
UNION
,INTERSECT
,MINUS
或UNION ALL
的复合查询,ORDER BY
子句必须指定位置或别名而不是显式表达式。此外,ORDER BY
子句只能出现在最后一个组件查询中。ORDER BY
子句对整个复合查询返回的所有行进行排序。
您正在使用该表达式别名,并且它并没有说您必须为特定组件添加别名(当然,它并不表示您不必须)。< / p>
该行为似乎与别名对最终投影有效不一致,并且关于别名的通常规则仅在order by子句中有效 - 这似乎在介于两者之间的某处。
答案 1 :(得分:4)
这不能回答为什么你从当前查询中获得不一致的行为,但是在Oracle中你可以轻松地重写如下(它应该永远不会因标识符错误而失败):
with t(x) as (
select 'A' from dual
union all
select 'B' from dual
union all
select 'C' from dual
)
select * from t
order by x asc
额外的好处是你只需要指定列别名(x)一次。