मैं MySQL पर SQL केस को संवेदनशील स्ट्रिंग तुलना कैसे कर सकता हूं?


285

मेरे पास एक फ़ंक्शन है जो मिश्रित मामले के साथ पांच वर्ण देता है। यदि मैं इस स्ट्रिंग पर एक प्रश्न करता हूं तो यह मामले की परवाह किए बिना मान लौटाएगा।

मैं MySQL स्ट्रिंग प्रश्नों को संवेदनशील कैसे बना सकता हूं?



8
ध्यान दें कि BINARY केस संवेदी तुलना के समान नहीं है: 'a' का चयन करें जैसे 'a' // // true true select 'à' जैसे BINARY 'a' / // false !!! एक 'COLLATE लैटिन 1_general_cs //' जैसे 'a' का चयन करें। सही है तो केस संवेदी तुलना के लिए BINARY का उपयोग करने का सुझाव गलत है।
cquezel

3
@ cquezel: तो, आप कह रहे हैं कि [BINARY 'a' की तरह 'a' का चयन करें? किसी भी मामले में, मामले की संवेदनशील तुलना से इसका क्या लेना-देना है?
फ्रांसिस्को ज़ाराबोज़ो

3
@FranciscoZarabozo नीचे कुछ लोगों ने केस संवेदी तुलना करने के लिए BINARY तुलना का उपयोग करने का सुझाव दिया। मैं केवल यह संकेत दे रहा हूं कि अन्य भाषाओं में, यह संभवतः अपेक्षित रूप से काम नहीं करेगा क्योंकि BINARY मामला संवेदनशील नहीं है।
cquezel

3
@ cquezel मुझे लगता है कि 'आ' 'ए' की तुलना में एक अलग अक्षर है। इसलिए दोनों के बीच तुलना वास्तव में झूठी होनी चाहिए जो भी मामला हो।
स्टीफन

जवाबों:


159

http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html

डिफॉल्ट कैरेक्टर सेट और कॉलेशन लैब्रा 1 और लैटिन 1_स्वादिस्टि_सी होते हैं, इसलिए नॉनबिनिकल स्ट्रींग कंपेयर डिफॉल्ट के मामले में असंवेदनशील होते हैं। इसका अर्थ है कि यदि आप col_name LIKE '% a' से खोजते हैं, तो आपको सभी स्तंभ मान मिलते हैं जो A या a से शुरू होते हैं। इस खोज के मामले को संवेदनशील बनाने के लिए, सुनिश्चित करें कि किसी एक ऑपरेंड में केस सेंसिटिव या बाइनरी कॉलेशन है। उदाहरण के लिए, यदि आप एक स्तंभ और एक तार की तुलना कर रहे हैं, जिसमें दोनों में लैटिन 1 वर्ण सेट है, तो आप COLLATE ऑपरेटर का उपयोग कर सकते हैं, जिससे या तो ऑपरेंड हो सकता है और लैटिन 1_general_cs या latin1_bin टकराव हो सकता है:

col_name COLLATE latin1_general_cs LIKE 'a%'
col_name LIKE 'a%' COLLATE latin1_general_cs
col_name COLLATE latin1_bin LIKE 'a%'
col_name LIKE 'a%' COLLATE latin1_bin

यदि आप चाहते हैं कि हमेशा केस-संवेदी फैशन में एक कॉलम का इलाज किया जाए, तो इसे केस सेंसिटिव या बाइनरी कॉलेशन के साथ घोषित करें।


4
कैसे phpmyadmin में यह करने के लिए पर कोई संकेत?
स्टीवनबी

4
@StevenB: स्तंभ का संपादन बटन क्लिक करें, फिर मिलान सेट -> i.imgur.com/7SoEw.png
परिश्रम से काम करना

32
@BT utf8 कॉलम केस को संवेदनशील बनाने के लिए आप बिन SELECT 'email' COLLATE utf8_bin = 'Email'
कोलेशन का

@drudge आप केस संवेदी टकराव के साथ कॉलम कैसे घोषित करेंगे?
स्टीफन

1
@StephaneEybert अगर आप सीधे केस सेंसिटिविटी की तलाश कर रहे हैं, तो मुझे ut8 टेबल में एक फ़ील्ड के लिए varchar के बजाय varbinary का उपयोग करने का सौभाग्य मिला है। HTH
एंड्रयू टी

724

अच्छी खबर यह है कि यदि आपको केस-संवेदी क्वेरी बनाने की आवश्यकता है, तो यह करना बहुत आसान है:

SELECT *  FROM `table` WHERE BINARY `column` = 'value'

34
यही वह है जिसकी तलाश में मैं हूं। अगर मैं कर सकता तो मैं इसे और ऊपर ले जाता। एक सवाल हालांकि, प्रदर्शन पर इसका क्या प्रभाव पड़ता है? मैं इसे सीमित रिपोर्टिंग चीज़ पर उपयोग कर रहा हूं, इसलिए यह मेरे मामले में महत्वपूर्ण नहीं है, लेकिन मैं उत्सुक हूं।
adjwilli

23
इसका जवाब क्यों नहीं है? यह वही है जो मुझे भी चाहिए था।
आर्ट गीगेल

7
@adjwilli यदि स्तंभ किसी अनुक्रमणिका का हिस्सा था, तो आपको उस अनुक्रमणिका पर निर्भर प्रश्नों पर एक प्रदर्शन प्रभावित होगा। प्रदर्शन को बनाए रखने के लिए, आपको वास्तव में तालिका को बदलने की आवश्यकता है।
dshin

6
यह यूटीएफ -8 तार के लिए एक अलग चरित्र के साथ एक ही चरित्र के साथ क्या करेगा, उदाहरण के लिए एक umlaut जोड़ने के लिए एक संयोजन चरित्र का उपयोग कर? ये UTF-8 स्ट्रिंग्स को समान माना जा सकता है: convert(char(0x65,0xcc,0x88) using utf8)(जैसे eकि ¨जोड़ा गया) और convert(char(0xc3,0xab) using utf8)(यानी ë), लेकिन जोड़ना BINARYउन्हें असमान बना देगा।
mvds

3
एक प्रदर्शन उदाहरण के रूप में: मेरी क्वेरी 3,5ms (नगण्य) से 1.570ms (यह लगभग एक दूसरे और एक आधा है) से गुजरती है, 1.8M पंक्तियों के साथ एक तालिका क्वेरी करते हुए aprox।
लूली सूनोल

64

क्रेग व्हाइट द्वारा पोस्ट किए गए उत्तर में बड़ा प्रदर्शन दंड है

SELECT *  FROM `table` WHERE BINARY `column` = 'value'

क्योंकि यह अनुक्रमित का उपयोग नहीं करते हैं। इसलिए, या तो आपको यहां उल्लेख की तरह तालिका कोलाज बदलने की आवश्यकता है https://dev.mysql.com/doc/refman/5.7/en/case-s संवेदनशीलता. html

या

सबसे आसान फिक्स, आपको मूल्य के एक बायिनरी का उपयोग करना चाहिए।

SELECT *  FROM `table` WHERE `column` = BINARY 'value'

उदाहरण के लिए।

mysql> EXPLAIN SELECT * FROM temp1 WHERE BINARY col1 = "ABC" AND col2 = "DEF" ;
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+
| id | select_type | table  | type | possible_keys | key  | key_len | ref  | rows   | Extra       |
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+
|  1 | SIMPLE      | temp1  | ALL  | NULL          | NULL | NULL    | NULL | 190543 | Using where |
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+

वी.एस.

mysql> EXPLAIN SELECT * FROM temp1 WHERE col1 = BINARY "ABC" AND col2 = "DEF" ;
+----+-------------+-------+-------+---------------+---------------+---------+------+------+------------------------------------+
| id | select_type | table | type  | possible_keys | key           | key_len | ref  | rows | Extra                              |
+----+-------------+-------+-------+---------------+---------------+---------+------+------+------------------------------------+
|  1 | SIMPLE      | temp1 | range | col1_2e9e898e | col1_2e9e898e | 93      | NULL |    2 | Using index condition; Using where |
+----+-------------+-------+-------+---------------+---------------+---------+------+------+------------------------------------+
enter code here

1 पंक्ति में सेट (0.00 सेकंड)


यह 10.3.22-MariaDB (libmysql - 5.6.43 का उपयोग करके) पर केस-संवेदी नहीं लगता है
user10398534

40

= ऑपरेटर का उपयोग करने के बजाय, आप LIKE या LIKE BINARY का उपयोग करना चाह सकते हैं

// this returns 1 (true)
select 'A' like 'a'

// this returns 0 (false)
select 'A' like binary 'a'


select * from user where username like binary 'a'

यह अपनी स्थिति में 'ए' और 'ए' नहीं लेगा


यह 10.3.22-MariaDB (libmysql - 5.6.43 का उपयोग करके) पर केस-संवेदी नहीं लगता है
user10398534

17

BINARY का उपयोग करने से पहले एक इंडेक्स का उपयोग करने के लिए, यदि आप बड़ी टेबल रखते हैं तो आप कुछ ऐसा कर सकते हैं।

SELECT
   *
FROM
   (SELECT * FROM `table` WHERE `column` = 'value') as firstresult
WHERE
   BINARY `column` = 'value'

सबक्वेरी का परिणाम वास्तव में एक छोटा सा मामला-असंवेदनशील उपसमुच्चय होता है, जिसके बाद आप केवल केस-संवेदी मैच का चयन करते हैं।


यह कहने योग्य है कि उपरोक्त केवल आपके डेटा के आधार पर मदद करेगा - आपका मामला असंवेदनशील खोज संभावित रूप से डेटा का एक बड़ा सबसेट वापस कर सकता है।
ब्रायनज

15

कॉलम के टकराव को बदलने के बिना केस संवेदनशील स्ट्रिंग तुलना करने का सबसे सही तरीका यह है कि कॉलम की तुलना किए जा रहे मूल्य के लिए वर्ण सेट और टकराव को स्पष्ट रूप से निर्दिष्ट करें।

select * from `table` where `column` = convert('value' using utf8mb4) collate utf8mb4_bin;

उपयोग क्यों नहीं binary?

binaryऑपरेटर का उपयोग करना अस्वीकार्य है क्योंकि यह एन्कोडेड स्ट्रिंग्स के वास्तविक बाइट्स की तुलना करता है। यदि आप अलग-अलग वर्णों का उपयोग करके एन्कोड किए गए दो स्ट्रिंग्स के वास्तविक बाइट्स की तुलना करते हैं, तो दो स्ट्रिंग्स को समान माना जाना चाहिए जो समान नहीं हो सकते हैं। उदाहरण के लिए यदि आपके पास एक ऐसा स्तंभ है जो latin1वर्ण सेट का उपयोग करता है , और आपका सर्वर / सत्र वर्ण सेट है utf8mb4, तो जब आप स्तंभ की तुलना एक स्ट्रिंग से करते हैं, जिसमें 'कैफ़े' जैसे उच्चारण होते हैं, तो यह उसी स्ट्रिंग वाले पंक्तियों से मेल नहीं खाएगा! ऐसा इसलिए है क्योंकि latin1é बाइट के रूप में एन्कोडेड है, 0xE9लेकिन utf8इसमें दो बाइट्स हैं 0xC3A9:।

convertसाथ ही उपयोग क्यों करें collate?

कोलाज को चरित्र सेट से मेल खाना चाहिए। इसलिए यदि आपका सर्वर या सत्र latin1वर्ण सेट का उपयोग करने के लिए सेट है जिसे आपको अवश्य उपयोग करना चाहिए collate latin1_binलेकिन यदि आपका चरित्र सेट है utf8mb4तो आपको अवश्य उपयोग करना चाहिए collate utf8mb4_bin। इसलिए सबसे मजबूत समाधान हमेशा मूल्य को सबसे लचीले चरित्र सेट में बदलना है, और उस चरित्र सेट के लिए द्विआधारी टकराव का उपयोग करना है।

मूल्य पर कॉलम क्यों नहीं convertऔर क्यों लागू collateकरें?

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

उच्चारण की संवेदनशीलता

यह नोट करना महत्वपूर्ण है कि MySql न केवल मामले में एक का उपयोग कर स्तंभों के लिए असंवेदनशील है _ciमिलान (जो डिफ़ॉल्ट रूप है), लेकिन यह भी लहजे असंवेदनशील। इसका मतलब है कि 'é' = 'e'। एक द्विआधारी टकराव (या binaryऑपरेटर) का उपयोग स्ट्रिंग तुलनात्मक उच्चारण के साथ-साथ मामले को संवेदनशील बना देगा।

क्या है utf8mb4?

utf8MySql में वर्ण सेट एक उपनाम के लिए है utf8mb3जो किया गया है हाल के संस्करण में पदावनत क्योंकि यह 4 बाइट वर्णों के लिए (जो की तरह 🐈 तार एन्कोड करने के लिए महत्वपूर्ण है) का समर्थन नहीं करता। यदि आप MySql के साथ UTF8 वर्ण एन्कोडिंग का उपयोग करना चाहते हैं तो आपको utf8mb4चारसेट का उपयोग करना चाहिए ।


8

निम्नलिखित MySQL संस्करणों के बराबर या 5.5 से अधिक है।

/Etc/mysql/my.cnf में जोड़ें

  [mysqld]
  ...
  character-set-server=utf8
  collation-server=utf8_bin
  ...

मेरे द्वारा किए गए अन्य सभी टकराव केस-असंवेदनशील लग रहे थे, केवल "utf8_bin" ने काम किया।

इसके बाद mysql को पुनः आरंभ करना न भूलें:

   sudo service mysql restart

Http://dev.mysql.com/doc/refman/5.0/en/case-s संवेदनशीलता. html के अनुसार "लैटिन 1_बिन" भी है।

Mysql स्टार्टअप द्वारा "utf8_general_cs" को स्वीकार नहीं किया गया था। (मैंने "_cs" को "केस-संवेदी" - ???) के रूप में पढ़ा।


7

इस तरह संवेदनशील होने के लिए आप BINARY का उपयोग कर सकते हैं

select * from tb_app where BINARY android_package='com.Mtime';

दुर्भाग्य से यह एसक्यूएल इंडेक्स का उपयोग नहीं कर सकता है, आप उस इंडेक्स पर निर्भर प्रश्नों पर हिट परफॉर्म करेंगे

mysql> explain select * from tb_app where BINARY android_package='com.Mtime';
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows    | filtered | Extra       |
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+
|  1 | SIMPLE      | tb_app | NULL       | ALL  | NULL          | NULL | NULL    | NULL | 1590351 |   100.00 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+

सौभाग्य से, इस समस्या को हल करने के लिए मेरे पास कुछ ट्रिक्स हैं

mysql> explain select * from tb_app where android_package='com.Mtime' and BINARY android_package='com.Mtime';
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+
| id | select_type | table  | partitions | type | possible_keys             | key                       | key_len | ref   | rows | filtered | Extra                 |
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+
|  1 | SIMPLE      | tb_app | NULL       | ref  | idx_android_pkg           | idx_android_pkg           | 771     | const |    1 |   100.00 | Using index condition |
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+  

यह 10.3.22-MariaDB (libmysql - 5.6.43 का उपयोग करके) पर केस-संवेदी नहीं लगता है
user10398534

2

अति उत्कृष्ट!

मैं आपके साथ साझा करता हूं, पासवर्ड की तुलना करने वाले फ़ंक्शन से कोड:

SET pSignal =
(SELECT DECODE(r.usignal,'YOURSTRINGKEY') FROM rsw_uds r WHERE r.uname =
in_usdname AND r.uvige = 1);

SET pSuccess =(SELECT in_usdsignal LIKE BINARY pSignal);

IF pSuccess = 1 THEN
      /*Your code if match*/
ELSE
      /*Your code if don't match*/

END IF;

declare pSuccess BINARY;शुरुआत में जोड़ने की जरूरत है
adinas

2

DB स्तर पर कुछ भी बदलने की आवश्यकता नहीं है, बस आपको SQL क्वेरी में परिवर्तन करना होगा जो यह काम करेगा।

उदाहरण -

"SELECT * FROM <TABLE> where userId = '" + iv_userId + "' AND password = BINARY '" + iv_password + "'";

बाइनरी कीवर्ड केस को संवेदनशील बनाएगा।


1

mysql डिफ़ॉल्ट रूप से संवेदनशील नहीं है, भाषा को बदलने के लिए प्रयास करें latin1_general_cs

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