web-dev-qa-db-ja.com

OracleUNIONとORDERBYに関する奇妙な問題

次のクエリは、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

ただし、これは 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

私はこの問題をいじってみましたが、少なくとも最初の副選択と2番目の最後(??)の副選択が必要であることがわかりましたxという列があります。最初の例では、2つの副選択は単純に一致しているように見えました。 実例

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

質問:

これはOracleSQLパーサーの(既知の)バグですか、それともORDER BY句から参照される名前の列を保持するために最初と最後から2番目の副選択を絶対に必要とする言語構文の非常に微妙な詳細がありますか?

26
Lukas Eder

これは実際には質問に答えませんが、言語要件というよりはパーサーのバグ(または「機能」)のようです。

My Oracle Supportによると、これはバグ14196463として発生したようですが、解決せずに終了しました。 コミュニティスレッド3561546 にも記載されています。ただし、これらのいずれかを表示するには、MOSアカウント、または少なくともOracleアカウントが必要です。

それはまた議論されました OTNスレッドで これは私が知る限りMOSアカウントではなく、基本的なOracleログインを必要とします。それもあまりありません情報ですが、調査結果を繰り返します。また、動作が少なくとも9.2.0.8まで、おそらくはるか以前に存在していたことも示唆しています。

ドキュメント は少し曖昧ですが、これが問題になると予想されることを示していません:

集合演算子UNIONINTERSECTMINUS、またはUNION ALLを含む複合クエリの場合、ORDER BY句は、明示的な式ではなく、位置またはエイリアスを指定する必要があります。また、ORDER BY句は、最後のコンポーネントクエリにのみ表示できます。 ORDER BY句は、複合クエリ全体から返されるすべての行を並べ替えます。

あなたはあなたの式をエイリアスしてそれを使用しています、そしてそれはあなたが特定のコンポーネントをエイリアスする必要があるとは言いません(もちろんそれはあなたをしないとは言いませんがどちらかをする必要があります)。

動作は、エイリアスが最終的な投影に有効であることに矛盾しているように見えます。エイリアスに関する通常のルールは、order by句でのみ有効です。これは、その中間にあるようです。

8
Alex Poole

これは、現在のクエリから一貫性のない動作が発生する理由には答えませんが、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)を1回だけ指定します。

4
tbone