Selvom denne adfærd er uintuitiv, er den meget veldefineret i Microsofts Knowledge Base:
KB #298674 :PRB:Underforespørgsel løser navne på kolonne til ydre tabeller
Fra den artikel:
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)
Folk har klaget over dette problem i årevis, men Microsoft vil ikke løse det. Det overholder trods alt standarden, som i det væsentlige siger:
Flere oplysninger i de følgende Connect-"bugs" sammen med flere officielle bekræftelser på, at denne adfærd er ved design og ikke vil ændre sig (så du bliver nødt til at ændre din - dvs. brug altid aliaser ):
Forbind #338468:CTE-kolonnenavnopløsning i underforespørgsel er ikke valideret
Connect #735178 :T-SQL-underforespørgsel virker ikke i nogle tilfælde, når IN-operator bruges
Forbind #302281 :Ikke-eksisterende kolonne får underforespørgsel til at blive ignoreret
Forbind #772612 :Aliasfejl bliver ikke rapporteret inden for en IN-operatør
Forbind #265772 :Fejl ved hjælp af sub vælg
I dit tilfælde vil denne "fejl" sandsynligvis være meget mindre tilbøjelig til at opstå, hvis du bruger mere meningsfulde navne end ID, OID og PID. Gør Order.PID
peg på Person.id
eller Person.PID
? Design dine tabeller, så folk kan finde ud af relationerne uden at skulle spørge dig. Et PersonID
skal altid være et PersonID
, uanset hvor i skemaet det er; det samme med et OrderID
. Det er ikke en god pris at gemme et par skrivetegn for et fuldstændigt tvetydigt skema.
Du kan skrive en EXISTS
klausul i stedet:
... 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?
);