Я обнаружил, что мой подзапрос не вызывает ошибки, когда должен. документы не указывает на то, что это потенциальная проблема, поэтому я считаю, что мне не хватает чего-то более фундаментального в том, как работает механизм запросов. Воспроизвести:
-- create and populate two tables with unique column names
create table tbl1 (col1 int);
insert tbl1 values (1);
create table tbl2 (col2 int);
insert tbl2 values (2);
-- execute query and subquery
select col1 from tbl1
where col1 in (select col1 from tbl2);
Один только подзапрос возвращает ожидаемую ошибку:
Invalid column name 'col1'.
Но полный запрос возвращает фиктивный результат, не вызывая ошибки.
Что здесь происходит, это официально задокументировано по стандарту Microsoft или SQL-92? Спасибо!
В этом нет ничего недокументированного. Каждая СУБД будет вести себя так. Это стандартный SQL.
«В этом нет ничего недокументированного» - можете ли вы дать ссылку на любую документацию, которая касается моего вопроса?
Подзапрос создает вложенную область для разрешения имен столбцов. Если имя столбца не может быть найдено в самом внутреннем запросе, тогда проверяются внешние запросы, чтобы разрешить имя. Пока найдено однозначное совпадение, т.е. оно не сводится к объединенным таблицам, у которых обе (или несколько) имеют одно и то же имя столбца, двусмысленности или ошибки нет. Лучше всего всегда использовать псевдонимы таблиц значимый для всех ссылок на столбцы. (Представьте, что однажды кто-то изменил / добавил / удалил имя столбца, в результате чего существующие запросы сместили ссылки на другую таблицу. Лучше ошибка.)
Как насчет Раздела 5.4.12 в винтажном стандарте это? (Совет: ищите «вложенный».)
Коррелирует с tbl1. Всегда псевдоним ваших таблиц
Это работает, как ожидалось
create table tbl1 (col1 int);
insert tbl1 values (1);
create table tbl2 (col2 int);
insert tbl2 values (2);
-- execute query and subquery
select col1 from tbl1
where col1 in (select Z.col1 from tbl2 Z);
Я знаю, что это раздражает и недокументировано и кажется ошибкой, но это не так. Если имя вашего столбца соответствует столбцу один из всех допустимых столбцов в области видимости, он использует этот столбец. Вот что здесь происходит. Существуют методы кодирования, которые предотвращают эти ошибки, то есть создание псевдонимов всего.
Я бы не назвал псевдонимы обходным решением. Здесь нет обходного пути - это вполне логично.
Вы можете покопаться в определениях того, как работают коррелированные подзапросы, и, вероятно, найдете ответ, но я бы просто посчитал это усвоенным уроком.
Спасибо, работает да. И было ясно, что именно здесь механизм запросов запутался. Я должен уточнить свой вопрос - задокументировано ли требование псевдонима?
"механизм запросов запутался" - нет, не было. Вот как это работает.
«вот как это работает» - где официально задокументировано?
Вы могли бы покопаться в определениях того, как работают коррелированные подзапросы, и, вероятно, что-то там найдете, но на самом деле я бы не стал беспокоиться. Все совершенно логично и повторяемо.
Ссылка подзапроса на столбец col1 на самом деле относится к внешней таблице:
select col1 from tbl1
where col1 in (select col1 from tbl2);
^^^ this is 'col1' in table 'tbl1'
Это ведет себя так, как ожидалось:
select t1.col1 from tbl1 t1
where t1.col1 in (select t2.col1 from tbl2 t2);
Чтобы избежать неожиданных результатов, всегда используйте псевдонимы для ваших таблиц.
Спасибо - задокументирован ли совет / требование псевдонима?
Извините, я имел в виду, это официально задокументировано? Или псевдоним является обходным решением?
Более 8 лет назад был задан такой же вопрос здесь, и, похоже, ответ все тот же: поведение подзапроса недокументировано, а псевдоним - лучший обходной путь.