मेरे अच्छे दोस्त आरोन बर्ट्रेंड ने मुझे यह लेख लिखने के लिए प्रेरित किया। उन्होंने मुझे याद दिलाया कि कैसे कभी-कभी हम चीजों को हल्के में लेते हैं जब वे हमें स्पष्ट लगते हैं और हमेशा उनके पीछे की पूरी कहानी की जाँच करने की जहमत नहीं उठाते। टी-एसक्यूएल की प्रासंगिकता यह है कि कभी-कभी हम मानते हैं कि हम कुछ टी-एसक्यूएल सुविधाओं के बारे में जानने के लिए सबकुछ जानते हैं, और यह देखने के लिए हमेशा दस्तावेज़ीकरण की जांच करने से परेशान नहीं होते हैं कि उनमें और भी कुछ है या नहीं। इस लेख में मैं कई टी-एसक्यूएल सुविधाओं को कवर करता हूं जिन्हें या तो अक्सर पूरी तरह से अनदेखा कर दिया जाता है, या जो पैरामीटर या क्षमताओं का समर्थन करते हैं जिन्हें अक्सर अनदेखा किया जाता है। यदि आपके पास अपने स्वयं के टी-एसक्यूएल रत्नों के उदाहरण हैं जिन्हें अक्सर अनदेखा कर दिया जाता है, तो कृपया उन्हें इस लेख के टिप्पणी अनुभाग में साझा करें।
इससे पहले कि आप इस लेख को पढ़ना शुरू करें, अपने आप से पूछें कि आप निम्नलिखित T-SQL सुविधाओं के बारे में क्या जानते हैं:EOMONTH, TRANSLATE, TRIM, CONCAT और CONCAT_WS, LOG, कर्सर चर, और OUTPUT के साथ MERGE।
अपने उदाहरणों में मैं TSQLV5 नामक एक नमूना डेटाबेस का उपयोग करूँगा। आप इस डेटाबेस को बनाने और भरने वाली स्क्रिप्ट यहां और इसके ईआर आरेख यहां पा सकते हैं।
EOMONTH का दूसरा पैरामीटर है
EOMONTH फ़ंक्शन को SQL Server 2012 में पेश किया गया था। बहुत से लोग सोचते हैं कि यह इनपुट तिथि रखने वाले केवल एक पैरामीटर का समर्थन करता है, और यह केवल महीने के अंत की तारीख देता है जो इनपुट तिथि से मेल खाती है।
पिछले महीने के अंत की गणना करने के लिए थोड़ी अधिक परिष्कृत आवश्यकता पर विचार करें। उदाहरण के लिए, मान लें कि आपको Sales.Orders तालिका और पिछले महीने के अंत में दिए गए आदेशों को वापस करने की आवश्यकता है।
इसे प्राप्त करने का एक तरीका यह है कि EOMONTH फ़ंक्शन को SYSDATETIME पर लागू किया जाए ताकि चालू माह की महीने की समाप्ति तिथि प्राप्त की जा सके, और फिर परिणाम से एक महीने को घटाने के लिए DATEADD फ़ंक्शन को लागू किया जाए, जैसे:
TSQLV5 का उपयोग करें; ऑर्डरिड चुनें, ऑर्डरडेट से बिक्री। ऑर्डर जहां ऑर्डरडेट =ईओमोन्थ (डेटैड (महीना, -1, SYSDATETIME ()));
ध्यान दें कि यदि आप वास्तव में इस क्वेरी को TSQLV5 नमूना डेटाबेस में चलाते हैं, तो आपको एक खाली परिणाम मिलेगा क्योंकि तालिका में दर्ज की गई अंतिम ऑर्डर तिथि 6 मई, 2019 है। हालाँकि, यदि तालिका में ऑर्डर दिनांक के साथ ऑर्डर होता है, जो अंतिम तिथि पर आता है। पिछले महीने के दिन, क्वेरी ने उन्हें वापस कर दिया होगा।
बहुत से लोगों को यह एहसास नहीं है कि EOMONTH दूसरे पैरामीटर का समर्थन करता है जहां आप इंगित करते हैं कि कितने महीने जोड़ना या घटाना है। यहाँ फ़ंक्शन का [पूरी तरह से प्रलेखित] सिंटैक्स है:
EOMONTH ( start_date [,month_to_add ] )
फ़ंक्शन के दूसरे पैरामीटर के रूप में केवल -1 को निर्दिष्ट करके हमारे कार्य को अधिक आसानी से और स्वाभाविक रूप से प्राप्त किया जा सकता है, जैसे:
ऑर्डरिड चुनें, ऑर्डरडेट से बिक्री।ऑर्डर जहां ऑर्डरडेट =ईओमोन्थ (SYSDATETIME (), -1);
अनुवाद कभी-कभी REPLACE से आसान होता है
बहुत से लोग REPLACE फ़ंक्शन से परिचित हैं और यह कैसे काम करता है। आप इसका उपयोग तब करते हैं जब आप एक इनपुट स्ट्रिंग में एक सबस्ट्रिंग की सभी घटनाओं को दूसरे के साथ बदलना चाहते हैं। कभी-कभी, हालांकि, जब आपके पास कई प्रतिस्थापन होते हैं जिन्हें आपको लागू करने की आवश्यकता होती है, तो REPLACE का उपयोग करना थोड़ा मुश्किल होता है और परिणामस्वरूप जटिल अभिव्यक्तियाँ होती हैं।
एक उदाहरण के रूप में, मान लीजिए कि आपको एक इनपुट स्ट्रिंग @s दी गई है जिसमें स्पैनिश स्वरूपण के साथ एक संख्या है। स्पेन में वे हजारों के समूहों के लिए विभाजक के रूप में एक अवधि का उपयोग करते हैं, और दशमलव विभाजक के रूप में अल्पविराम का उपयोग करते हैं। आपको इनपुट को यूएस फ़ॉर्मेटिंग में बदलने की आवश्यकता है, जहां एक अल्पविराम का उपयोग हजारों के समूहों के लिए विभाजक के रूप में और एक अवधि को दशमलव विभाजक के रूप में किया जाता है।
REPLACE फ़ंक्शन के लिए एक कॉल का उपयोग करके, आप केवल एक वर्ण की सभी घटनाओं को बदल सकते हैं या दूसरे के साथ सबस्ट्रिंग कर सकते हैं। दो प्रतिस्थापन (अवधि से अल्पविराम और अल्पविराम से अवधि तक) लागू करने के लिए आपको फ़ंक्शन कॉल को नेस्ट करना होगा। मुश्किल हिस्सा यह है कि यदि आप अवधि को अल्पविराम में बदलने के लिए एक बार REPLACE का उपयोग करते हैं, और फिर परिणाम के विरुद्ध दूसरी बार अल्पविराम को अवधियों में बदलने के लिए, तो आप केवल अवधियों के साथ समाप्त होते हैं। इसे आज़माएं:
DECLARE @s AS VARCHAR(20) ='123.456.789,00'; जगह चुनें (प्रतिस्थापन(@s, '।', ','), ',', '।');
आपको निम्न आउटपुट मिलता है:
123.456.789.00
यदि आप REPLACE फ़ंक्शन का उपयोग करते रहना चाहते हैं, तो आपको तीन फ़ंक्शन कॉल की आवश्यकता होगी। पीरियड्स को एक ऐसे न्यूट्रल कैरेक्टर से बदलने के लिए जिसे आप जानते हैं जो सामान्य रूप से डेटा (जैसे, ~) में दिखाई नहीं दे सकता है। सभी अल्पविरामों को अवधियों से बदलने के परिणाम के विरुद्ध एक और। परिणाम के खिलाफ एक और अस्थायी चरित्र की सभी घटनाओं को बदलने के लिए (~ हमारे उदाहरण में) अल्पविराम के साथ। ये रहा पूरा एक्सप्रेशन:
DECLARE @s AS VARCHAR(20) ='123.456.789,00'; Select REPLACE(REPLACE(REPLACE(@s, '.', '~'), ',', '.'), '~ ', ',');
इस बार आपको सही आउटपुट मिलता है:
123,456,789.00
यह एक तरह से करने योग्य है, लेकिन इसके परिणामस्वरूप एक लंबी और जटिल अभिव्यक्ति होती है। क्या होगा यदि आपके पास आवेदन करने के लिए और प्रतिस्थापन हों?
बहुत से लोग इस बात से अवगत नहीं हैं कि SQL सर्वर 2017 ने ट्रांसलेट नामक एक नया फ़ंक्शन पेश किया है जो इस तरह के प्रतिस्थापन को बहुत आसान बनाता है। यहाँ फ़ंक्शन का सिंटैक्स है:
ट्रांसलेट (इनपुटस्ट्रिंग, वर्ण, अनुवाद)
दूसरा इनपुट (अक्षर) अलग-अलग वर्णों की सूची के साथ एक स्ट्रिंग है जिसे आप बदलना चाहते हैं, और तीसरा इनपुट (अनुवाद) एक स्ट्रिंग है जिसमें संबंधित वर्णों की सूची है जिसे आप स्रोत वर्णों को बदलना चाहते हैं। इसका स्वाभाविक रूप से मतलब है कि दूसरे और तीसरे पैरामीटर में वर्णों की संख्या समान होनी चाहिए। फ़ंक्शन के बारे में महत्वपूर्ण बात यह है कि यह प्रत्येक प्रतिस्थापन के लिए अलग-अलग पास नहीं करता है। यदि ऐसा होता है, तो संभावित रूप से उसी बग में परिणाम होता है जैसा कि पहले उदाहरण में मैंने दो कॉलों को REPLACE फ़ंक्शन में उपयोग करके दिखाया था। नतीजतन, हमारे कार्य को संभालना बिना सोचे समझे हो जाता है:
DECLARE @s AS VARCHAR(20) ='123.456.789,00'; Select TRANSLATE(@s, '.,', ',.');
यह कोड वांछित आउटपुट उत्पन्न करता है:
123,456,789.00
यह बहुत साफ है!
TRIM, LTRIM(RTRIM()) से अधिक है
SQL सर्वर 2017 ने TRIM फ़ंक्शन के लिए समर्थन पेश किया। बहुत से लोग, जिनमें मैं भी शामिल था, शुरू में केवल यह मान लेते हैं कि यह एलटीआरआईएम (आरटीआरआईएम (इनपुट)) के लिए एक सरल शॉर्टकट से ज्यादा कुछ नहीं है। हालाँकि, यदि आप दस्तावेज़ीकरण की जाँच करते हैं, तो आप महसूस करते हैं कि यह वास्तव में उससे अधिक शक्तिशाली है।
इससे पहले कि मैं विवरण में जाऊं, निम्नलिखित कार्य पर विचार करें:एक इनपुट स्ट्रिंग @s को देखते हुए, अग्रणी और अनुगामी स्लैश (पीछे और आगे) को हटा दें। उदाहरण के तौर पर, मान लें कि @s में निम्न स्ट्रिंग है:
//\\ आगे और पीछे पीछे (\) और आगे (/) स्लैश \\//को हटा दें
वांछित आउटपुट है:
आगे और पीछे पीछे (\) और आगे (/) स्लैश हटाएं
ध्यान दें कि आउटपुट को अग्रणी और अनुगामी रिक्त स्थान बनाए रखना चाहिए।
यदि आप TRIM की पूर्ण क्षमताओं के बारे में नहीं जानते हैं, तो यहां एक तरीका है जिससे आप कार्य को हल कर सकते हैं:
DECLARE @s AS VARCHAR(100) ='//\\ आगे और पीछे वाले (\) और फॉरवर्ड (/) स्लैश \\//' को हटा दें; सेलेक्ट ट्रांसलेट (ट्रिम (ट्रांसलेट (ट्रिम (ट्रांसलेट (@s, '/', '~')), '\', '^')), '^~', '\/') AS आउटपुटस्ट्रिंग;
समाधान सभी रिक्त स्थान को एक तटस्थ वर्ण (~) के साथ बदलने के लिए ट्रांसलेट का उपयोग करके शुरू होता है और रिक्त स्थान के साथ आगे की स्लैश करता है, फिर परिणाम से अग्रणी और पिछली जगहों को ट्रिम करने के लिए टीआरआईएम का उपयोग करता है। यह कदम अनिवार्य रूप से आगे और पीछे के स्लैश को ट्रिम करता है, अस्थायी रूप से मूल रिक्त स्थान के बजाय ~ का उपयोग करता है। यह रहा इस चरण का परिणाम:
\\~निकालें~अग्रणी~और~पिछला~पिछड़ा~(\)~और~आगे~( )~स्लेश~\\
दूसरा चरण तब सभी रिक्त स्थान को किसी अन्य तटस्थ वर्ण (^) और रिक्त स्थान के साथ पिछड़े स्लैश के साथ बदलने के लिए ट्रांसलेट का उपयोग करता है, फिर परिणाम से अग्रणी और पिछली जगहों को ट्रिम करने के लिए टीआरआईएम का उपयोग करता है। यह चरण अनिवार्य रूप से मध्यवर्ती रिक्त स्थान के बजाय अस्थायी रूप से ^ का उपयोग करते हुए अग्रणी और पिछली स्लैश को ट्रिम करता है। यह रहा इस चरण का परिणाम:
~निकालें~अग्रणी~और~पिछला~पिछड़ा~( )~और~आगे~(^)~स्लैश~
अंतिम चरण में पीछे की ओर स्लैश के साथ रिक्त स्थान को बदलने के लिए ट्रांसलेट का उपयोग किया जाता है, ^ फ़ॉरवर्ड स्लैश के साथ, और ~ रिक्त स्थान के साथ, वांछित आउटपुट उत्पन्न करता है:
आगे और पीछे पीछे (\) और आगे (/) स्लैश हटाएं
एक अभ्यास के रूप में, इस कार्य को पूर्व-SQL सर्वर 2017 संगत समाधान के साथ हल करने का प्रयास करें जहाँ आप TRIM और TRANSLATE का उपयोग नहीं कर सकते।
SQL सर्वर 2017 और इसके बाद के संस्करण पर वापस, यदि आपने दस्तावेज़ीकरण की जाँच करने की जहमत उठाई, तो आपने पाया होगा कि TRIM अधिक परिष्कृत है जो आपने शुरू में सोचा था। यह है फ़ंक्शन का सिंटैक्स:
ट्रिम ([अक्षर से] स्ट्रिंग)
वैकल्पिक से वर्ण भाग आपको एक या अधिक वर्ण निर्दिष्ट करने की अनुमति देता है जिन्हें आप इनपुट स्ट्रिंग की शुरुआत और अंत से ट्रिम करना चाहते हैं। हमारे मामले में, आपको केवल '/\' को इस भाग के रूप में निर्दिष्ट करना है, जैसे:
DECLARE @s AS VARCHAR(100) ='//\\ आगे और पीछे वाले (\) और फॉरवर्ड (/) स्लैश \\//' को हटा दें; आउटपुटस्ट्रिंग के रूप में ट्रिम ('/\' @s से) चुनें;
पिछले समाधान की तुलना में यह काफी महत्वपूर्ण सुधार है!
CONCAT और CONCAT_WS
यदि आप कुछ समय के लिए टी-एसक्यूएल के साथ काम कर रहे हैं, तो आप जानते हैं कि जब आपको स्ट्रिंग्स को जोड़ने की आवश्यकता होती है तो एनयूएलएल से निपटना कितना अजीब होता है। उदाहरण के तौर पर, एचआर में कर्मचारियों के लिए रिकॉर्ड किए गए स्थान डेटा पर विचार करें। कर्मचारी तालिका:
मानव संसाधन से एम्पीड, देश, क्षेत्र, शहर चुनें। कर्मचारी;
यह क्वेरी निम्न आउटपुट उत्पन्न करती है:
एम्पिड कंट्री रीजन सिटी-------------------------------------- -------------1 यूएसए डब्ल्यूए सिएटल2 यूएसए डब्ल्यूए टैकोमा3 यूएसए डब्ल्यूए किर्कलैंड4 यूएसए डब्ल्यूए रेडमंड5 यूके न्यूल लंदन6 यूके न्यूल लंदन7 यूके न्यूल लंदन8 यूएसए डब्ल्यूए सिएटल9 यूके न्यूल लंदन
ध्यान दें कि कुछ कर्मचारियों के लिए क्षेत्र का हिस्सा अप्रासंगिक है और एक अप्रासंगिक क्षेत्र को NULL द्वारा दर्शाया गया है। मान लीजिए कि आपको विभाजक के रूप में अल्पविराम का उपयोग करके स्थान भागों (देश, क्षेत्र और शहर) को जोड़ना होगा, लेकिन NULL क्षेत्रों को अनदेखा करना होगा। जब क्षेत्र प्रासंगिक हो, तो आप चाहते हैं कि परिणाम <coutry>,<region>,<city>
के रूप में हो और जब क्षेत्र अप्रासंगिक हो तो आप चाहते हैं कि परिणाम <country>,<city>
. के रूप में हो . आम तौर पर, किसी चीज़ को NULL के साथ जोड़ना एक NULL परिणाम उत्पन्न करता है। आप CONCAT_NULL_YIELDS_NULL सत्र विकल्प को बंद करके इस व्यवहार को बदल सकते हैं, लेकिन मैं गैर-मानक व्यवहार को सक्षम करने की अनुशंसा नहीं करूंगा।
यदि आप CONCAT और CONCAT_WS फ़ंक्शंस के अस्तित्व के बारे में नहीं जानते हैं, तो आपने खाली स्ट्रिंग के साथ NULL को बदलने के लिए संभवतः ISNULL या COALESCE का उपयोग किया होगा, जैसे:
एम्पिड चुनें, देश + ISNULL(',' + क्षेत्र, '') + ',' + शहर एचआर से स्थान के रूप में। कर्मचारी;
यहाँ इस क्वेरी का आउटपुट दिया गया है:
एम्पिड लोकेशन----------------------------------------------- -------------1 यूएसए, डब्ल्यूए, सिएटल 2 यूएसए, डब्ल्यूए, टैकोमा 3 यूएसए, डब्ल्यूए, किर्कलैंड 4 यूएसए, डब्ल्यूए, रेडमंड 5 यूके, लंदन 6 यूके, लंदन 7 यूके, लंदन 8 यूएसए, डब्ल्यूए, सिएटल 9 यूके, लंदन
SQL सर्वर 2012 ने CONCAT फ़ंक्शन पेश किया। यह फ़ंक्शन वर्ण स्ट्रिंग इनपुट की एक सूची को स्वीकार करता है और उन्हें जोड़ता है, और ऐसा करते समय, यह NULLs को अनदेखा करता है। तो CONCAT का उपयोग करके आप इस तरह समाधान को सरल बना सकते हैं:
चुनें empid, CONCAT(देश, ',' + क्षेत्र, ',', शहर) एचआर से स्थान के रूप में। कर्मचारी;
फिर भी, आपको फ़ंक्शन के इनपुट के हिस्से के रूप में विभाजकों को स्पष्ट रूप से निर्दिष्ट करना होगा। हमारे जीवन को और भी आसान बनाने के लिए, SQL Server 2017 ने CONCAT_WS नामक एक समान फ़ंक्शन की शुरुआत की, जहां आप विभाजक को इंगित करके शुरू करते हैं, उसके बाद आइटम जिन्हें आप जोड़ना चाहते हैं। इस फ़ंक्शन के साथ समाधान को और सरल बनाया गया है:
चुनें empid, CONCAT_WS(',', देश, क्षेत्र, शहर) एचआर से स्थान के रूप में। कर्मचारी;
अगला कदम निश्चित रूप से माइंडरीडिंग है। 1 अप्रैल, 2020 को Microsoft CONCAT_MR जारी करने की योजना बना रहा है। फ़ंक्शन एक खाली इनपुट को स्वीकार करेगा, और स्वचालित रूप से यह पता लगाएगा कि आप अपने दिमाग को पढ़कर किन तत्वों को जोड़ना चाहते हैं। फिर क्वेरी कुछ इस तरह दिखेगी:
एम्पिड चुनें, CONCAT_MR() एचआर से स्थान के रूप में। कर्मचारी;
LOG का दूसरा पैरामीटर है
EOMONTH फ़ंक्शन के समान, बहुत से लोग यह महसूस नहीं करते हैं कि पहले से ही SQL Server 2012 से शुरू होकर, लॉग फ़ंक्शन एक दूसरे पैरामीटर का समर्थन करता है जो आपको लॉगरिदम के आधार को इंगित करने की अनुमति देता है। इससे पहले, टी-एसक्यूएल ने लॉग (इनपुट) फ़ंक्शन का समर्थन किया जो इनपुट के प्राकृतिक लॉगरिदम (आधार के रूप में निरंतर ई का उपयोग करके) और LOG10 (इनपुट) देता है जो आधार के रूप में 10 का उपयोग करता है।
लॉग फ़ंक्शन के दूसरे पैरामीटर के अस्तित्व से अवगत नहीं होने पर, जब लोग लॉग की गणना करना चाहते थेb (एक्स), जहां बी ई और 10 के अलावा अन्य आधार है, उन्होंने अक्सर इसे लंबा रास्ता तय किया। आप निम्न समीकरण पर भरोसा कर सकते हैं:
लॉग <उप>बीउप> (x) =लॉग <उप>एउप> (x)/लॉग<उप>एउप> (बी)उदाहरण के तौर पर, लॉग की गणना करने के लिए2 (8), आप निम्न समीकरण पर भरोसा करते हैं:
लॉग<उप>2उप> (8) =लॉग <उप>ईउप> (8)/लॉग<उप>ईउप> (2)T-SQL में अनुवादित, आप निम्नलिखित गणना लागू करते हैं:
DECLARE @x AS FLOAT =8, @b AS INT =2; सेलेक्ट लॉग(@x) / लॉग(@b);
एक बार जब आप महसूस करते हैं कि लॉग दूसरे पैरामीटर का समर्थन करता है जहां आप आधार को इंगित करते हैं, तो गणना बस बन जाती है:
DECLARE @x AS FLOAT =8, @b AS INT =2; सेलेक्ट लॉग(@x, @b);
कर्सर चर
यदि आप कुछ समय के लिए टी-एसक्यूएल के साथ काम कर रहे हैं, तो संभवतः आपके पास कर्सर के साथ काम करने के बहुत सारे मौके थे। जैसा कि आप जानते हैं, कर्सर के साथ काम करते समय, आप आमतौर पर निम्न चरणों का उपयोग करते हैं:
- कर्सर घोषित करें
- कर्सर खोलें
- कर्सर रिकॉर्ड के माध्यम से पुनरावृति करें
- कर्सर बंद करें
- कर्सर को हटा दें
उदाहरण के तौर पर, मान लीजिए कि आपको अपने उदाहरण में प्रति डेटाबेस कुछ कार्य करने की आवश्यकता है। कर्सर का उपयोग करते हुए, आप सामान्य रूप से निम्न के समान कोड का उपयोग करेंगे:
DECLARE @dbname AS sysname; DECLARE C CURSOR FORWARD_ONLY STATIC READ_ONLY चयन नाम के लिए sys.databases से; ओपन सी; सी से @dbname में अगला प्राप्त करें; जबकि @@FETCH_STATUS =0BEGIN PRINT N'हैंडलिंग डेटाबेस' + QUOTENAME(@dbname) + N'...'; /* ... अपना काम यहाँ करें ... */ C से @dbname में अगला प्राप्त करें;END; क्लोज सी; डीअलोकेट सी;
CLOSE कमांड वर्तमान परिणाम सेट जारी करता है और ताले को मुक्त करता है। DEALLOCATE कमांड एक कर्सर संदर्भ को हटा देता है, और जब अंतिम संदर्भ को हटा दिया जाता है, तो कर्सर वाले डेटा संरचनाओं को मुक्त कर देता है। यदि आप उपरोक्त कोड को दो बार बिना CLOSE और DEALLOCATE कमांड के चलाने का प्रयास करते हैं, तो आपको निम्न त्रुटि मिलेगी:
संदेश 16915, स्तर 16, राज्य 1, पंक्ति 4ए कर्सर जिसका नाम 'सी' है पहले से मौजूद है।संदेश 16905, स्तर 16, राज्य 1, पंक्ति 6कर्सर पहले से ही खुला है।
सुनिश्चित करें कि आप जारी रखने से पहले CLOSE और DEALLOCATE कमांड चलाते हैं।
बहुत से लोगों को यह एहसास नहीं होता है कि जब उन्हें केवल एक बैच में कर्सर के साथ काम करने की आवश्यकता होती है, जो कि सबसे आम मामला है, तो एक नियमित कर्सर का उपयोग करने के बजाय आप कर्सर चर के साथ काम कर सकते हैं। किसी भी चर की तरह, कर्सर चर का दायरा केवल वह बैच होता है जहां इसे घोषित किया गया था। इसका मतलब है कि जैसे ही एक बैच समाप्त होता है, सभी चर समाप्त हो जाते हैं। एक कर्सर चर का उपयोग करते हुए, एक बार बैच समाप्त होने के बाद, SQL सर्वर इसे स्वचालित रूप से बंद कर देता है और हटा देता है, जिससे आपको स्पष्ट रूप से CLOSE और DEALLOCATE कमांड चलाने की आवश्यकता बच जाती है।
इस बार कर्सर वेरिएबल का उपयोग करते हुए संशोधित कोड इस प्रकार है:
DECLARE @dbname AS sysname, @C AS CURSOR; SET @C =CURSOR FORWARD_ONLY STATIC READ_ONLY for SELECT name from sys.databases; ओपन @ सी; फ़ेच नेक्स्ट फ्रॉम @C INTO @dbname; जबकि @@FETCH_STATUS =0BEGIN PRINT N'हैंडलिंग डेटाबेस' + QUOTENAME(@dbname) + N'...'; /* ... अपना काम यहां करें ... */ FETCH NEXT FROM @C INTO @dbname;END;
बेझिझक इसे कई बार निष्पादित करें और ध्यान दें कि इस बार आपको कोई त्रुटि नहीं मिलेगी। यह बिल्कुल साफ है, और यदि आप कर्सर को बंद करना और हटाना भूल गए हैं तो आपको कर्सर संसाधनों को रखने के बारे में चिंता करने की ज़रूरत नहीं है।
आउटपुट के साथ मर्ज करें
SQL सर्वर 2005 में संशोधन कथनों के लिए OUTPUT क्लॉज की स्थापना के बाद से, जब भी आप संशोधित पंक्तियों से डेटा वापस करना चाहते हैं तो यह एक बहुत ही व्यावहारिक उपकरण बन गया है। लोग नियमित रूप से संग्रह, ऑडिटिंग और कई अन्य उपयोग के मामलों जैसे उद्देश्यों के लिए इस सुविधा का उपयोग करते हैं। हालाँकि, इस सुविधा के बारे में एक कष्टप्रद बात यह है कि यदि आप इसे INSERT कथनों के साथ उपयोग करते हैं, तो आपको केवल सम्मिलित पंक्तियों से डेटा वापस करने की अनुमति है, आउटपुट कॉलम को सम्मिलित के साथ उपसर्ग करते हुए . आपके पास स्रोत तालिका के कॉलम तक पहुंच नहीं है, भले ही कभी-कभी आपको लक्ष्य से कॉलम के साथ स्रोत से कॉलम वापस करने की आवश्यकता होती है।
एक उदाहरण के रूप में, टेबल T1 और T2 पर विचार करें, जिसे आप निम्न कोड चलाकर बनाते और पॉप्युलेट करते हैं:
ड्रॉप टेबल अगर मौजूद है dbo.T1, dbo.T2; GO CREATE TABLE dbo.T1(keycol INT NOT NULL Identity PRIMARY KEY, datacol VARCHAR(10) NOT NULL); क्रिएट टेबल dbo.T2 (कीकोल नॉट न्यूल आइडेंटिटी प्राइमरी की, डेटाकॉल वर्चर (10) नॉट न्यूल); INSERT INTO dbo.T1(datacol) VALUES('A'),('B'),('C'),('D'),('E'),('F');
ध्यान दें कि दोनों तालिकाओं में कुंजी उत्पन्न करने के लिए एक पहचान संपत्ति का उपयोग किया जाता है।
मान लीजिए कि आपको कुछ पंक्तियों को T1 से T2 तक कॉपी करने की आवश्यकता है; कहते हैं, जहां keycol% 2 =1. आप T2 में नई जेनरेट की गई कुंजियों को वापस करने के लिए OUTPUT क्लॉज का उपयोग करना चाहते हैं, लेकिन आप उन कुंजियों के साथ T1 से संबंधित स्रोत कुंजी भी वापस करना चाहते हैं। निम्नलिखित INSERT कथन का उपयोग करने की सहज अपेक्षा है:
डाबो में डालें।दुर्भाग्य से, जैसा कि उल्लेख किया गया है, OUTPUT क्लॉज आपको स्रोत तालिका से कॉलम को संदर्भित करने की अनुमति नहीं देता है, इसलिए आपको निम्न त्रुटि मिलती है:
Msg 4104, लेवल 16, स्टेट 1, लाइन 2
मल्टी-पार्ट आइडेंटिफ़ायर "T1.keycol" को बाउंड नहीं किया जा सका।बहुत से लोग यह महसूस नहीं करते हैं कि अजीब तरह से यह सीमा MERGE स्टेटमेंट पर लागू नहीं होती है। इसलिए भले ही यह थोड़ा अजीब हो, आप अपने INSERT स्टेटमेंट को MERGE स्टेटमेंट में बदल सकते हैं, लेकिन ऐसा करने के लिए, आपको हमेशा असत्य होने के लिए MERGE विधेय की आवश्यकता होती है। यह WHEN NOT MATCHED क्लॉज को सक्रिय करेगा और वहां केवल समर्थित INSERT कार्रवाई लागू करेगा। आप 1 =2 जैसी नकली झूठी स्थिति का उपयोग कर सकते हैं। यहां पूरा रूपांतरित कोड दिया गया है:
dbo.T2 में TGTUSING के रूप में मर्ज करें (कीकोल चुनें, dbo.T1 से डेटाकॉल जहां कीकॉल% 2 =1) एसआरसी पर 1 =2 जब मेल नहीं खाता है तो INSERT(datacol) VALUES(SRC.datacol)OUTPUT SRC.keycol AS T1_keycol, insert.keycol AS T2_keycol;इस बार कोड सफलतापूर्वक चलता है, निम्न आउटपुट देता है:
T1_keycol T2_keycol ----------- -----------1 13 25 3उम्मीद है, Microsoft अन्य संशोधन कथनों में OUTPUT क्लॉज़ के लिए समर्थन बढ़ाएगा ताकि स्रोत तालिका से भी कॉलम वापस करने की अनुमति मिल सके।
निष्कर्ष
मानो मत, और RTFM! :-)