Любопытная проблема с Oracle UNION и ORDER BY

следующий запрос прекрасно действует практически в каждой базе данных (или dual фиктивная таблица), включая Oracle:

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

Я играл с этой проблемой и выяснил, что, по-видимому, по крайней мере, первый подселект и второй-последний (??) subselect должен иметь столбец с именем 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 предложения?

2 ответов


это на самом деле не отвечает на вопрос, но, похоже, это ошибка парсера (или "функция"), а не языковое требование.

согласно моей поддержке Oracle, это, похоже, было поднято как ошибка 14196463, но закрыто без разрешения. Это также упоминается в сообщество thread 3561546. Вам нужна учетная запись MOS или, по крайней мере, учетная запись Oracle, чтобы увидеть любой из них.

это также обсуждалось в потоке OTN что насколько я могу судить, требуется базовый логин Oracle, а не учетная запись MOS. Это также не имеет большой информации, но повторяет ваши выводы, а также предполагает, что поведение существовало по крайней мере до 9.2.0.8 и, возможно, намного раньше.

документация немного расплывчато, но не указывает, что это, как ожидается, будет проблемой:

для составных запросов, содержащих операторы set UNION, INTERSECT, MINUS или UNION ALL на ORDER BY предложение должно указывать позиции или псевдонимы, а не явные выражения. Кроме того,ORDER BY предложение может появиться только в последнем запросе компонента. The 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) один раз.