मेरे पास एक फ़ंक्शन है जो मिश्रित मामले के साथ पांच वर्ण देता है। यदि मैं इस स्ट्रिंग पर एक प्रश्न करता हूं तो यह मामले की परवाह किए बिना मान लौटाएगा।
मैं MySQL स्ट्रिंग प्रश्नों को संवेदनशील कैसे बना सकता हूं?
मेरे पास एक फ़ंक्शन है जो मिश्रित मामले के साथ पांच वर्ण देता है। यदि मैं इस स्ट्रिंग पर एक प्रश्न करता हूं तो यह मामले की परवाह किए बिना मान लौटाएगा।
मैं MySQL स्ट्रिंग प्रश्नों को संवेदनशील कैसे बना सकता हूं?
जवाबों:
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
यदि आप चाहते हैं कि हमेशा केस-संवेदी फैशन में एक कॉलम का इलाज किया जाए, तो इसे केस सेंसिटिव या बाइनरी कॉलेशन के साथ घोषित करें।
SELECT 'email' COLLATE utf8_bin = 'Email'
अच्छी खबर यह है कि यदि आपको केस-संवेदी क्वेरी बनाने की आवश्यकता है, तो यह करना बहुत आसान है:
SELECT * FROM `table` WHERE BINARY `column` = 'value'
convert(char(0x65,0xcc,0x88) using utf8)
(जैसे e
कि ¨
जोड़ा गया) और convert(char(0xc3,0xab) using utf8)
(यानी ë
), लेकिन जोड़ना BINARY
उन्हें असमान बना देगा।
क्रेग व्हाइट द्वारा पोस्ट किए गए उत्तर में बड़ा प्रदर्शन दंड है
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 सेकंड)
= ऑपरेटर का उपयोग करने के बजाय, आप 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'
यह अपनी स्थिति में 'ए' और 'ए' नहीं लेगा
BINARY का उपयोग करने से पहले एक इंडेक्स का उपयोग करने के लिए, यदि आप बड़ी टेबल रखते हैं तो आप कुछ ऐसा कर सकते हैं।
SELECT
*
FROM
(SELECT * FROM `table` WHERE `column` = 'value') as firstresult
WHERE
BINARY `column` = 'value'
सबक्वेरी का परिणाम वास्तव में एक छोटा सा मामला-असंवेदनशील उपसमुच्चय होता है, जिसके बाद आप केवल केस-संवेदी मैच का चयन करते हैं।
कॉलम के टकराव को बदलने के बिना केस संवेदनशील स्ट्रिंग तुलना करने का सबसे सही तरीका यह है कि कॉलम की तुलना किए जा रहे मूल्य के लिए वर्ण सेट और टकराव को स्पष्ट रूप से निर्दिष्ट करें।
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
?utf8
MySql में वर्ण सेट एक उपनाम के लिए है utf8mb3
जो किया गया है हाल के संस्करण में पदावनत क्योंकि यह 4 बाइट वर्णों के लिए (जो की तरह 🐈 तार एन्कोड करने के लिए महत्वपूर्ण है) का समर्थन नहीं करता। यदि आप MySql के साथ UTF8 वर्ण एन्कोडिंग का उपयोग करना चाहते हैं तो आपको utf8mb4
चारसेट का उपयोग करना चाहिए ।
निम्नलिखित 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" को "केस-संवेदी" - ???) के रूप में पढ़ा।
इस तरह संवेदनशील होने के लिए आप 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 |
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+
अति उत्कृष्ट!
मैं आपके साथ साझा करता हूं, पासवर्ड की तुलना करने वाले फ़ंक्शन से कोड:
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;
शुरुआत में जोड़ने की जरूरत है
DB स्तर पर कुछ भी बदलने की आवश्यकता नहीं है, बस आपको SQL क्वेरी में परिवर्तन करना होगा जो यह काम करेगा।
उदाहरण -
"SELECT * FROM <TABLE> where userId = '" + iv_userId + "' AND password = BINARY '" + iv_password + "'";
बाइनरी कीवर्ड केस को संवेदनशील बनाएगा।