次のクエリは、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番目の副選択を絶対に必要とする言語構文の非常に微妙な詳細がありますか?
これは実際には質問に答えませんが、言語要件というよりはパーサーのバグ(または「機能」)のようです。
My Oracle Supportによると、これはバグ14196463として発生したようですが、解決せずに終了しました。 コミュニティスレッド3561546 にも記載されています。ただし、これらのいずれかを表示するには、MOSアカウント、または少なくともOracleアカウントが必要です。
それはまた議論されました OTNスレッドで これは私が知る限りMOSアカウントではなく、基本的なOracleログインを必要とします。それもあまりありません情報ですが、調査結果を繰り返します。また、動作が少なくとも9.2.0.8まで、おそらくはるか以前に存在していたことも示唆しています。
ドキュメント は少し曖昧ですが、これが問題になると予想されることを示していません:
集合演算子
UNION
、INTERSECT
、MINUS
、またはUNION ALL
を含む複合クエリの場合、ORDER BY
句は、明示的な式ではなく、位置またはエイリアスを指定する必要があります。また、ORDER BY
句は、最後のコンポーネントクエリにのみ表示できます。ORDER BY
句は、複合クエリ全体から返されるすべての行を並べ替えます。
あなたはあなたの式をエイリアスしてそれを使用しています、そしてそれはあなたが特定のコンポーネントをエイリアスする必要があるとは言いません(もちろんそれはあなたをしないとは言いませんがどちらかをする必要があります)。
動作は、エイリアスが最終的な投影に有効であることに矛盾しているように見えます。エイリアスに関する通常のルールは、order by句でのみ有効です。これは、その中間にあるようです。
これは、現在のクエリから一貫性のない動作が発生する理由には答えませんが、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回だけ指定します。