Dit gedrag, hoewel niet intuïtief, is zeer goed gedefinieerd in de Knowledge Base van Microsoft:
KB #298674:PRB:Subquery lost namen van kolommen op naar buitenste tabellen
Uit dat 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)
Mensen klagen al jaren over dit probleem, maar Microsoft gaat het niet oplossen. Het voldoet tenslotte aan de norm, die in wezen zegt:
Meer informatie vindt u in de volgende Connect "bugs" samen met meerdere officiële bevestigingen dat dit gedrag inherent is aan het ontwerp en niet zal veranderen (dus u zult de uwe moeten veranderen - d.w.z. gebruik altijd aliassen ):
Connect #338468:CTE-kolomnaamomzetting in subquery is niet gevalideerd
Connect #735178:T-SQL-subquery werkt in sommige gevallen niet wanneer IN-operator wordt gebruikt
Connect #302281:niet-bestaande kolom zorgt ervoor dat subquery wordt genegeerd
Connect #772612:Aliasfout wordt niet gerapporteerd binnen een IN-operator
Connect #265772 :Bug met sub selecteer
In uw geval zal deze "fout" waarschijnlijk veel minder snel optreden als u meer betekenisvolle namen gebruikt dan ID, OID en PID. Heeft Order.PID
wijs naar Person.id
of Person.PID
? Ontwerp uw tabellen zodat mensen de relaties kunnen achterhalen zonder dat ze het u hoeven te vragen. Een PersonID
moet altijd een PersonID
zijn , ongeacht waar in het schema het is; hetzelfde met een OrderID
. Het opslaan van een paar typetekens is geen goede prijs om te betalen voor een volledig dubbelzinnig schema.
Je zou een EXISTS
. kunnen schrijven clausule in plaats daarvan:
... 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?
);