Toto chování, i když je neintuitivní, je velmi dobře definováno ve znalostní bázi Microsoft:
KB #298674 :PRB:Poddotaz řeší názvy sloupců na vnější tabulky
Z toho článku:
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)
Lidé si na tento problém stěžují roky, ale Microsoft to nehodlá opravit. Je to přece v souladu s normou, která v podstatě říká:
Další informace naleznete v následujících „chybách“ Connect spolu s několika oficiálními potvrzeními, že toto chování je záměrné a nezmění se (takže budete muset změnit své – tj. vždy používejte aliasy ):
Připojení #338468 :Rozlišení názvu sloupce CTE v dílčím dotazu není ověřeno
Connect #735178 :Poddotaz T-SQL nefunguje v některých případech, když je použit operátor IN
Připojení #302281 :Neexistující sloupec způsobí, že bude poddotaz ignorován
Connect #772612 :Chyba aliasu není hlášena, když je operátor IN
Připojení #265772 :Chyba při použití sub vybrat
Ve vašem případě bude tato „chyba“ pravděpodobně mnohem méně pravděpodobná, pokud použijete smysluplnější názvy než ID, OID a PID. Má Order.PID
přejděte na Person.id
nebo Person.PID
? Navrhněte své tabulky tak, aby lidé mohli zjistit vztahy, aniž by se vás museli ptát. PersonID
by mělo být vždy PersonID
, bez ohledu na to, kde ve schématu je; totéž s OrderID
. Ušetřit pár znaků psaní není dobrá cena za zcela nejednoznačné schéma.
Můžete napsat EXISTS
místo toho klauzule:
... 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?
);