ओरेकल में केस असंवेदनशील खोज


228

का डिफ़ॉल्ट व्यवहार LIKEऔर अन्य तुलना ऑपरेटर =आदि केस-संवेदी है।

क्या यह संभव है कि उन्हें केस-असंवेदनशील बना दिया जाए?


फ्रेंडली रिमाइंडर कि कुछ उदाहरण खोज का परिणाम पूर्ण तालिका स्कैन में होगा, भले ही user_name पर कोई इंडेक्स हो।
जॉनसन

8
क्या आपने REGEXP_LIKE(username,'me','i')LIKE के बजाय उपयोग करने पर विचार किया है ?
kubanczyk

5
नहीं, LIKE मेरे लिए ठीक काम करता है
sergionni

जवाबों:


82

10gR2 के बाद से, ओरेकल सत्र NLS_COMPऔर NLS_SORTमापदंडों को निर्धारित करके स्ट्रिंग तुलनाओं के व्यवहार को ठीक करने की अनुमति देता है :

SQL> SET HEADING OFF
SQL> SELECT *
  2  FROM NLS_SESSION_PARAMETERS
  3  WHERE PARAMETER IN ('NLS_COMP', 'NLS_SORT');

NLS_SORT
BINARY

NLS_COMP
BINARY


SQL>
SQL> SELECT CASE WHEN 'abc'='ABC' THEN 1 ELSE 0 END AS GOT_MATCH
  2  FROM DUAL;

         0

SQL>
SQL> ALTER SESSION SET NLS_COMP=LINGUISTIC;

Session altered.

SQL> ALTER SESSION SET NLS_SORT=BINARY_CI;

Session altered.

SQL>
SQL> SELECT *
  2  FROM NLS_SESSION_PARAMETERS
  3  WHERE PARAMETER IN ('NLS_COMP', 'NLS_SORT');

NLS_SORT
BINARY_CI

NLS_COMP
LINGUISTIC


SQL>
SQL> SELECT CASE WHEN 'abc'='ABC' THEN 1 ELSE 0 END AS GOT_MATCH
  2  FROM DUAL;

         1

आप मामले को असंवेदनशील अनुक्रमित भी बना सकते हैं:

create index
   nlsci1_gen_person
on
   MY_PERSON
   (NLSSORT
      (PERSON_LAST_NAME, 'NLS_SORT=BINARY_CI')
   )
;

यह जानकारी ओरेकल केस असंवेदनशील खोजों से ली गई थी । लेख में उल्लेख किया गया है REGEXP_LIKEलेकिन यह अच्छे पुराने के =साथ भी काम करता है।


10gR2 से पुराने संस्करणों में यह वास्तव में नहीं किया जा सकता है और सामान्य दृष्टिकोण, अगर आपको उच्चारण-असंवेदनशील खोज की आवश्यकता नहीं है, तो बसUPPER() स्तंभ और खोज अभिव्यक्ति दोनों हैं।


1
यह अच्छी तरह से काम करता है, लेकिन यह LIKE / = ऑपरेटर्स का उपयोग करके UPDATES बहुत धीमी गति से करता है ...... :(
Saqib Ali

1
@SaqibAli महत्वाकांक्षी LIKEअभिव्यक्ति (जैसे WHERE foo LIKE '%abc%') पहले से ही काफी धीमी हैं अगर उन्हें अनुक्रमित नहीं किया जा सकता है, मुझे नहीं लगता कि यह विशेष रूप से केस सेंसिटिविटी से संबंधित है।
अल्वारो गोंजालेज

1
आप इन्हें शेल वातावरण की तरह SQLPLUS के बाहर भी सेट कर सकते हैं। उदाहरण के लिए एक पर्ल स्क्रिप्ट का उपयोग करके DBD::Oracle, आप $ENV{NLS_SORT} = 'BINARY_CI'; $ENV{NLS_COMP} = 'LINGUISTIC';`DBI-> connect` कॉल करने से पहले लिख सकते हैं ।
mivk

हे ALTER SESSIONकेवल सुधार के अपने स्थानीय उदाहरण को बदल देता है और क्या इसका मतलब आपके वर्तमान सत्र की तरह है, अगर मैं इसे बंद कर देता और फिर से खोल देता। क्या कोई ऐसा तरीका है जो मैं देख सकता हूं कि वर्तमान मूल्य क्या हैं ताकि अगर हर जगह
इसकायम

305

पूर्ण-पाठ अनुक्रमणिका का उपयोग किए बिना Oracle में केस-असंवेदनशील खोज करने के 3 मुख्य तरीके हैं।

अंततः आपके द्वारा चुनी गई विधि आपके व्यक्तिगत परिस्थितियों पर निर्भर करती है; याद रखने वाली मुख्य बात यह है कि प्रदर्शन को बेहतर बनाने के लिए आपको केस-इन्सेंसिव सर्च के लिए सही इंडेक्स करना चाहिए।

1. अपने कॉलम और अपने स्ट्रिंग को पहचान के अनुसार केस करें।

आप अपने सभी डेटा का उपयोग करके UPPER()या एक ही मामले के लिए बाध्य कर सकते हैं LOWER():

select * from my_table where upper(column_1) = upper('my_string');

या

select * from my_table where lower(column_1) = lower('my_string');

यदि उपयुक्त के रूप में column_1अनुक्रमित नहीं किया जाता है upper(column_1)या lower(column_1), यह एक पूर्ण तालिका स्कैन को बाध्य कर सकता है। इससे बचने के लिए आप फ़ंक्शन-आधारित इंडेक्स बना सकते हैं ।

create index my_index on my_table ( lower(column_1) );

यदि आप LIKE का उपयोग कर रहे हैं, तो आपको %उस स्ट्रिंग के चारों ओर भाग लेना होगा जिसे आप खोज रहे हैं।

select * from my_table where lower(column_1) LIKE lower('my_string') || '%';

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

2. नियमित अभिव्यक्ति का प्रयोग करें।

ओरेकल से 10 ग्राम आगे REGEXP_LIKE()उपलब्ध है। आप _match_parameter_ निर्दिष्ट कर सकते हैं'i'केस-असंवेदनशील खोज करने के लिए ।

एक समानता ऑपरेटर के रूप में इसका उपयोग करने के लिए आपको स्ट्रिंग के प्रारंभ और अंत को निर्दिष्ट करना होगा, जिसे कैरेट और डॉलर चिह्न द्वारा दर्शाया गया है।

select * from my_table where regexp_like(column_1, '^my_string$', 'i');

LIKE के समतुल्य प्रदर्शन करने के लिए, इन्हें हटाया जा सकता है।

select * from my_table where regexp_like(column_1, 'my_string', 'i');

इससे सावधान रहें क्योंकि आपके स्ट्रिंग में ऐसे अक्षर हो सकते हैं जिनकी नियमित अभिव्यक्ति इंजन द्वारा अलग तरह से व्याख्या की जाएगी।

यह SQL Fiddle आपको REGEXP_LIKE () का उपयोग करने के अलावा एक ही उदाहरण आउटपुट दिखाता है।

3. इसे सत्र स्तर पर बदलें।

NLS_SORT पैरामीटर आदेश और विभिन्न तुलना ऑपरेटरों, सहित के लिए मिलान अनुक्रम को नियंत्रित करता है =और तरह। आप एक बाइनरी, केस-असंवेदनशील को निर्दिष्ट कर सकते हैं, सत्र को बदलकर सॉर्ट कर सकते हैं। इसका अर्थ यह होगा कि उस सत्र में की गई प्रत्येक क्वेरी केस-असंवेदनशील मापदंडों का प्रदर्शन करेगी।

alter session set nls_sort=BINARY_CI

भाषाई छँटाई और स्ट्रिंग खोज के आसपास अतिरिक्त जानकारी उपलब्ध हैयदि आप एक अलग भाषा निर्दिष्ट करना चाहते हैं, या BINARY_AI का उपयोग करके एक उच्चारण-असंवेदनशील खोज करना चाहते हैं, तो ।

आपको NLS_COMP पैरामीटर बदलने की भी आवश्यकता होगी ; उद्धरण के लिए:

NLS_SORT पैरामीटर का पालन करने वाले सटीक ऑपरेटर और क्वेरी क्लॉज़ NLS_COMP पैरामीटर के मान पर निर्भर करते हैं। यदि कोई ऑपरेटर या क्लॉज़ NLS_SORT मान का पालन नहीं करता है, जैसा कि NLS_COMP द्वारा निर्धारित किया जाता है, तो उपयोग किया गया कोलाज BINARY है।

NLS_COMP का डिफ़ॉल्ट मान BINARY है; लेकिन, LINGUISTIC निर्दिष्ट करता है कि Oracle को NLS_SORT के मूल्य पर ध्यान देना चाहिए:

WHERE क्लॉज और PL / SQL ब्लॉक्स में सभी SQL ऑपरेशंस के लिए तुलना NLS_SORT पैरामीटर में निर्दिष्ट भाषाई प्रकार का उपयोग करना चाहिए। प्रदर्शन में सुधार करने के लिए, आप उस स्तंभ पर एक भाषाई सूचकांक को भी परिभाषित कर सकते हैं जिसके लिए आप भाषाई तुलना चाहते हैं।

इसलिए, एक बार फिर, आपको सत्र को बदलने की आवश्यकता है

alter session set nls_comp=LINGUISTIC

जैसा कि प्रलेखन में कहा गया है कि आप प्रदर्शन को बेहतर बनाने के लिए एक भाषाई सूचकांक बनाना चाहते हैं

create index my_linguistc_index on my_table 
   (NLSSORT(column_1, 'NLS_SORT = BINARY_CI'));

"फंक्शन-आधारित इंडेक्स बनाएं" कमाल है कि इससे क्या फर्क
पड़

क्या मैं पूछ सकता हूं कि इसके select * from my_table where lower(column_1) LIKE lower('my_string') || '%';बजाय ऐसा करना अलग क्यों है select * from my_table where lower(column_1) LIKE lower('my_string%');? क्या इससे कोई फायदा होता है?
लोपेज़विट

1
एक कारण यह होगा कि यदि आपकी क्वेरी को अधिकता से (अधिकतर स्थितियों में) सम्‍मिलित किया गया है, तो आपके कॉलिंग कोड को हमेशा @lopezvit पर एक% समाप्‍त करने की आवश्‍यकता नहीं है।
बेन

1
अगर कुछ पात्र हैं, जो इसके परिणाम को गड़बड़ कर देंगे regexp_like, तो क्या ऐसे तार से बचने का कोई तरीका है? एक उदाहरण देते हुए, यदि स्ट्रिंग में $ है, तो आउटपुट वैसा नहीं होगा जैसा हम उम्मीद करते हैं। // cc @Ben और अन्य कृपया साझा करें।
बूजमोब

2
` भागने चरित्र @bozzmob है। आउटपुट में कोई अंतर नहीं होना चाहिए अगर स्ट्रिंग नियमित अभिव्यक्ति पर चल रही है $, तो इसमें आपको केवल समस्या हो सकती है यदि आपको $अपने नियमित अभिव्यक्ति में शाब्दिक की आवश्यकता हो । यदि आपको कोई विशिष्ट मुद्दा मिला है तो मैं एक और प्रश्न पूछूंगा यदि इस टिप्पणी / उत्तर ने मदद नहीं की है।
बेन

51

शायद आप प्रयोग करके देख सकते हैं

SELECT user_name
FROM user_master
WHERE upper(user_name) LIKE '%ME%'

3
यह काम करता है जब इनपुट पैरामीटर पूरे ऊपरी-मामले में होता है, और यदि कम या मिश्रित होता है, तो यह नहीं होता है
सर्जियोनी

13
क्या आपने इसके बारे में सोचा है WHERE upper(user_name) LIKE UPPER('%ME%')? :)
कोनराक

3
@sergionni आपको ऊपरी शब्द खोज शब्द के अनुसार ही होना चाहिए!
मार्कस विनैंड

3
@sergionni, तो फिर आप UPPERइनपुट पैरामीटर पर भी उपयोग क्यों नहीं करते ?
Czechnology

5
@ V4Vendetta upperफ़ंक्शन का उपयोग करके आप सूचकांक खो देते हैं, क्या आपके पास कोई विचार है कि सूचकांक का उपयोग करके खोज कैसे करें?
jcho360

7

Oracle 12c R2 से आप उपयोग कर सकते हैं COLLATE operator:

कोलायत ऑपरेटर एक अभिव्यक्ति के लिए टकराव को निर्धारित करता है। यह ऑपरेटर आपको उस कॉलेशन को ओवरराइड करने में सक्षम बनाता है जो डेटाबेस ने मानक कॉलेशन व्युत्पत्ति नियमों का उपयोग करके अभिव्यक्ति के लिए प्राप्त किया होगा।

COLLATE ऑपरेटर एक तर्क, collation_name लेता है, जिसके लिए आप एक नामित टकराव या छद्म-टकराव निर्दिष्ट कर सकते हैं। यदि समतलीकरण नाम में कोई स्थान है, तो आपको दोहरे उद्धरण चिह्नों में नाम संलग्न करना होगा।

डेमो:

CREATE TABLE tab1(i INT PRIMARY KEY, name VARCHAR2(100));

INSERT INTO tab1(i, name) VALUES (1, 'John');
INSERT INTO tab1(i, name) VALUES (2, 'Joe');
INSERT INTO tab1(i, name) VALUES (3, 'Billy'); 
--========================================================================--
SELECT /*csv*/ *
FROM tab1
WHERE name = 'jOHN' ;
-- no rows selected

SELECT /*csv*/ *
FROM tab1
WHERE name COLLATE BINARY_CI = 'jOHN' ;
/*
"I","NAME"
1,"John"
*/

SELECT /*csv*/ *
FROM tab1 
WHERE name LIKE 'j%';
-- no rows selected

SELECT /*csv*/ *
FROM tab1 
WHERE name COLLATE BINARY_CI LIKE 'j%';
/*
"I","NAME"
1,"John"
2,"Joe"
*/

db <> फिडेल डेमो


2
select user_name
from my_table
where nlssort(user_name, 'NLS_SORT = Latin_CI') = nlssort('%AbC%', 'NLS_SORT = Latin_CI')

%अपने दूसरे के लिए पहली बहस में की NLSSORTकर रहे हैं नहीं वाइल्डकार्ड, सही मतलब? वे तरह तरह के भ्रम करते हैं।
स्टेफन वैन डेन अककर

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.