【问题标题】:Curious issue with Oracle UNION and ORDER BYOracle UNION 和 ORDER BY 的奇怪问题
【发布时间】:2014-10-12 19:42:38
【问题描述】:

以下查询在几乎所有数据库中都是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

我一直在研究这个问题,并发现显然,至少第一个子选择和 second-last (??) 子选择需要有一个名为 x 的列。在第一个示例中,两个子选择似乎只是重合。 Working example:

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

你可能已经猜到了,这个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' as x from dual union all
select 'F'      from dual union all
select 'G'      from dual
order by x asc

有趣的旁注:

派生表似乎不受此限制的影响。 This works:

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 子句?

【问题讨论】:

  • 只是补充一点,在SQL Server 2008 R2 的第一个选择 - 列上必须有别名。
  • @Elias:是的,到目前为止,我已经尝试过使用 SQL Server、PostgreSQL 和 H2。
  • 似乎已作为错误 14196463 提出,但没有解决就关闭了。在社区线程 3561546 中也提到过。仅供参考,在 11.2.0.3 和 10.2.0.5 中转载。

标签: sql oracle oracle11g sql-order-by union-all


【解决方案1】:

这并不能真正回答问题,但它似乎是解析器错误(或“功能”)而不是语言要求。

根据 My Oracle Support,这似乎已作为错误 14196463 提出,但没有解决就关闭了。 community thread 3561546 中也提到了这一点。您需要一个 MOS 帐户,或至少一个 Oracle 帐户,才能查看其中任何一个。

据我所知,in an OTN thread 也被讨论过,它需要基本的 Oracle 登录而不是 MOS 帐户。这也没有太多信息,但重复了您的发现,并且还表明该行为至少可以追溯到 9.2.0.8 甚至更早。

The documentation 有点含糊,但并不表示这会是个问题:

对于包含集合运算符UNIONINTERSECTMINUSUNION ALL 的复合查询,ORDER BY 子句必须指定位置或别名,而不是显式表达式。此外,ORDER BY 子句只能出现在最后一个组件查询中。 ORDER BY 子句对整个复合查询返回的所有行进行排序。

您正在为您的表达式加上别名并使用它,它并没有说您必须为特定的组件加上别名(当然它也没有说您不必也必须这样做)。

该行为似乎与别名对最终投影有效,并且关于别名仅在 order by 子句中有效的通常规则不一致 - 这似乎介于两者之间。

【讨论】:

  • 感谢您的回答。在OTN线程中,也有人得出结论,“'有趣的是'它似乎要求第一组和倒数第二组列有别名”。我会接受这个作为我的问题的答案“这是 Oracle SQL 解析器中的(已知?)错误”
【解决方案2】:

这并不能回答为什么您从当前查询中得到不一致的行为,但在 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)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-06
    • 1970-01-01
    相关资源
    最近更新 更多