यह क्वेरी क्यों काम करती है?


37

मेरे पास दो टेबल हैं, table_a (id, name) और table_b (id), आइए Oracle 12c पर कहते हैं।

यह क्वेरी अपवाद क्यों नहीं लौटाती है?

select * from table_a where name in (select name from table_b);

मैं जो समझता हूं, ओरेकल इसे देखता है

select * from table_a where name = name;

लेकिन जो मुझे नहीं मिलता वह क्यों है?

जवाबों:


61

यदि स्तंभ table_bनहीं है, तो क्वेरी वाक्यात्मक रूप से सही SQL है name। कारण गुंजाइश संकल्प है।

जब क्वेरी पार्स की जाती है, तो पहले यह चेक किया जाता है कि क्या table_bएक nameकॉलम है। चूंकि यह नहीं है, तो table_aजाँच की जाती है। यह केवल एक त्रुटि फेंकेगा यदि तालिकाओं में से कोई एक nameस्तंभ न हो।

अंत में क्वेरी को इस प्रकार निष्पादित किया जाता है:

select a.* 
from table_a  a
where a.name in (select a.name 
                 from table_b  b
                );

परिणामों के अनुसार क्वेरी प्रत्येक पंक्ति के लिए table_a, सबक्वेरी (select name from table_b)- या (select a.name from table_b b)- एक तालिका होगी जिसमें एक ही a.nameमान वाला एक स्तंभ होगा और जितनी पंक्तियाँ होंगी table_b। इसलिए, यदि table_b1 या अधिक पंक्तियाँ हैं, तो क्वेरी निम्नानुसार चलती है:

select a.* 
from table_a  a
where a.name in (a.name, a.name, ..., a.name) ;

या:

select a.* 
from table_a  a
where a.name = a.name ;

या:

select a.* 
from table_a  a
where a.name is not null ;

यदि table_bखाली है, तो क्वेरी कोई पंक्तियाँ नहीं लौटाएगी (उस संभावना की ओर संकेत करने के लिए @ thhaix)।


वह (यह तथ्य कि आपको कोई त्रुटि नहीं मिलती है) संभवतः सबसे अच्छा कारण है कि सभी स्तंभ संदर्भों को तालिका नाम / उपनाम के साथ उपसर्ग किया जाना चाहिए। यदि प्रश्न था:

select a.* from table_a where a.name in (select b.name from table_b); 

आपको सीधे त्रुटि मिली होगी। जब तालिका उपसर्गों को छोड़ दिया जाता है, तो ऐसी गलतियों के लिए मुश्किल नहीं है, विशेष रूप से अधिक जटिल प्रश्नों में, और इससे भी अधिक महत्वपूर्ण है, किसी का ध्यान नहीं जाना।

Oracle डॉक्स में भी पढ़ें : Static SQL स्टेटमेंट में नामों का रिज़ॉल्यूशन इनर कैप्चर में समान उदाहरण B-6 और SELECT और DML स्टेटमेंट पैराग्राफ में इनर कैप्चर इनर कैप्चरिंग में अनुशंसाएँ :

उपयुक्त तालिका उपनाम के साथ बयान में प्रत्येक कॉलम संदर्भ को योग्य बनाएं।


आपने SQL इंजन की आंतरिक कार्यप्रणाली को इतनी सटीकता से कैसे विच्छेदित किया?
रिंकीपिंकू

8

इसलिये

ऑरेकल एक सहसंबद्ध सबक्वेरी का प्रदर्शन करता है जब एक नेस्टेड सबक्वेरी एक टेबल से एक कॉलम को संदर्भित करता है जो कि उप-डेरी से एक स्तर ऊपर एक पैरेंट स्टेटमेंट को संदर्भित करता है। http://docs.oracle.com/cd/E11882_01/server.112/e41084/queries007.htm#SQLRF52357

इसका मतलब यह निर्धारित करने के लिए है कि क्या उपसमुच्चय सहसंबद्ध है ओरेकल को बाहरी विवरण संदर्भ सहित उपकुंजी में नामों को हल करने का प्रयास करना चाहिए । और उपसर्ग के लिए nameयह एकमात्र संकल्प संभव है।


4

ऐसा कोई nameक्षेत्र नहीं है table_bजिससे कि Oracle में से कोई एक लेता हो table_a। मैंने कोशिश की, EXPLAIN PLANलेकिन इसने मुझे केवल यही दिया कि एक है TABLE ACCESS FULL। मुझे लगता है कि यह दोनों तालिकाओं के बीच किसी प्रकार का कार्टेशियन उत्पाद उत्पन्न करेगा जिसके परिणामस्वरूप सभी नामों की सूची table_aउप-क्वेरी द्वारा वापस आ जाएगी।


5
"Table_b में कोई नाम फ़ील्ड नहीं है, इसलिए Oracle table_a से एक लेता है।" सही बात। "मुझे लगता है कि यह किसी प्रकार का कार्टेशियन उत्पाद उत्पन्न करेगा।" गलत। क्वेरी है from table_a where ...। यह table_aउन सभी पंक्तियों को लौटा देगा, जिन्हें छोड़कर nameयह अशक्त है।
ypercube y

1
TABLE ACCESS FULLओरेकल का यह बताने का तरीका है कि आप अनुक्रमिक स्कैन कर रहे हैं।
जोशी बोडियो

1
आपका पीएलए अप्रासंगिक है - बड़ी तालिकाओं के साथ अच्छी तरह से अनुक्रमण हो सकता है - मैं मान रहा हूं कि आपका परीक्षण डेटा पर चल रहा है?
18
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.