Почему 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. Баунти для тех, кто может показать это исправлено в более ранней версии!
5 ответов
Не могу сказать, когда это было исправлено, но вот мои результаты:
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
Искал поддержку Oracle и нашел это:
Ошибка 5368296 - SQL-соединение ANSI может не отображать 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 Support для просмотра подробностей, но считал, что затронутые число / версии ошибок Oracle будут в порядке, чтобы поделиться, чтобы указать вам правильное направление в Oracle Support.
Вы используете ANSI SQL. Я предполагаю, что это связывает STATUS в предложении where с таблицей управления.
Когда вы используете синтаксис "оракул", вы увидите ожидаемое поведение.
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'
Более подтвержденная ошибка об этом здесь: http://oracledoug.com/serendipity/index.php?/archives/1555-Bug-Hunting.html
Последнее обновление - это исправлено в 11.2.0.2
Ну, если я попробую это на 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'