Временная таблица SQL не выбрасывает неверное имя столбца Ошибка, когда это должно - PullRequest
2 голосов
/ 16 августа 2011

Я обнаружил следующую проблему в SQL Server 2008 Management Studio.Когда я запускаю следующий скрипт целиком, я ожидаю ошибки (из-за «ошибки копирования и вставки»), но не получаю их.

IF OBJECT_ID('Foo') IS NOT NULL
BEGIN
    DROP TABLE Foo
END
IF OBJECT_ID('Bar') IS NOT NULL
BEGIN
    DROP TABLE Bar
END
CREATE TABLE Foo (
    FooID int
)
Create Table Bar (
    BarID int
,   FooID int
)
INSERT INTO Foo
SELECT 1 UNION ALL SELECT 2
INSERT INTO Bar
SELECT 1,1 UNION ALL SELECT 2,1 UNION ALL SELECT 3,1
GO

IF OBJECT_ID('tempdb..#temp') IS NOT NULL
BEGIN
      DROP TABLE #TEMP
END
GO
CREATE TABLE #TEMP (
    FooID int
)
INSERT INTO #TEMP
    SELECT FooID FROM Bar
GO
SELECT * FROM Foo WHERE FooID IN (SELECT FooID FROM #TEMP)
GO
SELECT * FROM Bar WHERE BarID IN (SELECT BarID FROM #TEMP)
GO
SELECT * FROM #TEMP
GO

Второй последний оператор, содержащий фильтр предложения where дляSELECT BarID FROM #TEMP ", но в #TEMP нет столбца BarID.При запуске сценария в целом я не получаю ошибки, и сценарий возвращает все строки в Foo.Однако когда я запускаю команду самостоятельно, я получаю сообщение об ошибке, сообщающее, что в # TEMP нет BarId.

Есть ли причина для этого?Это мой код?

Ответы [ 2 ]

4 голосов
/ 16 августа 2011

Ваш второй запрос на самом деле работает правильно.

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

SELECT * FROM Bar x WHERE x.BarID IN (SELECT x.BarID FROM #TEMP)

Для каждой строки в #TEMP вложенный выбор фактически возвращает текущее значение BarID из таблицы Bar, поэтому да, BarID в (BarID) имеет значение true, поэтому каждая строка в Bar совпадает, поэтому каждая строка возвращается.

Чтобы показать, что вы не сумасшедший, попробуйте

SELECT * FROM Bar WHERE BarID IN (SELECT NonExistentFieldName FROM #TEMP) 

Это поднимает ошибку, я думаю, вы ожидаете.

0 голосов
/ 16 августа 2011

Дополнительную информацию об ответе Нила см. В следующей статье базы знаний:

http://support.microsoft.com/kb/298674

Пример, который они используют (это работает, хотя кажется, что это не должно) очень похож на ваш пример (хотя и без таблиц #temp):

CREATE TABLE X1 (ColA INT, ColB INT)
CREATE TABLE X2 (ColC INT, ColD INT)
SELECT ColA FROM X1 WHERE ColA IN (Select ColB FROM X2)

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

Это на самом деле соответствует стандарту ANSI для разрешения столбцов и не изменится (если они не реализуют SET STRICT_CHECKS ON Эрланда ).

Некоторые другие, кто жаловался на эту ошибку (и намного больше информации о том, почему движок должен работать таким образом):

http://connect.microsoft.com/SQL/feedback/details/542289/

http://connect.microsoft.com/SQL/feedback/details/422252/

http://connect.microsoft.com/SQL/feedback/details/126785/

Приходится соглашаться с комментарием @ BalamBalam: почему вы пишете неверный код, а затем жалуетесь, что он ошибочно принят как действительный?

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