PostgreSQL: "केस-असंवेदनशील" क्वेरी कैसे करें


338

क्या PostgreSQL में केस-असंवेदनशील प्रश्नों को लिखने का कोई तरीका है, उदाहरण के लिए, मैं चाहता हूं कि निम्नलिखित 3 प्रश्न उसी परिणाम को लौटाएं।

SELECT id FROM groups where name='administrator'

SELECT id FROM groups where name='ADMINISTRATOR'

SELECT id FROM groups where name='Administrator'

यदि citext आपके Postgres स्थापना के साथ आता है, तो citext प्रकार का प्रयास करें। यह केस-असंवेदनशील पाठ है
माइकल बुएन

2
इस प्रश्न के नए लोगों के लिए, आधिकारिक डाकघरों के इस लिंक में यहां दिए गए सभी उत्तर हैं, साथ ही कुछ अन्य विकल्प भी हैं।
पार्थियन शॉट

सर ने कृपा करके @Arun द्वारा किए गए जवाब को स्वीकार कर लिया। यह बहुत कम जटिल है और लागू होने के बाद परेशानियों का गुच्छा नहीं खींचता है।
जेलिबोबा

जवाबों:


451

तुलना करने से पहले स्ट्रिंग्स को लोअर केस में बदलने के लिए LOWER फ़ंक्शन का उपयोग करें ।

इसे इस्तेमाल करे:

SELECT id 
  FROM groups
 WHERE LOWER(name)=LOWER('Administrator')

92
यह ध्यान रखना महत्वपूर्ण है कि विधेय स्तंभों पर LOWER (या किसी भी फ़ंक्शन) का उपयोग करते हुए - इस मामले में "नाम" - किसी भी अनुक्रमणिका का कारण नहीं रह जाएगा। यदि यह एक बड़ी या बार-बार की जाने वाली सारणी है, तो इससे परेशानी हो सकती है। केस-असंवेदनशील टकराव, साइटेक्स या एक फ़ंक्शन-आधारित इंडेक्स प्रदर्शन में सुधार करेगा।
जॉर्डन

108
या बस इस तरह एक इंडेक्स बनाएं: इंडेक्स idx_groups_name पर समूहों को कम करें (नाम);
डैनियल

19
यह भी निर्दिष्ट करें varchar_pattern_opsकि क्या आप सूचकांक को LIKE 'xxx%'क्वेरी के साथ काम करना चाहते हैं , अर्थात CREATE INDEX ix_groups_name ON groups (lower(name) varchar_pattern_ops)
Sayap

10
ILIKE ऑपरेटर का उपयोग करना (जैसा कि नीचे दिए गए अन्य उत्तरों में दिखाया गया है) एक सरल दृष्टिकोण है, भले ही यह सबसे अधिक मतदान वाला उत्तर हो।
रयान

5
यहां टिप्पणियों के माध्यम से जा रहे हैं, यहां बहुत सारे सुझाव बताते हैं ILIKE, यह काम करेगा but with slow response,। गणनाओं के परिणामों के आधार पर तालिकाओं तक तेजी से पहुंच प्राप्त करने के लिए, मैं सुझाव देता हूं कि किसी को भी यह जांचना चाहिए कि इसे स्वीकृत उत्तर के साथ जाना चाहिए। और अधिक विवरण यहाँ और यहाँ
अफोलाबी ओलावुवा अकिंवुमी

230

के ILIKEबजाय का उपयोग करLIKE

SELECT id FROM groups WHERE name ILIKE 'Administrator'

1
ध्यान दें कि ILIKEस्प्रिंग बूट में उपयोग किए जाने पर हाइबरनेट द्वारा समर्थित नहीं है।
चींटी

@ इसके साथ org.hibernate.dialect.PostgreSQL94Dialectऔर स्प्रिंग बूट 2.0.6 के साथ काम करता है । कृपया। लेकिन इंटेलीज ने इसकी शिकायत की।
समिथा केवेश

134

सबसे आम तरीका खोज स्ट्रिंग और डेटा को कम या अधिक करना है। लेकिन इसके साथ दो समस्याएं हैं।

  1. यह अंग्रेजी में काम करता है, लेकिन सभी भाषाओं में नहीं। (शायद अधिकांश भाषाओं में भी नहीं।) प्रत्येक लोअरकेस अक्षर में एक समान अपरकेस अक्षर नहीं है; प्रत्येक अपरकेस अक्षर में एक समान लोअरकेस अक्षर नहीं होता है।
  2. निचले () और ऊपरी () जैसे कार्यों का उपयोग करना आपको एक अनुक्रमिक स्कैन देगा। यह अनुक्रमित का उपयोग नहीं कर सकता। मेरी परीक्षण प्रणाली में, एक इंडेक्स का उपयोग करने वाली क्वेरी की तुलना में कम () का उपयोग करने में लगभग 2000 गुना अधिक समय लगता है। (परीक्षण डेटा में 100k से अधिक पंक्तियाँ हैं।)

कम से कम तीन कम अक्सर उपयोग किए जाने वाले समाधान हैं जो अधिक प्रभावी हो सकते हैं।

  1. साइटेक्स मॉड्यूल का उपयोग करें , जो ज्यादातर केस-असंवेदनशील डेटा प्रकार के व्यवहार की नकल करता है। उस मॉड्यूल को लोड करने के बाद, आप एक केस-इन्सेंसिटिव इंडेक्स बना सकते हैं CREATE INDEX ON groups (name::citext);। (लेकिन नीचे देखें।)
  2. केस-असंवेदनशील टकराव का उपयोग करें। यह तब सेट किया जाता है जब आप डेटाबेस को इनिशियलाइज़ करते हैं। केस-असंवेदनशील टकराव का उपयोग करने का मतलब है कि आप ग्राहक कोड से किसी भी प्रारूप के बारे में स्वीकार कर सकते हैं, और आप अभी भी उपयोगी परिणाम वापस करेंगे। (इसका मतलब यह भी है कि आप केस-संवेदी प्रश्न नहीं कर सकते हैं।
  3. एक कार्यात्मक सूचकांक बनाएं। उपयोग करके एक लोअरकेस इंडेक्स बनाएं CREATE INDEX ON groups (LOWER(name));। ऐसा करने के बाद, आप जैसे प्रश्नों के साथ सूचकांक का लाभ उठा सकते हैं SELECT id FROM groups WHERE LOWER(name) = LOWER('ADMINISTRATOR');, या SELECT id FROM groups WHERE LOWER(name) = 'administrator';आपको LOWER () का उपयोग करना याद रखना होगा, हालाँकि।

साइटेक्स मॉड्यूल एक वास्तविक केस-असंवेदनशील डेटा प्रकार प्रदान नहीं करता है। इसके बजाय, यह व्यवहार करता है जैसे कि प्रत्येक स्ट्रिंग को नीचा दिखाया गया था। यही है, यह व्यवहार करता है जैसे कि आपने lower()प्रत्येक स्ट्रिंग पर बुलाया था , जैसा कि ऊपर की संख्या 3 में है। इसका फायदा यह है कि प्रोग्रामर को स्ट्रैंथ को कम करने के लिए याद नहीं रखना पड़ता है। लेकिन आपको साइटेक्स का उपयोग करने का निर्णय लेने से पहले डॉक्स में "स्ट्रिंग तुलनात्मक व्यवहार" और "सीमाएं" अनुभागों को पढ़ना होगा।


1
# 1 के बारे में: यह एक समस्या नहीं होनी चाहिए, क्योंकि यह दो अलग-अलग तार होंगे (ऐसा करने के बारे में सोचें col = 'a'और col = 'b')। # 2 के बारे में: जैसा कि आपने कहा, आप एक अभिव्यक्ति पर एक इंडेक्स बना सकते हैं, इसलिए यह वास्तव में कोई समस्या नहीं है। लेकिन मैं आपसे सहमत हूं कि कोलाज को बदलना सबसे अच्छा समाधान है।
विंसेंट सवार्द

5
क्या कोई मुझे बता सकता है कि पोस्ट-क्रेग बिल्ट-इन कॉलेन्स क्या केस-असंवेदनशील टकराव हैं? मैं इसे एक विकल्प के रूप में देखता हूं, लेकिन नेट पर पोस्टग्रेज के लिए केस-असंवेदनशील टकराव के बारे में कुछ भी नहीं पा सकता हूं?
खोर्वत

1
@ अनूपशाह: नहीं, मैं ऐसा नहीं कह रहा हूं। मैं विंडोज पर PostgreSQL नहीं चला रहा हूं। 9.4 डॉक्स यह कहते हैं : "सभी प्लेटफार्मों पर, डिफ़ॉल्ट, C और POSIX नाम के टकराव उपलब्ध हैं। ऑपरेटिंग सिस्टम समर्थन के आधार पर अतिरिक्त कोलाज उपलब्ध हो सकते हैं।" आप देख सकते हैं कि PostgreSQL के कौन से कॉलेजों के साथ उपलब्ध हैं select * from pg_collation;
माइक शेरिल 'कैट रिकॉल'

1
@ मैथ्यू: यह उस विषय के लिए सबसे अच्छा परिचय (और सावधानी) है जिसके बारे में मुझे पता है: एज केसेस टू कीप इन माइंड। भाग 1 - पाठ
माइक शेरिल 'कैट रिकॉल'


95

आप उपयोग कर सकते हैं ILIKE। अर्थात

SELECT id FROM groups where name ILIKE 'administrator'

मेरे लिए इसका सही और काम करना ठीक है, मैं मैक ओएस एक्स (माउंटेन लायन) का उपयोग कर रहा हूं।
ADJ

5
यह काम करेगा, लेकिन धीमी प्रतिक्रिया के साथ। गणनाओं के परिणामों के आधार पर तालिकाओं तक तेजी से पहुंच प्राप्त करने के लिए, मैं lowerफ़ंक्शन का उपयोग करने का सुझाव देता हूं । अधिक विवरण देखें
अफोलाबी ओलावुवा अकिंवुमी

1
@AfolabiOlaoluwaAkinwumi मौलिक रूप से यह ज्ञात है कि क्या आप ज्ञात मानों को फ़िल्टर करने के विरोध में परिणाम खोज रहे हैं। बाद के मामले में, एक समान मामले को डेटा स्तर पर बनाए रखा जाना चाहिए, जिससे समानता ऑपरेटर काम कर सके। [व्यक्तिगत सिफारिश प्रकार कोड मूल्यों के लिए ऊपरी पास्कल मामला है]
क्रिस मैरिसिक

53

आप ILIKEकीवर्ड पर भी पढ़ सकते हैं । यह कई बार उपयोगी हो सकता है, यद्यपि यह SQL मानक के अनुरूप नहीं है। अधिक जानकारी के लिए यहाँ देखें: http://www.postgresql.org/docs/9.2/static/functions-match.html


9
यहाँ कुछ देखने के लिए दुर्भावनापूर्ण उपयोगकर्ता इनपुट है। यदि आप कोई क्वेरी चलाते हैं email ILIKE 'user-input-email-here', तो उपयोगकर्ता इनपुट से बचना सुनिश्चित करें। अन्यथा लोग कुछ भी मेल खाने वाले% जैसे वर्णों में प्रवेश कर सकते हैं।
मैट डे लियोन

2
@MattDeLeon हाय। ख़ूब कहा है। लेकिन मैं सिर्फ आपसे पूछना चाहता हूं, अगर मैं उपयोग करता हूं ILIKEऔर prepared statementsक्या यह मेरी रक्षा करेगा sql injection?
स्लीपविन

यकीन नहीं हुआ, मुझे लगता है कि आप तैयार स्टेटमेंट में एक एस्केप स्ट्रिंग भेजना चाहते हैं।
मैट डी लियोन

1
"सक्रिय स्थान के अनुसार मैच केस-असंवेदनशील बनाने के लिए मुख्य शब्द ILIKE का उपयोग LIKE के बजाय किया जा सकता है। यह SQL मानक में नहीं है, बल्कि एक PostgreSQL एक्सटेंशन है।" 9.3 में एक आकर्षण की तरह काम करता है
अलेक्सी डेरीगिन

1
ILIKE की तुलना में धीमी है lower(column_name) like %expression%
पेट्रीक इमोसा

28

आप POSIX नियमित अभिव्यक्तियों का भी उपयोग कर सकते हैं, जैसे

SELECT id FROM groups where name ~* 'administrator'

SELECT 'asd' ~* 'AsD' रिटर्न t


1
मुझे एक ही समस्या थी, मुझे अपने पोस्टग्रेक्यूएल डेटाबेस पर असंवेदनशील खोजों की आवश्यकता थी। मैंने उपयोगकर्ता इनपुट स्ट्रिंग को एक नियमित अभिव्यक्ति में बदलने के बारे में सोचा। अब, = या LIKE के बजाय ~ * का उपयोग करना पूरी तरह से काम करता है! मुझे नए सूचकांक, कॉलम या जो कुछ भी बनाने की आवश्यकता नहीं थी। यकीन है, regex खोज सीधे बाइट की तुलना में धीमी है, लेकिन मुझे नहीं लगता कि प्रदर्शन पर प्रभाव डेटा के दो सेटों को संभालने की तुलना में बहुत अधिक होगा (केवल खोज के लिए एक कम या अपरकेस, फिर संबंधित मूल प्राप्त करने के लिए दूसरे सेट से डेटा)। इसके अलावा, यह क्लीनर है!
साइबरनाइट

1
ठीक है, लेकिन उदाहरण के लिए regexp_matches () के साथ कैसे करें?
डब्ल्यूकेटी

पोस्टग्रेज डॉक्स के अनुसार: ऑपरेटर ~~ LIKE के बराबर है, और ~~ * ILIKE से मेल खाता है। वहाँ भी हैं! ~~ और! ~~ * ऑपरेटर जो क्रमशः LIKE और NOT ILIKE का प्रतिनिधित्व करते हैं। ये सभी ऑपरेटर PostgreSQL-specific हैं।
sh4

मुझे एक समस्या का सामना करना पड़ा जब कोष्ठक को पाठ में शामिल किया गया है, इसका काम नहीं कर रहा है। जैसे: "कोड (LC)"
ओशन विस्पररुमा

8

प्रयोग ~*INSTR की कार्यक्षमता के साथ, प्रदर्शन पर बहुत सुधार कर सकता है।

SELECT id FROM groups WHERE name ~* 'adm'

उन पंक्तियों को नाम के साथ लौटाएं जिनमें 'प्रशंसा' के बराबर या बराबर है।


1
हे, रॉबिन, एसओ में आपका स्वागत है। जेम्स ब्राउन के जवाब ने पहले ही इस समाधान का प्रस्ताव दिया था। इसके अतिरिक्त, आपका प्रस्तावित उत्तर किसी भी तरह से रेगेक्स का लाभ नहीं उठाता है।
राफेल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.