2010-11-18 12 views
39

बयानएक तैयार स्थिति में (शायद) शून्य मानों से कैसे निपटें?

SELECT * FROM tableA WHERE x = ? 

है और पैरामीटर java.sql.PreparedStatement 'stmt'

stmt.setString(1, y); // y may be null 

तो y रिक्त है के माध्यम से डाला जाता है, बयान हर मामले में कोई भी पंक्ति रिटर्न x = null हमेशा होता है क्योंकि झूठा (x IS NULL होना चाहिए)। एक समाधान

SELECT * FROM tableA WHERE x = ? OR (x IS NULL AND ? IS NULL) 

होगा लेकिन फिर मैं एक ही पैरामीटर दो बार सेट करना होगा। क्या कोई बेहतर समाधान है?

धन्यवाद!

वक्तव्य 1:

SELECT * FROM tableA WHERE x is NULL 

वक्तव्य 2:

SELECT * FROM tableA WHERE x = ? 

आप अपने चर की जाँच करें और स्थिति के आधार पर उचित बयान का निर्माण कर सकते

+0

मैं तैयार बयान का उपयोग नहीं करता हूं। मैं एसक्यूएल स्ट्रिंग का उपयोग करता हूं, और फिर मैं एसक्यूएल स्ट्रिंग में 'Is Null' के साथ' = NULL' को प्रतिस्थापित करता हूं। एक जादू की तरह काम करता है। –

+19

यह इंजेक्शन हमलों के लिए सुरक्षित और संभावित रूप से कमजोर नहीं है। – aioobe

उत्तर

29

मैंने हमेशा इसे आपके प्रश्न में दिखाया है। एक ही पैरामीटर को दो बार सेट करना इतनी बड़ी कठिनाई नहीं है, है ना?

select * from mytable where ifnull(mycolumn,'') = ?; 

तो यो कर सकता है::

SELECT * FROM tableA WHERE x = ? OR (x IS NULL AND ? IS NULL); 
+0

धन्यवाद पॉल आपके नोट के लिए। तो आप 'यह सबसे अच्छा अभ्यास' के लिए वोट देते हैं? – Zeemee

+0

मुझे कभी बेहतर तरीका नहीं मिला है। –

+4

प्रदर्शन अलग होने पर दो अलग-अलग एसक्यूएल बेहतर हो सकते हैं, हालांकि, क्योंकि आप चाहते हैं कि एक्सेस पथ अलग-अलग है या नहीं, इस पर निर्भर करता है। – Thilo

5

सिर्फ 2 अलग बयानों का प्रयोग करेंगे। मुझे लगता है कि यह कोड को समझने के लिए बहुत स्पष्ट और आसान बनाता है।

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

+0

धन्यवाद डीसीपी, यह मेरे लिए सीधे आगे दिखता है। लेकिन कल्पना करें कि मेरे कथन में 1 पैरामीटर नहीं है, लेकिन 5. मुझे 5^2 स्टेटमेंट = 25 की आवश्यकता होगी! – Zeemee

+0

तो यह समस्या से बच जाएगी कि यह अभी भी 'IS' के बजाय '=' कहता है? – aioobe

+1

@ डीसीपी, ऐसा लगता है कि आपने अपना जवाब एक चीज़ से कुछ अलग में बदल दिया है। क्यूं कर? –

0

आप उदाहरण mysql के लिए उपयोग करते हैं तो आप शायद की तरह कुछ कर सकता है

stmt.setString(1, foo == null ? "" : foo); 

आप की जाँच करने के लिए होगा आपके देखने के लिए योजना की व्याख्या यह आपके प्रदर्शन में सुधार करता है। हालांकि इसका मतलब यह होगा कि खाली स्ट्रिंग शून्य के बराबर है, इसलिए यह नहीं माना जाता है कि यह आपकी आवश्यकताओं के अनुरूप होगा।

+1

धन्यवाद Knubo, लेकिन मैं यह सुनिश्चित नहीं कर सकता कि खाली तारों को मूल्य के रूप में उपयोग नहीं किया जाता है। – Zeemee

+0

यदि आपको वास्तव में प्रदर्शन की ज़रूरत है, तो आप कुछ मूल्य चुन सकते हैं जो आपको यकीन है कि परीक्षण के लिए कभी भी उपस्थित नहीं होगा। यह एक प्रदर्शन हैक होगा, इसलिए यदि आप कर सकते हैं तो मैं इसे टालना चाहूंगा। (उदाहरण के लिए, यह हो सकता है कि आपके डेटा में कभी भी एक € नहीं हो, ताकि आप इसके बजाय ' – Knubo

8

एक अज्ञात एएनएसआई-एसक्यूएल ऑपरेटर IS DISTINCT FROM है जो नल मानों को संभालता है। इसका उपयोग इस प्रकार किया जा सकता है:

SELECT * FROM tableA WHERE x NOT IS DISTINCT FROM ? 

तो केवल एक पैरामीटर सेट करना होगा। दुर्भाग्य से, यह एमएस एसक्यूएल सर्वर (2008) द्वारा समर्थित नहीं है।

एक अन्य समाधान हो सकता है, अगर वहाँ एक मूल्य है कि है और इस्तेमाल कभी नहीं किया जाएगा ('XXX') है:

SELECT * FROM tableA WHERE COALESCE(x, 'XXX') = COALESCE(?, 'XXX') 
+0

की कोशिश कर सकें। इसे MySQL + PHP PDO के साथ आज़माया और यह कथन तैयार करने का प्रयास करते समय' झूठी 'भी लौटा दी :( – Pere

+1

[से DISTINCT] [https://www.postgresql.org/docs/current/static/functions-comparison.html) PostgreSQL –

+0

के साथ अच्छी तरह से काम करता है ओरेकल के पुराने संस्करणों में, एनवीएल का उपयोग उसी चीज़ के लिए किया जा सकता है, लेकिन यदि उपलब्ध हो तो COALESCE अच्छा है (https://stackoverflow.com/questions/950084/oracle-differences-between-nvl-and-coalesce देखें)। –

0

ओरेकल 11g में, मैं इसे इस तरह करते हैं, क्योंकि x = null तकनीकी रूप से UNKNOWN का मूल्यांकन:

WHERE (x IS NULL AND ? IS NULL) 
    OR NOT LNNVL(x = ?) 

अभिव्यक्ति OR से पहले शून्य के साथ शून्य equating का ख्याल रखता है, तो अभिव्यक्ति के बाद अन्य सभी संभावनाओं का ख्याल रखता है। LNNVLUNKNOWNTRUE है, जो हम क्या चाहते हैं के ठीक विपरीत है, इसलिए NOT है TRUE को, TRUEFALSE करने और FALSE बदल जाता है।

स्वीकार किए गए समाधान कुछ मामलों में ओरेकल में मेरे लिए काम नहीं करते थे, जब यह एक बड़ी अभिव्यक्ति का हिस्सा था, जिसमें NOT शामिल था।

संबंधित मुद्दे