Това поведение, макар и неинтуитивно, е много добре дефинирано в базата знания на Microsoft:
KB #298674:PRB:Подзаявка преобразува имена на колони към външни таблици
От тази статия:
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)
SELECT ColA FROM X1 WHERE ColA in (Select X2.ColB FROM X2)
Хората се оплакват от този проблем от години, но Microsoft няма да го поправи. В края на краищата той отговаря на стандарта, който по същество гласи:
Повече информация в следните "бъгове" на Connect заедно с множество официални потвърждения, че това поведение е проектирано и няма да се промени (така че ще трябва да промените своя - т.е. винаги използвайте псевдоними ):
Свързване #338468:Резолюцията на име на колона CTE в подзаявка не е валидирана
Connect #735178 :T-SQL подзаявката не работи в някои случаи, когато се използва оператор IN
Connect #302281 :Несъществуваща колона кара подзаявката да бъде игнорирана
Connect #772612 :Грешка с псевдоним не се съобщава, когато сте в оператор IN
Connect #265772:Грешка при използване на sub изберете
Във вашия случай тази "грешка" вероятно ще бъде много по-малка, ако използвате по-смислени имена от ID, OID и PID. Прави Order.PID
посочете Person.id
или Person.PID
? Проектирайте таблиците си така, че хората да могат да разберат връзките, без да се налага да ви питат. PersonID
винаги трябва да бъде PersonID
, без значение къде в схемата е; същото с OrderID
. Спестяването на няколко знака от въвеждане не е добра цена за напълно двусмислена схема.
Можете да напишете EXISTS
клауза вместо това:
... FROM dbo.Person AS p WHERE EXISTS
(
SELECT 1 FROM dbo.[Order] AS o
WHERE o.PID = p.id -- or is it PID? See why it pays to be explicit?
);