यह व्यवहार, सहज ज्ञान युक्त होते हुए भी, 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 इसे ठीक करने वाला नहीं है। आखिरकार, यह मानक का अनुपालन कर रहा है, जिसमें अनिवार्य रूप से कहा गया है:
निम्नलिखित में अधिक जानकारी "बग" को कई आधिकारिक पुष्टियों के साथ कनेक्ट करें कि यह व्यवहार डिज़ाइन द्वारा है और बदलने वाला नहीं है (इसलिए आपको अपना बदलना होगा - यानी हमेशा उपनाम का उपयोग करें ):
कनेक्ट #338468 :उप क्वेरी में सीटीई कॉलम नाम समाधान मान्य नहीं है
कनेक्ट #735178 :टी-एसक्यूएल सबक्वेरी कुछ मामलों में काम नहीं कर रहा है जब IN ऑपरेटर इस्तेमाल किया जाता है
कनेक्ट #302281 :गैर-मौजूद कॉलम सबक्वेरी को अनदेखा कर देता है
कनेक्ट #772612 :आईएन ऑपरेटर के भीतर होने पर उपनाम त्रुटि की सूचना नहीं दी जा रही है
Connect #265772 :उप का उपयोग कर बग चुनें
आपके मामले में, यदि आप आईडी, ओआईडी और पीआईडी से अधिक सार्थक नामों का उपयोग करते हैं, तो यह "त्रुटि" होने की संभावना बहुत कम होगी। क्या 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?
);