Неоднозначное имя столбца Ошибка SQL с INNER JOIN: Почему? - PullRequest
7 голосов
/ 11 мая 2011

Следующий код будет работать для выбора данных из двух таблиц:

SELECT t1.foo, t2.bar FROM TABLE1 t1 INNER JOIN TABLE2 t2 ON t1.foo=t2.foo

Я мог бы так же легко написать

SELECT t2.foo, t2.bar FROM TABLE1 t1 INNER JOIN TABLE2 t2 ON t1.foo=t2.foo

t1.foo или t2.foo: шесть из одного или полдюжины из другого. Почему не просто foo?

Мне было интересно, почему SQL-сервер просто не возвращает данные автоматически, если я не указал одну или другую таблицу, поскольку выбор совершенно произвольный (насколько я могу судить).

Я могу составить сценарий, в котором вам нужно будет указать таблицу, например

SELECT t1.foo, t2.bar FROM TABLE1 t1 INNER JOIN TABLE t2 ON t1.foo+=t2.foo

Однако такие сценарии далеки от нормы в моем опыте.

Может ли кто-нибудь объяснить мне, почему язык разработан так, что мне приходится принимать это, казалось бы, произвольное решение в моем коде?

Ответы [ 7 ]

5 голосов
/ 11 мая 2011

Поскольку равенство в MS SQL не обязательно означает, что они равны в значениях, которые вы хотите.Рассмотрим следующие 2 значения для foo: "Bar", "baR".Sql будет считать их равными по отношению к объединению из-за нечувствительности к регистру, присущей при сравнении, но какой из них вы запрашивали?SQL Server не знает и не может догадаться.Вы должны явно указать это.

Редактировать: Как говорилось в @Lukas Eder, не все реализации SQL используют сравнения без учета регистра.Я знаю, что MS SQL использует нечувствительность к регистру, и мой ответ основан на этой концепции.

4 голосов
/ 11 мая 2011

Ваше рассуждение не совсем верно.Хотя t1.foo = t2.foo может быть правдой, это не значит, что они одинаковы.Некоторые примеры:

  • Один может быть VARCHAR(1) другой VARCHAR(2)
  • Один может быть VARCHAR(1) другой NUMBER(1)
  • t1 можетбыть простой таблицей, тогда как t2 является представлением (или вложенным выбором), которое выполняет сверхсложные вычисления для значения foo.Стоимость проекции либо foo может не совпадать в некоторых СУБД.

И существуют десятки других причин, почему было бы неоднозначно просто написать foo

3 голосов
/ 11 мая 2011

Если вы уверены, что столбцы представляют собой то же самое, что вы можете объединить с помощью предложения USING.

SELECT foo, t2.bar FROM TABLE1 t1 INNER JOIN TABLE2 t2 USING (foo);

В противном случае нет гарантии, что t1.foo - это то же самое, что t2.foo

1 голос
/ 11 мая 2011

В этом случае у вас есть ВНУТРЕННЕЕ СОЕДИНЕНИЕ, поэтому ясно, что решение является произвольным. Но есть много ситуаций, когда даже если вы присоединяетесь к FOO, 2 не совпадают.

EX: в случае левого соединения ИЛИ если у вас есть что-то вроде ON t1.foo = t2.foo + / - / whater

Движку нужно, чтобы вы знали, откуда взять данные.

0 голосов
/ 11 мая 2011

SQL этого не делает, потому что просто не разрешает неоднозначности.(Но, как вы заметили, они эквивалентны.)

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

0 голосов
/ 11 мая 2011

В этом конкретном случае t1.foo и t2.foo - это одно и то же, но движок для этого не оптимизирован (и это может сбить с толку).Что, если ваше объединение сделало что-то, где они могут не совпадать, как это?

SELECT t2.foo, t2.bar FROM TABLE1 t1 INNER JOIN TABLE2 t2 ON t1.foo<t2.foo

Поскольку мы используем <, foo на t1 и t2 может быть очень разными.Движок не может «угадать» в этом случае.

Просто потому, что ваш опыт «далек от нормы» в вашем опыте, движок должен это учитывать, в противном случае он сделает некоторые типы запросов чрезвычайнотрудно писать.

0 голосов
/ 11 мая 2011

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

...