Запрос столбцов, которые не существуют, не завершается ошибкой - PullRequest
3 голосов
/ 27 марта 2012

Странная ситуация.

Если у меня есть эти таблицы:

CREATE TABLE t1 (id INT, title VARCHAR(20), someIntCol INT)
GO
CREATE TABLE t2 (id INT, t1Id INT, someData VARCHAR(20))
GO

и делай:

SELECT    t1.* 
FROM    t1 
WHERE    t1.id IN (SELECT someIntCol FROM t2)

странная вещь: парсер не возражает против того, что столбец someIntCol не существует

странная вещь: если я изменю someIntCol на someIntCol2, я получу «Неверное имя столбца 'someIntCol2'». ошибка

Может кто-нибудь объяснить это?

К вашему сведению, это не мой код. Я получил это от этой ссылки

Ответы [ 4 ]

6 голосов
/ 27 марта 2012

Попробуйте:

SELECT    t1.* 
FROM    t1 
WHERE    t1.id IN (SELECT t2.someIntCol FROM t2)

Теперь при выполнении выдается исключение.

Поскольку someIntCol существует в t1, он использует этот элемент данных из основного запроса.

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

SELECT [TableName].[ColumnName]

Это также предотвратит неоднозначность, если у вас есть 2 столбца с одинаковыми именами в t1 и t2


Вот MSDN, который может дать вам лучшее понимание того, как работают подзапросы:

http://msdn.microsoft.com/en-us/library/aa213262(v=sql.80).aspx

4 голосов
/ 27 марта 2012

В SQL Server шаг синтаксического анализа только семантически проверяет синтаксис для таких вещей, как неэкранированные столбцы, начинающиеся с цифр, например [2ndColumn] и не 2ndColumn (что не сможет выполнить синтаксический анализ), ключевые слова и тому подобное, и гарантирует, что запрос может быть разобрано . Это процесс, который происходит, когда вы нажимаете кнопку разбора в SSMS. Этот процесс не проверяет запрос на соответствие базовым данным.

Поэтому я могу ввести SELECT abc FROM DEF, хотя у меня нет ни одного столбца с именем abc, и даже нет таблицы с именем DEF.

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

Еще один способ убедиться в этом - указать SQL Server только анализировать и больше ничего не делать:

SET PARSEONLY ON
SELECT abc FROM def
GO

Над запросом будет указано «Команда (и) выполнена успешно».

SET PARSEONLY OFF
SELECT abc FROM def
GO

Над запросом будет указано «Недопустимое имя объекта def».

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

1 голос
/ 27 марта 2012

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

0 голосов
/ 27 марта 2012

Можете ли вы найти, что

SELECT    t1.*  FROM    t1  WHERE    t1.id IN (SELECT someIntCol FROM t2)

В таблице T2 не было столбца "someIntCol".

, поэтому анализатор отображает ошибку

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...