Поведение подзапроса TSQL

Я обнаружил, что мой подзапрос не вызывает ошибки, когда должен. документы не указывает на то, что это потенциальная проблема, поэтому я считаю, что мне не хватает чего-то более фундаментального в том, как работает механизм запросов. Воспроизвести:

-- 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'.

Но полный запрос возвращает фиктивный результат, не вызывая ошибки.

Поведение подзапроса TSQL

Что здесь происходит, это официально задокументировано по стандарту Microsoft или SQL-92? Спасибо!

Более 8 лет назад был задан такой же вопрос здесь, и, похоже, ответ все тот же: поведение подзапроса недокументировано, а псевдоним - лучший обходной путь.

user9375338 08.09.2018 07:21

В этом нет ничего недокументированного. Каждая СУБД будет вести себя так. Это стандартный SQL.

Martin Smith 08.09.2018 12:00

«В этом нет ничего недокументированного» - можете ли вы дать ссылку на любую документацию, которая касается моего вопроса?

user9375338 08.09.2018 17:36

Подзапрос создает вложенную область для разрешения имен столбцов. Если имя столбца не может быть найдено в самом внутреннем запросе, тогда проверяются внешние запросы, чтобы разрешить имя. Пока найдено однозначное совпадение, т.е. оно не сводится к объединенным таблицам, у которых обе (или несколько) имеют одно и то же имя столбца, двусмысленности или ошибки нет. Лучше всего всегда использовать псевдонимы таблиц значимый для всех ссылок на столбцы. (Представьте, что однажды кто-то изменил / добавил / удалил имя столбца, в результате чего существующие запросы сместили ссылки на другую таблицу. Лучше ошибка.)

HABO 08.09.2018 18:01

Как насчет Раздела 5.4.12 в винтажном стандарте это? (Совет: ищите «вложенный».)

HABO 08.09.2018 18:11
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
78
2

Ответы 2

Коррелирует с 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);

Я знаю, что это раздражает и недокументировано и кажется ошибкой, но это не так. Если имя вашего столбца соответствует столбцу один из всех допустимых столбцов в области видимости, он использует этот столбец. Вот что здесь происходит. Существуют методы кодирования, которые предотвращают эти ошибки, то есть создание псевдонимов всего.

Я бы не назвал псевдонимы обходным решением. Здесь нет обходного пути - это вполне логично.

Вы можете покопаться в определениях того, как работают коррелированные подзапросы, и, вероятно, найдете ответ, но я бы просто посчитал это усвоенным уроком.

Спасибо, работает да. И было ясно, что именно здесь механизм запросов запутался. Я должен уточнить свой вопрос - задокументировано ли требование псевдонима?

user9375338 08.09.2018 06:22

"механизм запросов запутался" - нет, не было. Вот как это работает.

Mitch Wheat 08.09.2018 06:26

«вот как это работает» - где официально задокументировано?

user9375338 08.09.2018 06:30

Вы могли бы покопаться в определениях того, как работают коррелированные подзапросы, и, вероятно, что-то там найдете, но на самом деле я бы не стал беспокоиться. Все совершенно логично и повторяемо.

Nick.McDermaid 08.09.2018 07:37

Ссылка подзапроса на столбец 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);

Чтобы избежать неожиданных результатов, всегда используйте псевдонимы для ваших таблиц.

Спасибо - задокументирован ли совет / требование псевдонима?

user9375338 08.09.2018 06:25

Извините, я имел в виду, это официально задокументировано? Или псевдоним является обходным решением?

user9375338 08.09.2018 06:31

Другие вопросы по теме