क्यों इस तरह से प्रश्नों को पार किया जाता है जो अधिकांश खंडों में स्तंभ उपनामों के उपयोग को रोकते हैं?


16

क्वेरी लिखने का प्रयास करते समय, मुझे पता चला (कठिन तरीका) कि SQL सर्वर एक क्वेरी निष्पादित करते समय चयनों को पार्स करने से बहुत पहले एक क्वेरी में कहाँ करता है।

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

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

ऐसा लगता है कि यह एक ऐसा चकाचौंध मुद्दा है कि यह तर्क करने के लिए खड़ा है, फिर, यह निर्णय लेने के लिए अन्य कारण हैं कि स्तंभ उपनामों को SELECT और ORDER BY के अलावा किसी अन्य चीज़ में अनुमति नहीं दी जानी चाहिए, लेकिन वे कारण क्या हैं?

जवाबों:


19

सारांश

इसका कोई तार्किक कारण नहीं है, लेकिन यह लाभ छोटा है और कुछ ऐसे नुकसान हैं जो तुरंत स्पष्ट नहीं हो सकते हैं।

शोध का परिणाम

मैंने कुछ शोध किया और कुछ अच्छी जानकारी पाई। 2012-08-09 17:49 GMT पर एक विश्वसनीय प्राथमिक स्रोत (जो गुमनाम रहना चाहता है) से एक प्रत्यक्ष उद्धरण निम्नलिखित है:

जब एसक्यूएल का आविष्कार किया गया था, तो इसका चयन खंड में कोई उपनाम नहीं था। यह एक गंभीर कमी थी जिसे 1986 में ANSI द्वारा भाषा को मानकीकृत किए जाने पर ठीक किया गया था।

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

select name, salary + bonus as pay
from employee
where pay > 100000

हालांकि मुझे लगता है कि यह एक उचित प्रश्न है, कुछ SQL- आधारित सिस्टम कुछ कार्यान्वयन से संबंधित कारणों के लिए उपनाम के उपयोग पर प्रतिबंध लगा सकते हैं। मुझे यह सुनकर आश्चर्य नहीं हुआ कि SQL सर्वर ऐसा करता है।

मैं SQL-86 मानक में और अधिक शोध में दिलचस्पी रखता हूं और आधुनिक DBMSes उर्फ ​​पुन: उपयोग का समर्थन क्यों नहीं करते हैं, लेकिन अभी तक इसके साथ बहुत दूर होने का समय नहीं है। शुरुआत के लिए, मुझे नहीं पता कि दस्तावेज कहां से मिलें या कैसे पता लगाया जाए कि समिति किसने बनाई है। क्या कोई मदद कर सकता है? मैं मूल Sybase उत्पाद के बारे में अधिक जानना चाहूंगा जो SQL सर्वर से आया था।

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

हर जगह उपनाम का उपयोग करने के साथ समस्या

यदि आप सेलेक्ट आइटम को WHERE क्लॉज में रखने की अनुमति देते हैं, तो आप न केवल क्वेरी की जटिलता (और इस तरह एक अच्छा निष्पादन योजना खोजने की जटिलता) को पूरी तरह से अतार्किक सामग्री के साथ आना संभव है। प्रयत्न:

SELECT X + 5 Y FROM MyTable WHERE Y = X

क्या होगा यदि MyTable में पहले से ही एक कॉलम Y है, जिसमें से किसका जिक्र है? समाधान एक सीटीई या एक व्युत्पन्न तालिका का उपयोग करना है, जिसे ज्यादातर मामलों में कोई अतिरिक्त खर्च नहीं करना चाहिए, लेकिन समान अंतिम परिणाम प्राप्त होता है। सीटीई और व्युत्पन्न टेबल कम से कम एक बार केवल एक उपनाम का उपयोग करने की अनुमति देकर अस्पष्टता के संकल्प को लागू करते हैं।

इसके अलावा, FROM क्लॉज में एलियासेस का उपयोग नहीं करना प्रख्यात अर्थ है। आप ऐसा नहीं कर सकते:

SELECT
   T3.ID + (SELECT Min(Interval) FROM Intervals WHERE IntName = 'T') CalcID
FROM
   Table1 T
   INNER JOIN Table2 T2
      ON T2.ID = CalcID
   INNER JOIN Table3 T3
      ON T2.ID = T3.ID

यही कारण है कि एक परिपत्र संदर्भ (इस अर्थ में कि टी 2 गुप्त रूप से टी 3 से एक मूल्य के लिए बात कर रहा है, इससे पहले कि उस तालिका में शामिल हों सूची में प्रस्तुत किया गया है), और है रफ़ू मुश्किल देखने के लिए। इसके बारे में क्या खयाल है:

INSERT dbo.FinalTransaction
SELECT
   newid() FinalTransactionGUID,
   'GUID is: ' + Convert(varchar(50), FinalTransactionGUID) TextGUID,
   T.*
FROM
   dbo.MyTable T

आप कितना शर्त लगाना चाहते हैं कि न्यूड () फ़ंक्शन को निष्पादन योजना में दो बार डाला जा रहा है, पूरी तरह से अप्रत्याशित रूप से दो कॉलम को अलग-अलग मान दिखा रहा है? क्या होगा जब उपरोक्त क्वेरी का उपयोग CTE या व्युत्पन्न तालिकाओं में N स्तर गहरे में किया जाता है। मैं गारंटी देता हूं कि समस्या आपकी कल्पना से भी बदतर है। जब कोई चीज़ केवल एक बार या किसी क्वेरी योजना में किस बिंदु पर आंकी जाती है, इस बारे में पहले से ही गंभीर असंगतता की समस्याएँ हैं, और Microsoft ने कहा है कि यह ठीक नहीं होगाउनमें से कुछ क्योंकि वे क्वेरी बीजगणित को ठीक से व्यक्त कर रहे हैं - यदि कोई अप्रत्याशित परिणाम प्राप्त करता है, तो क्वेरी को भागों में तोड़ दें। जंजीर संदर्भों की अनुमति देना, संभावित रूप से बहुत लंबी श्रृंखलाओं के माध्यम से परिपत्र संदर्भों का पता लगाना - ये काफी मुश्किल समस्याएं हैं। समानता का परिचय दें और आपको बनाने में एक बुरा सपना आया है।

नोट: WHERE या GROUP BY में उपनाम का उपयोग करने से नए () या रैंड () जैसे फ़ंक्शंस के साथ समस्याओं का कोई फर्क नहीं पड़ने वाला है।

पुन: प्रयोज्य अभिव्यक्ति बनाने के लिए एक SQL सर्वर तरीका

CROSS APPLY / OUTER APPLY SQL सर्वर में एक ऐसा तरीका है जो अभिव्यक्ति बनाने के लिए है जिसे क्वेरी में कहीं और इस्तेमाल किया जा सकता है (अभी पहले FROM क्लॉज में नहीं):

SELECT
   X.CalcID
FROM
   Table1 T
   INNER JOIN Table3 T3
      ON T.ID = T3.ID
   CROSS APPLY (
      SELECT
         T3.ID + (SELECT Min(Interval) FROM Intervals WHERE IntName = 'T') CalcID
   ) X
   INNER JOIN Table2 T2
      ON T2.ID = X.CalcID

यह दो काम करता है:

  1. CROSS APPLY में सभी अभिव्यक्तियों को एक "नेमस्पेस" (एक टेबल उपनाम, यहाँ, एक्स) मिलता है और उस नेमस्पेस के भीतर अद्वितीय होना चाहिए।
  2. यह हर जगह स्पष्ट करता है कि न केवल कैल्सीड एक्स से आ रहा है, बल्कि यह भी स्पष्ट करता है कि टेबल टी 1 और टी 3 में शामिल होने पर आप एक्स से कुछ भी उपयोग क्यों नहीं कर सकते, क्योंकि एक्स अभी तक पेश नहीं किया गया है।

मैं वास्तव में CROSS APPLY का काफी शौकीन हूं। यह मेरा वफादार दोस्त बन गया है, और मैं हर समय इसका इस्तेमाल करता हूं। एक आंशिक UNPIVOT (जिसमें देशी वाक्यविन्यास का उपयोग करके PIVOT / UNPIVOT या UNIVIVOT / PIVOT की आवश्यकता होगी) की आवश्यकता है? CROSS APPLY के साथ संपन्न हुआ। एक गणना मूल्य की आवश्यकता है जिसे कई बार पुन: उपयोग किया जाएगा? किया हुआ। लिंक किए गए सर्वर पर कॉल के लिए निष्पादन आदेश को सख्ती से लागू करने की आवश्यकता है? गति में एक चिल्ला सुधार के साथ किया। केवल एक प्रकार की पंक्ति को 2 पंक्तियों या अतिरिक्त स्थितियों के साथ विभाजित करने की आवश्यकता है? किया हुआ।

तो बहुत कम से कम, DBMS SQL Server 2005 और ऊपर में, आपके पास शिकायत का कोई और कारण नहीं है: CROSS APPLY यह है कि आप जिस तरह से चाहते हैं, उसी तरह से आप कैसे सूखी हैं।


14

मैं आपको इसके सटीक कारण नहीं बता सकता, लेकिन मैं आपको बताऊंगा कि दोहराव से बचने के लिए CTE, सबक्वेरी, व्युत्पन्न टेबल आदि का उपयोग करते हुए उदाहरणों को दोहराने के लिए वर्कअराउंड हैं।

यदि आप एक बार-बार अभिव्यक्ति के साथ एक क्वेरी दिखाते हैं, तो हम शायद आपको दिखा सकते हैं कि इसे फिर से कैसे लिखा जाए ताकि अभिव्यक्ति केवल एक बार सूचीबद्ध हो। हालाँकि, यह क्वेरी लिखने / पढ़ने में जटिलता को कम करता है, यह दक्षता के बारे में बहुत कुछ बदलने की संभावना नहीं है। SQL सर्वर आम तौर पर पहचानने के बारे में बहुत अच्छा है कि अभिव्यक्ति दोहराई जाती है, और यह उस काम को दो बार नहीं करेगा। ऐसे अपवाद हैं जो दूसरे तरीके से जाते हैं, लेकिन आपको केवल दक्षता के बारे में चिंतित होना चाहिए जब आप वास्तव में ऐसा होने का निरीक्षण करते हैं। मुझे लगता है कि आपके द्वारा लिखे गए अधिकांश दोहराए गए भावों की योजना में वास्तव में केवल एक ही ऑपरेशन में ढह जाता है।

सभी ने कहा, मैं इस सवाल से अपने जवाब का एक हिस्सा भी दोहराऊंगा:

/dba/19762/why-is-the-select-clause-listed-first


यहाँ जो सेल्को की व्याख्या है कि कैसे एक क्वेरी मानक के अनुसार संसाधित की जाती है (मैंने इसे अपने खुद के aspfaq.com लेख से चुरा लिया है, जो शायद सेल्को द्वारा एक समाचार समूह पोस्ट से उद्धरण चुराया गया है):

यहाँ बताया गया है कि SQL में SELECT कैसे काम करता है ... कम से कम सिद्धांत में। वास्तविक उत्पाद चीजों को तब अनुकूलित करेंगे जब वे कर सकते हैं।

FROM क्लॉज में शुरू करें और सभी जोनों, यूनियनों, चौराहों, और जो भी अन्य टेबल कंस्ट्रक्टर्स हैं, उनमें से एक वर्किंग टेबल बनाएं। AS विकल्प आपको इस वर्किंग टेबल को एक नाम देता है, जिसे आपको बाकी क्वेरी के लिए उपयोग करना होता है।

WHERE क्लॉज पर जाएं और उन पंक्तियों को हटा दें जो मानदंड पास नहीं करते हैं; वह यह है कि, TRUE का परीक्षण न करें (UNKNOWN और FALSE को अस्वीकार करें)। WHROM क्लॉज को FROM क्लॉज में काम करने के लिए लागू किया जाता है।

वैकल्पिक ग्रुप बाय क्लॉज पर जाएं, ग्रुप बनाएं और प्रत्येक ग्रुप को एक सिंगल रो में घटाएं, नए ग्रुपेड टेबल के साथ ऑरिजनल वर्किंग टेबल को रिप्लेस करें। एक समूहीकृत तालिका की पंक्तियों में समूह विशेषताएँ होनी चाहिए: (1) एक समूह स्तंभ (2) समूह के बारे में एक आँकड़ा (यानी कुल कार्य) (3) एक फ़ंक्शन या (4) उन तीन वस्तुओं से बना एक अभिव्यक्ति।

वैकल्पिक HAVING क्लॉज पर जाएं और समूहीकृत वर्किंग टेबल के खिलाफ इसे लागू करें; यदि कोई समूह BY खंड नहीं था, तो पूरी तालिका को एक समूह के रूप में मानें।

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

नेस्टेड क्वेरी एक्सप्रेशंस सामान्य स्कूपिंग नियमों का पालन करते हैं, जो आप सी, पास्कल, अल्गोल आदि जैसे ब्लॉक संरचित भाषा से उम्मीद करेंगे। अंतरतम प्रश्न उन प्रश्नों में कॉलम और तालिकाओं का संदर्भ दे सकते हैं जिनमें वे निहित हैं।

इसका मतलब यह है कि एक SELECT में एक ग्रुप BY से अधिक कॉलम नहीं हो सकते हैं; लेकिन इसमें निश्चित रूप से कम कॉलम हो सकते हैं।

अब, सेल्को मानकों के पुराने संस्करणों में मुख्य योगदानकर्ताओं में से एक था। मुझे नहीं पता कि आप कभी WHY?प्रश्न का निश्चित उत्तर प्राप्त करने जा रहे हैं , केवल अटकलों को छोड़कर। मेरा अनुमान है कि वास्तविक ऑपरेशन को सूचीबद्ध करना सबसे पहले पार्सर के लिए यह जानना बहुत आसान बनाता है कि ऑपरेशन का प्रकार क्या होने जा रहा है। एक 20-तालिका में शामिल होने जा रहा है कि कल्पना कीजिए लग सकती है एक SELECTया UPDATEयाDELETE , और याद रखें कि इन इंजनों के लिए कोड मूल रूप से दिनों में वापस लिखा गया था जब स्ट्रिंग पार्स काफी महंगा था।

ध्यान दें कि यदि SQL मानक FROMपहले आने के लिए निर्धारित है, तो विक्रेताओं ने स्वतंत्र रूप से व्याकरण को एक अलग क्रम में पार्स करने का निर्णय लिया हो सकता है, इसलिए यह अभी भी क्लॉस के आदेश की अपेक्षा करने के लिए समझ में नहीं आता है क्योंकि पूरी तरह से 100% प्रसंस्करण के आदेश का पालन करना चाहिए। समय।

चीजों के लिए भी यही सच है CASEहमने इस साइट पर परिदृश्यों को यहीं देखा है , उदाहरण के लिए, जहां पहले माना गया कि मिथक CASEहमेशा क्रम और शॉर्ट सर्किट में प्रक्रियाएं झूठी होती हैं। और यह अन्य सामान्य मान्यताओं तक फैली हुई है, जैसे कि SQL सर्वर उनके द्वारा लिखे गए क्रम में जुड़ने का मूल्यांकन करता है, बाईं ओर से दाईं ओर छोटी WHEREधाराएं जमा करता है , या CTE को एक बार या एक निश्चित क्रम में संसाधित करता है, भले ही वे कई बार संदर्भित हों। उत्पाद अनुकूलित करने के लिए स्वतंत्र हैं कि वे कैसे फिट देखते हैं भले ही यह प्रतिबिंबित न करें कि आपने यह कैसे कहा है कि घोषित रूप से काम करना चाहिए।


2
यह भी ध्यान दें कि क्वेरी के विभिन्न हिस्सों में उपनामों का उपयोग या उपयोग करने की क्षमता पार्सर द्वारा लागू की जाती है, न कि अनुकूलक या निष्पादन इंजन द्वारा। इंजन वास्तव में क्वेरी को कैसे निष्पादित करता है, यह जरूरी नहीं कि सिंटैक्स को प्रभावित करने वाले प्रतिबंधों को प्रतिबिंबित करता है।
हारून बर्ट्रेंड

2

में इकाई एसक्यूएल , आप कुछ स्थितियों में क्वेरी में अन्य स्थानों में भाव से कल्पित नामों का प्रयोग कर सकते हैं:

select k1, count(t.a), sum(t.a)
from T as t
group by t.b + t.c as k1

ध्यान दें कि यहाँ आप GROUP BYखंड में अभिव्यक्ति का उपयोग करें ताकि इसे खंड में उपयोग किया जा सके SELECT

SQL प्रश्नों में इस तरह के कुछ अन्य प्रकार के पुन: प्रयोज्य-अभिव्यक्ति की अनुमति देना स्पष्ट रूप से संभव है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.