Подтвердить что ты не робот

Почему Oracle не создает "ORA-00918: столбец неоднозначно определен" для этого запроса?

Я только что встретил странное поведение в Oracle, где я ожидал бы, что ORA-00918 будет поднят, но это не так. Возьмите этот запрос, например.

SELECT *
FROM USER_TABLES TAB
JOIN USER_TRIGGERS TRG ON TRG.TABLE_NAME = TAB.TABLE_NAME
WHERE STATUS = 'DISABLED'

Этот запрос, как правило, ищет информацию о таблицах с отключенными триггерами, но обратите внимание, что это не проблема, которую я пытаюсь решить. Проблема не уникальна для этого запроса, словаря данных, представлений или таблиц; насколько я могу судить, это относится к любому набору таблиц или представлений (из двух или трех, которые я пробовал).

Во всяком случае, попробуйте запустить этот запрос, и вы получите ORA-00918, потому что оба USER_TABLES и USER_TRIGGERS имеют столбец с именем STATUS, поэтому для запроса запроса для выполнения предложения WHERE необходимо изменить на TRG.STATUS. Хорошо, круто, но попробуйте вместо этого присоединиться к другой таблице.

SELECT *
FROM USER_TABLES TAB
JOIN USER_TRIGGERS TRG ON TRG.TABLE_NAME = TAB.TABLE_NAME
JOIN USER_CONSTRAINTS CON ON CON.TABLE_NAME = TAB.TABLE_NAME
WHERE STATUS = 'DISABLED'

Этот запрос, не определяя, какую колонку STATUS вы подразумеваете, волшебным образом работает! Не обращайте внимания на семантику или то, что возвращает запрос, нет ошибки. USER_CONSTRAINTS тоже имеет столбец с именем STATUS, так как он не знает, что делать, когда есть два столбца на выбор, но все в порядке с еще большей двусмысленностью?

Все это на 10.2.0.3.0 кстати, и по существу ORA-00918 перестает подниматься, если в вашем запросе содержится более двух таблиц. Если это ошибка Oracle, знает ли кто-нибудь, когда она была исправлена, и поэтому какая версия Oracle может вызвать проблемы с ковбойским кодом, если наша база данных будет обновлена?

Обновление

Благодаря BQ для демонстрации ошибки исправлено в 11.2.0.1.0. Bounty для всех, кто может показать его исправленным в более ранней версии!

4b9b3361

Ответ 1

Не могу сказать, когда он был исправлен, но вот мои результаты:

Connected to:
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options

SQL> SELECT *
  2  FROM USER_TABLES TAB
  3  JOIN USER_TRIGGERS TRG ON TRG.TABLE_NAME = TAB.TABLE_NAME
  4  WHERE STATUS = 'DISABLED';
WHERE STATUS = 'DISABLED'
      *
ERROR at line 4:
ORA-00918: column ambiguously defined

SQL> ed
Wrote file afiedt.buf

  1  SELECT *
  2  FROM USER_TABLES TAB
  3  JOIN USER_TRIGGERS TRG ON TRG.TABLE_NAME = TAB.TABLE_NAME
  4  JOIN USER_CONSTRAINTS CON ON CON.TABLE_NAME = TAB.TABLE_NAME
  5* WHERE STATUS = 'DISABLED'
SQL> /
WHERE STATUS = 'DISABLED'
      *
ERROR at line 5:
ORA-00918: column ambiguously defined

Ответ 2

Искал поддержку Oracle и нашел следующее:

Ошибка 5368296 - ANSI join SQL может не сообщать ORA-918 для неоднозначного столбца [ID 5368296.8]

Версии подтверждены как затронутые:

  • 10.2.0.3
  • 10.2.0.4

Эта проблема исправлена ​​в

  • 10.2.0.4 Патч 2 на платформах Windows
  • 10.2.0.5 (набор патчей для сервера)
  • 11.1.0.6 (базовый выпуск)

Не публикуйте больше, чем нужно, так как вам нужна учетная запись службы поддержки Oracle, чтобы просмотреть детали, но подумал, что число или версии Oracle Bug, затронутые вами, будут в порядке, чтобы указать вам правильное направление поддержки Oracle.

Ответ 3

Вы используете ANSI SQL. Я предполагаю, что он связывает STATUS в разделе where с таблицей вождения.

Когда вы используете синтаксис "oracle", вы увидите ожидаемое поведение.

SELECT *
FROM USER_TABLES TAB, USER_TRIGGERS TRG, USER_CONSTRAINTS CON
WHERE TRG.TABLE_NAME = TAB.TABLE_NAME
AND CON.TABLE_NAME = TAB.TABLE_NAME
AND STATUS = 'DISABLED'

Ответ 5

Хорошо, если я попробую это на 11.2.0.2.0, я получаю ту же проблему. Независимо от функциональности, если вы добавляете некоторые левые и правые соединения, эта ошибка вообще не фиксируется!

SELECT *
FROM USER_TABLES TAB
LEFT JOIN USER_TRIGGERS TRG ON TRG.TABLE_NAME = TAB.TABLE_NAME
RIGHT JOIN USER_CONSTRAINTS CON ON CON.TABLE_NAME = TAB.TABLE_NAME
WHERE STATUS = 'DISABLED'