以下查询在几乎所有数据库(提供或采用虚拟表)中都完全有效dual,包括 Oracle:
dual
select 'A' as x from dual union all select 'B' from dual order by x asc
返回:
| X | |---| | A | | B |
现在这个查询仍然是相当标准的 SQL,但在 Oracle 上不起作用
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
然而,这有效:
select 'A' as x from dual union all select 'B' as x from dual union all select 'C' from dual order by x asc
我一直在解决这个问题,并发现显然,至少第一个子选择和倒数第二个(??) 子选择需要有一个名为x. 在第一个示例中,两个子选择似乎只是重合。工作示例:
x
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
您可能已经猜到了,这行不通:
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
派生表似乎不受此限制。这有效:
select * from ( select 'A' as x from dual union all select 'B' from dual union all select 'C' from dual ) order by x asc
这是 Oracle SQL 解析器中的(已知的?)错误,还是语言语法中是否有任何非常微妙的细节,绝对需要第一个和倒数第二个子选择来保存从ORDER BY子句中引用的名称列?
ORDER BY
这并没有真正回答问题,但它似乎是解析器错误(或“功能”)而不是语言要求。
根据 My Oracle Support,这似乎是作为错误 14196463 提出的,但没有解决就关闭了。社区线程 3561546 中也提到了它。您需要一个 MOS 帐户,或者至少是一个 Oracle 帐户,才能查看其中任何一个。
据我所知,在 OTN 线程中也讨论过它需要基本的 Oracle 登录名而不是 MOS 帐户。这也没有太多信息,但重复了您的发现,并且还表明该行为至少可以追溯到 9.2.0.8 甚至更早。
该文档有点含糊,但并不表明这预计会成为问题:
对于包含集合运算符UNION、INTERSECT、MINUS或 的复合查询UNION ALL,该ORDER BY子句必须指定位置或别名而不是显式表达式。此外,该ORDER BY子句只能出现在最后一个组件查询中。该ORDER BY子句对整个复合查询返回的所有行进行排序。
UNION
INTERSECT
MINUS
UNION ALL
您正在为您的表达式添加别名并使用它,它并没有说您必须为特定组件添加别名(尽管当然它也没有说您不必)。
该行为似乎与对最终投影有效的别名不一致,并且关于别名的通常规则仅在 order by 子句中有效 - 这似乎介于两者之间。