यह एक ऐसा मुद्दा है जिसे मैंने अतीत में शोध करने में घंटों बिताए हैं। यह मुझे ऐसा लगता है जो आधुनिक आरडीबीएमएस समाधानों द्वारा संबोधित किया जाना चाहिए था, लेकिन अभी तक मुझे ऐसा कुछ भी नहीं मिला है जो वास्तव में मुझे किसी भी वेब या विंडोज एप्लिकेशन में डेटाबेस बैक-एंड के साथ एक अविश्वसनीय रूप से सामान्य आवश्यकता के रूप में संबोधित करता हो।
मैं डायनेमिक सॉर्टिंग की बात करता हूं। मेरी काल्पनिक दुनिया में, यह कुछ के समान सरल होना चाहिए:
ORDER BY @sortCol1, @sortCol2
यह नौसिखिया उदाहरण है जो पूरे इंटरनेट पर मंचों पर नौसिखिया एसक्यूएल और संग्रहित प्रक्रिया डेवलपर्स द्वारा दिया गया है । "यह क्यों संभव नहीं है?" वे पूछते हैं। वास्तव में, कोई व्यक्ति अंततः उन्हें संग्रहीत प्रक्रियाओं की संकलित प्रकृति, सामान्य रूप से निष्पादन योजनाओं और सभी अन्य प्रकार के अन्य कारणों के बारे में व्याख्यान देने के लिए आता है, जो एक पैरामीटर को सीधे एक ORDER BY
खंड में रखना संभव नहीं है ।
मुझे पता है कि आप में से कुछ पहले से ही क्या सोच रहे हैं: "ग्राहक को छंटाई करने दें, फिर।" स्वाभाविक रूप से, यह आपके डेटाबेस से काम को बंद कर देता है। हालांकि हमारे मामले में, हमारे डेटाबेस सर्वर भी 99% समय के पसीने को नहीं तोड़ रहे हैं और वे अभी भी मल्टी-कोर नहीं हैं या सिस्टम आर्किटेक्चर में हर 6 महीने में होने वाले अन्य असंख्य सुधारों में से एक हैं। अकेले इस कारण से, हमारे डेटाबेस को छांटने में समस्या नहीं होगी। इसके अतिरिक्त, डेटाबेस बहुत हैंछँटाई में अच्छा। वे इसके लिए अनुकूलित हैं और इसे सही करने के लिए वर्षों से हैं, इसे करने के लिए भाषा अविश्वसनीय रूप से लचीली, सहज और सरल है और सभी किसी भी शुरुआती SQL लेखक को पता है कि यह कैसे करना है और इससे भी अधिक महत्वपूर्ण बात यह है कि वे इसे संपादित करना जानते हैं, परिवर्तन करें, रखरखाव करें, आदि। जब आपके डेटाबेस पर कर लगने से दूर हैं और आप बस (और छोटा!) विकास समय चाहते हैं तो यह एक स्पष्ट विकल्प लगता है।
फिर वेब मुद्दा है। मैंने जावास्क्रिप्ट के साथ चारों ओर खेला है जो HTML तालिकाओं के क्लाइंट-साइड सॉर्टिंग करेगा, लेकिन वे अनिवार्य रूप से मेरी आवश्यकताओं के लिए पर्याप्त रूप से लचीले नहीं हैं और फिर से, चूंकि मेरे डेटाबेस पर अत्यधिक कर नहीं हैं और वास्तव में वास्तव में आसानी से छँटाई कर सकते हैं, मैं एक मुश्किल समय को फिर से लिखने या रोल-माय-खुद के जावास्क्रिप्ट सॉर्टर में लगने वाले समय को उचित ठहराना होगा। वही आम तौर पर सर्वर-साइड सॉर्टिंग के लिए जाता है, हालांकि यह पहले से ही जावास्क्रिप्ट पर बहुत पसंद किया जाता है। मैं ऐसा नहीं हूं जो विशेष रूप से डेटासेट के ओवरहेड को पसंद करता हूं, इसलिए मुझे मुकदमा करो।
लेकिन यह इस बिंदु को वापस लाता है कि यह संभव नहीं है - या बल्कि, आसानी से नहीं। मैंने पूर्व प्रणालियों के साथ किया है, गतिशील छँटाई करने का एक अविश्वसनीय रूप से हैक तरीका। यह सुंदर नहीं था, न ही सहज, सरल, या लचीला और एक शुरुआती SQL लेखक सेकंड के भीतर खो जाएगा। पहले से ही यह इतना "समाधान" नहीं बल्कि एक "जटिलता" है।
निम्नलिखित उदाहरण किसी भी प्रकार की सर्वोत्तम प्रथाओं या अच्छी कोडिंग शैली या किसी भी चीज़ को उजागर करने के लिए नहीं हैं, और न ही वे टी-एसक्यूएल प्रोग्रामर के रूप में मेरी क्षमताओं का संकेत हैं। वे वही हैं जो मैं कर रहा हूं और मैं पूरी तरह से मानता हूं कि वे भ्रामक, खराब रूप और सिर्फ सादे हैक हैं।
हम एक पूर्णांक मान को एक संग्रहीत प्रक्रिया के पैरामीटर के रूप में पास करते हैं (चलो पैरामीटर को केवल "सॉर्ट" कहते हैं) और उसी से हम अन्य चर का एक गुच्छा निर्धारित करते हैं। उदाहरण के लिए ... मान लें कि क्रमांक 1 है (या डिफ़ॉल्ट):
DECLARE @sortCol1 AS varchar(20)
DECLARE @sortCol2 AS varchar(20)
DECLARE @dir1 AS varchar(20)
DECLARE @dir2 AS varchar(20)
DECLARE @col1 AS varchar(20)
DECLARE @col2 AS varchar(20)
SET @col1 = 'storagedatetime';
SET @col2 = 'vehicleid';
IF @sort = 1 -- Default sort.
BEGIN
SET @sortCol1 = @col1;
SET @dir1 = 'asc';
SET @sortCol2 = @col2;
SET @dir2 = 'asc';
END
ELSE IF @sort = 2 -- Reversed order default sort.
BEGIN
SET @sortCol1 = @col1;
SET @dir1 = 'desc';
SET @sortCol2 = @col2;
SET @dir2 = 'desc';
END
आप पहले से ही देख सकते हैं कि अगर मैंने अन्य कॉलमों को परिभाषित करने के लिए और अधिक @colX चर घोषित किए तो मैं वास्तव में "सॉर्ट" के मूल्य के आधार पर सॉर्ट करने के लिए कॉलम के साथ रचनात्मक हो सकता था ... इसका उपयोग करने के लिए, यह आमतौर पर निम्नलिखित की तरह लग रहा है अविश्वसनीय रूप से गड़बड़ क्लॉज:
ORDER BY
CASE @dir1
WHEN 'desc' THEN
CASE @sortCol1
WHEN @col1 THEN [storagedatetime]
WHEN @col2 THEN [vehicleid]
END
END DESC,
CASE @dir1
WHEN 'asc' THEN
CASE @sortCol1
WHEN @col1 THEN [storagedatetime]
WHEN @col2 THEN [vehicleid]
END
END,
CASE @dir2
WHEN 'desc' THEN
CASE @sortCol2
WHEN @col1 THEN [storagedatetime]
WHEN @col2 THEN [vehicleid]
END
END DESC,
CASE @dir2
WHEN 'asc' THEN
CASE @sortCol2
WHEN @col1 THEN [storagedatetime]
WHEN @col2 THEN [vehicleid]
END
END
जाहिर है यह बहुत ही नीचे का उदाहरण है। असली सामान, चूँकि हमारे पास आमतौर पर छाँटने के लिए चार या पाँच स्तंभ होते हैं, प्रत्येक संभव माध्यमिक या यहाँ तक कि इसके अलावा क्रमबद्ध करने के लिए एक तीसरा स्तंभ होता है (उदाहरण के लिए अवरोह के बाद फिर आरोही नाम से दूसरा क्रमबद्ध) और प्रत्येक सहायक द्वि-। दिशात्मक छंटाई जो प्रभावी रूप से मामलों की संख्या को दोगुना करती है। हाँ ... यह बहुत जल्दी बालों वाली हो जाती है।
विचार यह है कि कोई व्यक्ति "आसानी से" सॉर्ट मामलों को बदल सकता है जैसे कि वाहन चालक को स्टोरेजटाइम से पहले सॉर्ट किया जाता है ... लेकिन छद्म-लचीलेपन, कम से कम इस सरल उदाहरण में, वास्तव में समाप्त होता है। अनिवार्य रूप से, प्रत्येक मामला जो एक परीक्षण में विफल रहता है (क्योंकि हमारी सॉर्ट विधि इस बार उस पर लागू नहीं होती है) एक पूर्ण मान प्रदान करता है। और इस प्रकार आप एक क्लॉज के साथ समाप्त होते हैं जो निम्नलिखित की तरह कार्य करता है:
ORDER BY NULL DESC, NULL, [storagedatetime] DESC, blah blah
तुम्हें नया तरीका मिल गया है। यह काम करता है क्योंकि SQL सर्वर प्रभावी रूप से खंडों द्वारा शून्य मानों की उपेक्षा करता है। यह बनाए रखने के लिए अविश्वसनीय रूप से कठिन है, क्योंकि SQL के किसी भी बुनियादी काम के ज्ञान के साथ कोई भी शायद देख सकता है। अगर मैंने आप में से किसी को खो दिया है, तो बुरा मत मानिए। हमें इसे काम करने में लंबा समय लगा और हम अभी भी इसे संपादित करने या इसके जैसे नए बनाने की कोशिश में भ्रमित हैं। शुक्र है कि इसे अक्सर बदलने की आवश्यकता नहीं है, अन्यथा यह जल्दी से "मुसीबत के लायक नहीं" बन जाएगा।
अभी तक यह किया था काम।
मेरा सवाल तब है: क्या कोई बेहतर तरीका है?
मैं संग्रहीत प्रक्रिया वाले लोगों के अलावा अन्य समाधानों के साथ ठीक हूं, क्योंकि मुझे एहसास है कि यह सिर्फ जाने का तरीका नहीं हो सकता है। अधिमानतः, मैं यह जानना चाहूंगा कि क्या कोई इसे संग्रहीत प्रक्रिया के भीतर बेहतर कर सकता है, लेकिन यदि नहीं, तो आप कैसे सभी को ASP.NET के साथ उपयोगकर्ता को डेटा की डायनेमिक रूप से सॉर्ट टेबल (द्वि-प्रत्यक्ष, बहुत) की सुविधा देते हैं?
और इतने लंबे प्रश्न को पढ़ने (या कम से कम स्किमिंग) के लिए धन्यवाद!
पुनश्च: मुझे खुशी है कि मैंने एक संग्रहीत प्रक्रिया का अपना उदाहरण नहीं दिखाया जो डायनेमिक सॉर्टिंग, डायनेमिक फ़िल्टरिंग / कॉलम की खोज-खोज का समर्थन करता है, ROWNUMBER () के माध्यम से पृष्ठांकन, और प्रयास करें ... त्रुटियों पर लेन-देन रोलबैकिंग के साथ पकड़ ... "behemoth- आकार" भी उन्हें वर्णन करने के लिए शुरू नहीं करता है।
अपडेट करें:
- मैं डायनेमिक SQL से बचना चाहूंगा । एक स्ट्रिंग को एक साथ पार्स करना और उस पर एक EXEC चलाना पहली जगह में एक संग्रहीत प्रक्रिया होने के उद्देश्य को बहुत कुछ हरा देता है। कभी-कभी मुझे आश्चर्य होता है कि अगर ऐसा काम करने का विवेक इसके लायक नहीं होगा, तो कम से कम इन विशेष गतिशील छंटाई के मामलों में। फिर भी, मैं हमेशा गंदे महसूस करता हूं जब भी मैं इस तरह से गतिशील SQL स्ट्रिंग्स करता हूं - जैसे मैं अभी भी क्लासिक एएसपी दुनिया में रह रहा हूं।
- सुरक्षा के लिए पहली जगह में संग्रहीत प्रक्रियाओं के बहुत सारे कारण हम चाहते हैं । मुझे सुरक्षा चिंताओं पर कॉल करने के लिए नहीं मिलता है, केवल समाधान सुझाते हैं। SQL सर्वर 2005 के साथ हम अलग-अलग संग्रहीत प्रक्रियाओं पर स्कीमा स्तर पर अनुमतियाँ सेट कर सकते हैं (यदि आवश्यकता हो तो प्रति-उपयोगकर्ता के आधार पर) और फिर सीधे तालिकाओं के विरुद्ध किसी भी प्रश्न को अस्वीकार कर सकते हैं। इस दृष्टिकोण के पेशेवरों और विपक्षों की आलोचना शायद एक और सवाल के लिए है, लेकिन फिर से यह मेरा निर्णय नहीं है। मैं सिर्फ लीड कोड बंदर हूं। :)