मूल प्रश्न यह था कि "मैं किसी क्वेरी को कैसे मानकीकृत करूँ ..."
मुझे यहीं बता दें, कि यह मूल प्रश्न का उत्तर नहीं है । अन्य अच्छे उत्तरों में पहले से ही कुछ प्रदर्शन हैं।
इसके साथ ही, आगे बढ़ें और इस उत्तर को चिह्नित करें, इसे डाउनवोट करें, इसे एक उत्तर के रूप में चिह्नित करें ... जो कुछ भी आप मानते हैं वह सही है।
मार्क ब्रैकेट के उत्तर को उस पसंदीदा उत्तर के लिए देखें जिसे मैंने (और 231 अन्य) ने अपवोट किया था। उनके उत्तर में दिया गया दृष्टिकोण 1) बाइंड चर के प्रभावी उपयोग के लिए अनुमति देता है, और 2) उन विधेय के लिए जो कि व्यर्थ हैं।
चयनित उत्तर
मैं यहां जोल को संबोधित करना चाहता हूं, जोएल स्पोल्स्की के उत्तर में दिया गया दृष्टिकोण है, उत्तर "चयनित" सही उत्तर के रूप में।
जोएल स्पोलस्की का दृष्टिकोण चतुर है। और यह यथोचित रूप से काम करता है, यह "सामान्य" मूल्यों को देखते हुए, पूर्वानुमेय व्यवहार और पूर्वानुमेय प्रदर्शन को प्रदर्शित करने वाला है, और नाल और खाली स्ट्रिंग जैसे मानक किनारे के मामलों के साथ। और यह किसी विशेष अनुप्रयोग के लिए पर्याप्त हो सकता है।
लेकिन इस दृष्टिकोण को सामान्य बनाने के संदर्भ में, आइए अधिक अस्पष्ट कोने वाले मामलों पर भी विचार करें, जैसे कि जब Name
कॉलम में वाइल्डकार्ड वर्ण होता है (जैसा कि LIKE द्वारा मान्यता प्राप्त है।) वाइल्डकार्ड वर्ण जो मुझे सबसे अधिक उपयोग में आता है %
(एक प्रतिशत संकेत है)। तो चलो अब यहाँ से निपटते हैं, और बाद में अन्य मामलों पर चलते हैं।
% चरित्र के साथ कुछ समस्याएं
के नाम मान पर विचार करें 'pe%ter'
। (यहां उदाहरणों के लिए, मैं कॉलम नाम के स्थान पर शाब्दिक स्ट्रिंग मान का उपयोग करता हूं।) '' pe% ter 'के नाम मान के साथ एक पंक्ति फॉर्म की एक क्वेरी द्वारा लौटा दी जाएगी:
select ...
where '|peanut|butter|' like '%|' + 'pe%ter' + '|%'
लेकिन अगर खोज शब्दों का क्रम उल्टा हो तो वही पंक्ति वापस नहीं होगी :
select ...
where '|butter|peanut|' like '%|' + 'pe%ter' + '|%'
हम जो व्यवहार करते हैं, वह अजीब है। सूची में खोज शब्दों का क्रम बदलने से परिणाम सेट बदल जाता है।
यह लगभग यह कहे बिना चला जाता है कि हम pe%ter
मूंगफली के मक्खन से मेल नहीं खाना चाहते , चाहे वह कितना भी पसंद कर ले।
अस्पष्ट कोने का मामला
(हां, मैं इस बात को मानूंगा कि यह एक अस्पष्ट मामला है। संभवतः एक जिसका परीक्षण होने की संभावना नहीं है। हम एक कॉलम मूल्य में वाइल्डकार्ड की उम्मीद नहीं करेंगे। हम मान सकते हैं कि एप्लिकेशन ऐसे मूल्य को संग्रहीत होने से रोकता है। लेकिन मेरे अनुभव में, मैंने शायद ही कभी एक डेटाबेस बाधा देखी है जो विशेष रूप से वर्ण या पैटर्न को अस्वीकार कर दिया था जिसे एक LIKE
तुलना ऑपरेटर के दाईं ओर वाइल्डकार्ड माना जाएगा ।
छेद करना
इस छेद को पैच करने का एक तरीका %
वाइल्डकार्ड चरित्र से बचना है । (ऑपरेटर पर एस्केप क्लॉज से परिचित किसी के लिए भी, यहां SQL सर्वर प्रलेखन का लिंक नहीं है ।
select ...
where '|peanut|butter|'
like '%|' + 'pe\%ter' + '|%' escape '\'
अब हम शाब्दिक% का मिलान कर सकते हैं। बेशक, जब हमारे पास एक कॉलम नाम होता है, तो हमें वाइल्डकार्ड से गतिशील रूप से बचने की आवश्यकता होती है। हम REPLACE
फ़ंक्शन का उपयोग %
वर्ण की घटनाओं को खोजने और प्रत्येक के सामने एक बैकस्लैश चरित्र डालने के लिए कर सकते हैं , जैसे:
select ...
where '|pe%ter|'
like '%|' + REPLACE( 'pe%ter' ,'%','\%') + '|%' escape '\'
ताकि% वाइल्डकार्ड के साथ समस्या हल हो जाए। लगभग।
पलायन बच गया
हम मानते हैं कि हमारे समाधान ने एक और समस्या पेश की है। भागने का पात्र। हम देखते हैं कि हमें भागने वाले चरित्र की किसी भी घटना से बचने की आवश्यकता है। इस समय, हम का उपयोग करें! बच चरित्र के रूप में:
select ...
where '|pe%t!r|'
like '%|' + REPLACE(REPLACE( 'pe%t!r' ,'!','!!'),'%','!%') + '|%' escape '!'
अंडरस्कोर भी
अब जब हम एक रोल पर हैं, तो हम REPLACE
अंडरस्कोर वाइल्डकार्ड को एक और हैंडल जोड़ सकते हैं । और सिर्फ मनोरंजन के लिए, इस बार, हम बच चरित्र के रूप में $ का उपयोग करेंगे।
select ...
where '|p_%t!r|'
like '%|' + REPLACE(REPLACE(REPLACE( 'p_%t!r' ,'$','$$'),'%','$%'),'_','$_') + '|%' escape '$'
मैं इस दृष्टिकोण को बचने के लिए पसंद करता हूं क्योंकि यह ओरेकल और MySQL के साथ-साथ SQL सर्वर में भी काम करता है। (मैं आमतौर पर भागने के चरित्र के रूप में \ backslash का उपयोग करता हूं, क्योंकि यह चरित्र है जिसे हम नियमित अभिव्यक्तियों में उपयोग करते हैं। लेकिन सम्मेलन द्वारा विवश क्यों किया जाए!
उन pesky कोष्ठक
SQL सर्वर वाइल्डकार्ड वर्णों को कोष्ठक में संलग्न करके शाब्दिक के रूप में माना जाता है []
। इसलिए हमने अभी तक फिक्सिंग नहीं की है, कम से कम SQL सर्वर के लिए। चूंकि कोष्ठक के जोड़ों का विशेष अर्थ है, इसलिए हमें इनसे भी बचना होगा। यदि हम कोष्ठक से ठीक से बचने का प्रबंधन करते हैं, तो कम से कम हमें कोष्ठक के भीतर हाइफ़न -
और कैरेट से परेशान नहीं होना पड़ेगा ^
। और हम किसी भी छोड़ सकते हैं %
और _
पात्रों के अंदर कोष्ठक बच गए, हम मूल रूप से कोष्ठक की विशेष अर्थ को निष्क्रिय कर दिया जाएगा के बाद से।
कोष्ठक के मिलान जोड़े ढूँढना उतना कठिन नहीं होना चाहिए। यह सिंगलटन% और _ की घटनाओं को संभालने की तुलना में थोड़ा अधिक कठिन है। (ध्यान दें कि यह केवल कोष्ठक की सभी घटनाओं से बचने के लिए पर्याप्त नहीं है, क्योंकि एक सिंगलटन ब्रैकेट को शाब्दिक माना जाता है, और इससे बचने की आवश्यकता नहीं है। तर्क थोड़ा फजीर हो रहा है क्योंकि मैं अधिक परीक्षण मामलों को चलाने के बिना संभाल सकता हूं। ।)
इनलाइन अभिव्यक्ति गड़बड़ हो जाती है
SQL में इनलाइन अभिव्यक्ति लंबे और बदसूरत हो रही है। हम शायद इसे काम कर सकते हैं, लेकिन स्वर्ग उस गरीब आत्मा की मदद करता है जो पीछे आती है और उसे समझाना पड़ता है। एक प्रशंसक के रूप में मैं इनलाइन अभिव्यक्तियों के लिए बहुत कुछ कर रहा हूं, मैं यहां एक का उपयोग नहीं कर रहा हूं, मुख्य रूप से क्योंकि मैं एक टिप्पणी नहीं छोड़ना चाहता हूं जो गंदगी का कारण बताता है, और इसके लिए माफी माँगता हूं।
एक समारोह कहाँ?
ठीक है, इसलिए, यदि हम एसक्यूएल में इनलाइन अभिव्यक्ति के रूप में नहीं संभालते हैं, तो हमारे पास निकटतम विकल्प उपयोगकर्ता परिभाषित फ़ंक्शन है। और हम जानते हैं कि चीजों को गति नहीं दी जाएगी (जब तक कि हम उस पर एक सूचकांक को परिभाषित नहीं कर सकते हैं, जैसे कि हम ओरेकल के साथ कर सकते हैं।) यदि हमें एक फ़ंक्शन बनाने के लिए मिला है, तो हम बेहतर हो सकता है कि कोड में जो एसक्यूएल कहता है। बयान।
और उस फ़ंक्शन के व्यवहार में कुछ अंतर हो सकते हैं, जो डीबीएमएस और संस्करण पर निर्भर हैं। (आप सभी जावा डेवलपर्स के लिए एक चिल्लाओ ताकि किसी भी डेटाबेस इंजन का उपयोग करने में सक्षम होने के लिए उत्सुक हो।)
डोमेन की जानकारी
हमारे पास कॉलम के लिए डोमेन का विशेष ज्ञान हो सकता है, (यह है कि कॉलम के लिए लागू स्वीकार्य मूल्यों का सेट। हम एक प्राथमिकता जान सकते हैं कि कॉलम में संग्रहीत मूल्यों में कभी भी प्रतिशत चिह्न, अंडरस्कोर, या ब्रैकेट नहीं होगा। जोड़े। उस मामले में, हम सिर्फ एक त्वरित टिप्पणी शामिल करते हैं कि उन मामलों को कवर किया गया है।
कॉलम में संग्रहीत मान% या _ वर्णों के लिए अनुमति दे सकते हैं, लेकिन एक बाधा को उन मूल्यों से बचने की आवश्यकता हो सकती है, शायद एक परिभाषित चरित्र का उपयोग करके, जैसे कि मानों की तुलना "सुरक्षित" है। फिर, मूल्यों के अनुमत सेट के बारे में एक त्वरित टिप्पणी, और विशेष रूप से किस चरित्र का उपयोग एक भागने चरित्र के रूप में किया जाता है, और जोएल स्पोल्स्की के दृष्टिकोण के साथ चलते हैं।
लेकिन, विशेष ज्ञान और गारंटी के अभाव में, कम से कम उन अस्पष्ट कोने के मामलों को संभालने पर विचार करना हमारे लिए महत्वपूर्ण है, और विचार करें कि क्या व्यवहार उचित है और "विनिर्देश के अनुसार" है।
अन्य मुद्दों पर पुनरावृत्ति हुई
मेरा मानना है कि दूसरों ने पहले से ही चिंता के अन्य क्षेत्रों में से कुछ को पर्याप्त रूप से इंगित किया है:
SQL इंजेक्शन (उपयोगकर्ता की आपूर्ति की गई जानकारी के लिए जो दिखाई देगा, और जिसमें बाइंड चर के माध्यम से आपूर्ति करने के बजाय SQL पाठ में शामिल है। बाइंड चर का उपयोग करना आवश्यक नहीं है, यह SQL इंजेक्शन के साथ विफल करने के लिए सिर्फ एक सुविधाजनक तरीका है। अन्य हैं। इससे निपटने के तरीके:
इंडेक्स स्कैन की बजाय इंडेक्स स्कैन का उपयोग करके ऑप्टिमाइज़र योजना, वाइल्डकार्ड से बचने के लिए एक अभिव्यक्ति या फ़ंक्शन के लिए संभावित आवश्यकता (संभव इंडेक्स या फ़ंक्शन पर इंडेक्स)
बाइंड चर के स्थान पर शाब्दिक मूल्यों का उपयोग स्केलेबिलिटी को प्रभावित करता है
निष्कर्ष
मुझे जोएल स्पोल्स्की का दृष्टिकोण पसंद है। यह चतुर है। और यह काम करता है।
लेकिन जैसे ही मैंने इसे देखा, मैंने तुरंत इसके साथ एक संभावित समस्या देखी, और इसे स्लाइड करने की मेरी प्रकृति नहीं है। मेरा मतलब दूसरों के प्रयासों के प्रति आलोचनात्मक होना नहीं है। मुझे पता है कि कई डेवलपर्स अपने काम को बहुत व्यक्तिगत रूप से लेते हैं, क्योंकि वे इसमें बहुत निवेश करते हैं और वे इसके बारे में बहुत परवाह करते हैं। तो कृपया समझें, यह व्यक्तिगत हमला नहीं है। मैं यहां जो पहचान कर रहा हूं, वह उस प्रकार की समस्या है, जो परीक्षण के बजाय उत्पादन में लगी रहती है।
हां, मैं मूल प्रश्न से बहुत दूर चला गया हूं। लेकिन एक प्रश्न के लिए "चयनित" उत्तर के साथ एक महत्वपूर्ण मुद्दा होने के संबंध में मैं इस नोट को कहां छोड़ता हूं?