2011-03-09 15 views
5

मुझे लगता है कि मैंने हमेशा यह माना है कि SQL क्वेरी के चयन भाग में स्केलर फ़ंक्शंस केवल उन पंक्तियों पर लागू होंगे जो खंड के सभी मानदंडों को पूरा करते हैं।SQL स्टेटमेंट निष्पादित करते समय फ़िल्टरिंग से पहले स्केलर फ़ंक्शन लागू किए जा सकते हैं?

आज मैं एक विक्रेता से कुछ कोड डीबग कर रहा था और उस धारणा को चुनौती दी गई थी। इस कोड के असफल होने का एकमात्र कारण यह है कि सबस्ट्रिंग() फ़ंक्शन को डेटा पर कॉल किया जा रहा है जिसे WHERE क्लॉज द्वारा फ़िल्टर किया जाना चाहिए था। लेकिन ऐसा प्रतीत होता है कि फ़िल्टरिंग होने से पहले सबस्ट्रिंग कॉल लागू किया जा रहा है, क्वेरी विफल हो रही है। मेरा मतलब यह है कि मेरा क्या मतलब है। आइए मान लें कि हमारे पास दो टेबल हैं, प्रत्येक में 2 कॉलम हैं और क्रमश: 2 पंक्तियां और 1 पंक्ति हैं। प्रत्येक में पहला कॉलम सिर्फ एक आईडी है। NAME सिर्फ एक स्ट्रिंग है, और NAME_LENGTH हमें बताता है कि उसी आईडी वाले नाम में कितने अक्षर हैं। ध्यान दें कि LONG_NAMES तालिका में केवल एक से अधिक वर्ण वाले नामों की एक समान पंक्ति है।

NAMES: ID, NAME 
    1, "Peter" 
    2, "X" 
LONG_NAMES: ID, NAME_LENGTH 
    1, 5 

मैं एक प्रश्न काट पिछले 3 पत्र के साथ प्रत्येक नाम मुद्रित करने के लिए चाहते हैं, मैं पहली बार कुछ इस तरह (अब के लिए एसक्यूएल सर्वर वाक्य रचना कल्पना करते हुए) की कोशिश कर सकते:

SELECT substring(NAME,1,len(NAME)-3) 
    FROM NAMES; 

मैं जल्द ही होगा पता लगाएं कि यह मुझे एक त्रुटि देगा, क्योंकि जब यह "एक्स" तक पहुंच जाता है तो यह सबस्ट्रिंग कॉल में नकारात्मक संख्या का उपयोग करने का प्रयास करेगा, और यह असफल हो जाएगा। जिस तरह से मेरे विक्रेता ने इसे हल करने का फैसला किया, वह पंक्तियों को फ़िल्टर करके था, जहां काम करने के लिए लेन-3 क्वेरी के लिए स्ट्रिंग बहुत कम थीं। उन्होंने कहा कि एक और मेज पर शामिल होने से यह किया:

SELECT substring(NAMES.NAME,1,len(NAMES.NAME)-3) 
    FROM NAMES 
     INNER JOIN LONG_NAMES 
      ON NAMES.ID = LONG_NAMES.ID; 

पहली नज़र में, जैसे कि यह काम हो सकता है कि इस प्रश्न के लग रहा है। शामिल स्थिति किसी भी पंक्तियों को खत्म कर देगी जिनके पास NAME फ़ील्ड सबस्ट्रिंग कॉल विफल होने के लिए पर्याप्त छोटा है।

हालांकि, मैं क्या देख सकते हैं से, एसक्यूएल सर्वर कभी कभी तालिका में सब कुछ के लिए स्ट्रिंग अभिव्यक्ति की गणना करने की कोशिश करेंगे, और तो पंक्तियों को फ़िल्टर करने में शामिल होने के लागू होते हैं। क्या यह इस तरह से होना चाहिए? क्या ऑपरेशन का एक दस्तावेज क्रम है जहां कुछ चीजें होने पर मुझे पता चल सकता है? क्या यह एक विशेष डेटाबेस इंजन या एसक्यूएल मानक के हिस्से के लिए विशिष्ट है? यदि मैंने छोटे नामों को फ़िल्टर करने के लिए मेरी NAMES तालिका पर कुछ अनुमान लगाने का निर्णय लिया है, (जैसे लेन (NAME)> 3), क्या SQL सर्वर भी सबस्ट्रिंग को लागू करने का प्रयास करने के बाद लागू करना चुन सकता है? यदि ऐसा है तो ऐसा लगता है कि एक सबस्ट्रिंग करने का एकमात्र सुरक्षित तरीका इसे चुनने में "केस कब" में लपेटना होगा?

+4

हाँ। ऐसा करने का एकमात्र सुरक्षित तरीका 'केस' है। इस विषय पर एक अच्छे उत्तर के लिए http://stackoverflow.com/questions/5191701/tsql-divide-by-zero-encountered-despite-no-columns-containing-0/5203211#5203211 देखें। लिंक के लिए –

+0

@ मार्टिन धन्यवाद। मैं यह नहीं समझ सका कि इस तरह के प्रश्नों को कैसे खोजा जाए क्योंकि यह एक तरह का सार है। –

उत्तर

0

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

2

मार्टिन ने यह लिंक दिया जो काफी कुछ बता रहा है कि क्या हो रहा है - क्वेरी ऑप्टिमाइज़र के पास चीजों को फिर से व्यवस्थित करने के लिए मुफ्त रीइन है। मैं इसे एक उत्तर के रूप में शामिल कर रहा हूं ताकि मैं कुछ स्वीकार कर सकूं। मार्टिन, यदि आप इसमें अपने लिंक के साथ एक उत्तर बनाते हैं तो मैं खुशी से स्वीकार करूंगा कि इसके बजाय।

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

TSQL divide by zero encountered despite no columns containing 0

संपादित करें: के रूप में अधिक प्रतिक्रिया में आ गए हैं, मैं फिर से उलझन में हूँ। यह अभी तक स्पष्ट प्रतीत नहीं होता है जब बिल्कुल अनुकूलक को चयनित खंड में चीजों का मूल्यांकन करने की अनुमति दी जाती है। मुझे लगता है मुझे एसक्यूएल मानक खुद को जाना होगा और देखें कि क्या मैं इसका एहसास कर सकता हूं।

+0

एसक्यूएल मानकों के अनुरूप एक डीबीएमएस * चीजों को पुन: व्यवस्थित करने के लिए कुछ * स्वतंत्रता है, लेकिन इसमें चीजों को फिर से व्यवस्थित करने के लिए मुफ्त रीन नहीं है। अभी भी एक ही अपरिवर्तित, क्रूर बल, चरण-दर-चरण, क्वेरी के पेंसिल-और-पेपर मूल्यांकन के समान परिणाम उत्पन्न करने की आवश्यकता है। और इस मामले में, मुझे पूरा यकीन है कि इसका मतलब है कि इसे कार्य करना होगा जैसे कि चयन अनुभाग का मूल्यांकन करने से पहले WHERE क्लॉज का मूल्यांकन किया जाए। (यहां मेरे संदर्भ के साथ कहीं भी संदर्भ देखें।) –

+1

@Catcall - यह पहले माइक्रोसॉफ्ट कनेक्ट साइट में उठाया गया है। Https://connect.microsoft.com/SQLServer/feedback/details/537419/sql-server-should-not-raise-illogical-errors –

+0

मुझे लगता है कि मैंने कहा होगा कि "यह चीजों को पुन: व्यवस्थित करने के लिए मुफ्त रीइन है यह तब तक पसंद करता है जब तक कि यह अभी भी एक ही परिणाम के बिना एक अपरिवर्तित, क्रूर बल, चरण-दर-चरण, पेंसिल-और-पेपर मूल्यांकन के समान परिणाम उत्पन्न करता है "। –

1

जो सेल्को, जिन्होंने प्रारंभिक एसक्यूएल मानकों को लिखने में मदद की, ने विभिन्न यूएसनेट समाचार समूहों में इस तरह के कई बार पोस्ट किया है। (मैं उन खंडों पर जा रहा हूं जो आपके चयन कथन पर लागू नहीं होते हैं।) उन्होंने आमतौर पर कुछ ऐसा कहा जैसे "इस तरह के कथनों को कार्य करने की तरह कार्य करना चाहिए"। दूसरे शब्दों में, एसक्यूएल कार्यान्वयनों को वास्तव में व्यवहार करना चाहिए जैसे कि इन चरणों में से प्रत्येक को वास्तव में करने के लिए इन चरणों को किया गया था।

  1. बिल्ड में तालिका कंस्ट्रक्टर्स सब की तरफ से एक काम कर तालिका FROM खंड।
  2. उन पंक्तियों की कार्य तालिका से निकालें जो WHERE खंड को संतुष्ट नहीं करते हैं।
  3. में अभिव्यक्तियों का निर्माण कार्य तालिका के विरुद्ध चयन खंड।

तो, इसके बाद, कोई एसक्यूएल डीबीएमएस कार्य नहीं करना चाहिए जैसे कि चयन अनुभाग में कार्यों का मूल्यांकन करने से पहले यह WHERE क्लॉज लागू होता है।

हाल ही में पोस्टिंग में, Joe expands the steps to include CTEs

सीजे तिथि और ह्यूग डार्वेन अनिवार्य रूप से वही बात कहते हैं जो उनकी पुस्तक एसक्यूएल मानक पर एक गाइड के अध्याय 11 ("टेबल अभिव्यक्ति") में एक ही बात है। वे यह भी ध्यान देते हैं कि यह अध्याय SQL मानकों में "क्वेरी विशिष्टता" खंड (खंड?) से मेल खाता है।

+0

क्या क्लॉज या एक अलग चरण का हिस्सा माना जाता है? –

+0

मैंने जो सामान पढ़ा, उसमें जॉइन क्लॉज को "खंड से तालिका निर्माणकर्ता" में से एक माना जाता था। –