আমি কীভাবে এসকিউএল কেসকে সংবেদনশীল স্ট্রিং মাইএসকিউএলে তুলনা করতে পারি?


285

আমার একটি ফাংশন রয়েছে যা মিশ্র কেস সহ পাঁচটি অক্ষর প্রদান করে। যদি আমি এই স্ট্রিংয়ে কোনও জিজ্ঞাসা করি তা কেস নির্বিশেষে মানটি ফিরিয়ে দেবে।

আমি কীভাবে মাইএসকিউএল স্ট্রিং কোয়েরি কেসকে সংবেদনশীল করে তুলতে পারি?



8
লক্ষ্য করুন যে বিনারি কেস সংবেদনশীল তুলনা হিসাবে এক নয়: '' 'এর মতো' এ 'নির্বাচন করুন // সত্য সত্য নির্বাচন করুন' B 'বিনয়ের মতো' এ '// রিটার্ন মিথ্যা !!! '' 'এর মতো' একটি 'নির্বাচন করুন ল্যাটিন 1_ জেনারাল_সিএস // রিটার্ন সত্য হয় তাই সংবেদনশীল তুলনার ক্ষেত্রে বিনয়ের ব্যবহারের পরামর্শটি ভুল।
cquezel

3
@ কেকেজেল: সুতরাং, আপনি বলছেন যে ['select' বিনয়ের মতো '' নির্বাচন করুন] সত্য হওয়া উচিত? ?? যে কোনও ক্ষেত্রে, কেস সংবেদনশীল তুলনার সাথে এটির কী সম্পর্ক রয়েছে?
ফ্রান্সিসকো জারাবোজো

3
@ ফ্রেঞ্চিসকো জারাবোজো নীচের কিছু লোক ক্ষেত্রে সংবেদনশীল তুলনা করার জন্য বিনয়ের তুলনাটি ব্যবহার করার পরামর্শ দিয়েছেন। আমি কেবল ইঙ্গিত করছি যে অন্যান্য ভাষায়, এটি সম্ভবত প্রত্যাশার মতো কাজ করবে না কারণ বিনারি যেমন সংবেদনশীল হিসাবে একই নয়।
cquezel

3
@ কেকেজেল আমি ভাবব যে 'à' 'এ' থেকে আলাদা চিঠি। সুতরাং উভয়ের মধ্যে তুলনা সত্যই যাই হোক না কেন মিথ্যা হওয়া উচিত।
স্টিফেন

উত্তর:


159

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

ডিফল্ট অক্ষর সেট এবং কোলেশনটি হ'ল ল্যাটিন 1 এবং ল্যাটিন 1_সুইডিস_সি, সুতরাং ননবাইনারি স্ট্রিং তুলনাগুলি ডিফল্টরূপে সংবেদনশীল হয় না। এর অর্থ হ'ল আপনি যদি কল_নাম 'লাইক' একটি% 'দিয়ে অনুসন্ধান করেন তবে আপনি কলামের মানগুলি A বা a দিয়ে শুরু করবেন। এই অনুসন্ধান কেসটিকে সংবেদনশীল করতে, নিশ্চিত হয়ে নিন যে কোনও অপারেন্ডের কেস সংবেদনশীল বা বাইনারি কোলেশন রয়েছে। উদাহরণস্বরূপ, আপনি যদি একটি কলাম এবং একটি স্ট্রিংয়ের তুলনা করছেন যা উভয়টিতেই ল্যাটিন 1 বর্ণচিহ্ন সেট রয়েছে, আপনি কোল্যাট অপারেটরটি ল্যাটিন 1_জেনারাল_সিএস বা ল্যাটিন 1_বিন কোলেশন তৈরি করতে ব্যবহার করতে পারেন:

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
@ বিটি ইউটিএফ ৮ কলামের ক্ষেত্রে সংবেদনশীল করতে আপনি বিন কোলেশন যেমন ব্যবহার করতে পারেন:SELECT 'email' COLLATE utf8_bin = 'Email'
পিয়োট্রেক্কর

@ ড্রড আপনি কেস সংবেদনশীল কোলেশন দিয়ে কীভাবে একটি কলাম ঘোষণা করবেন?
স্টিফেন

1
@ স্টেফেনইবার্ট আপনি যদি সন্ধানের ক্ষেত্রে সংবেদনশীলতাটি সরাসরি খুঁজছেন তবে আমি ইউটি 8 টেবিলের কোনও ক্ষেত্রের জন্য ভার্চারের পরিবর্তে ভের্বাইনারি ব্যবহার করার ভাগ্য পেয়েছি। এইচটিএইচ
অ্যান্ড্রু টি

724

সুসংবাদটি হ'ল যদি আপনার কেস-সংবেদনশীল কোয়েরি করা দরকার হয় তবে এটি করা খুব সহজ:

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

34
আমি ঠিক এটিই খুঁজছিলাম। আমি যদি পারতাম তবে এটি আরও উচ্চতর হত। যদিও একটি প্রশ্ন, এর পারফরম্যান্সে কী প্রভাব ফেলবে? আমি এটি একটি সীমিত প্রতিবেদনের জিনিসটিতে ব্যবহার করছি, সুতরাং এটি আমার ক্ষেত্রে গুরুত্বপূর্ণ নয়, তবে আমি কৌতূহলী।
অ্যাডউইলি

23
কেন এই উত্তর না? এটিও আমার খুব প্রয়োজন ছিল।
আর্ট জিগেল

7
@ অ্যাডজুইলি যদি কলামটি কোনও সূচকের অংশ হয় তবে আপনি সেই সূচকের উপর নির্ভরশীল প্রশ্নের উপর একটি পারফরম্যান্সের আঘাতের শিকার হবেন। কর্মক্ষমতা বজায় রাখার জন্য, আপনাকে অবশ্যই টেবিলটি পরিবর্তন করতে হবে।
dshin

6
এটি ইউটিএফ -8 স্ট্রিংগুলির জন্য আলাদাভাবে উপস্থাপনা সহ একই অক্ষর যুক্ত কী করবে, যেমন একটি উমলাউট যুক্ত করার জন্য একটি সংমিশ্রিত অক্ষর ব্যবহার করে? এই হল UTF-8 স্ট্রিং সমান হিসাবে গণ্য করা যেতে পারে: convert(char(0x65,0xcc,0x88) using utf8)(অর্থাত eসঙ্গে ¨যোগ করা হয়েছে) এবং convert(char(0xc3,0xab) using utf8)(অর্থাত ë), কিন্তু যোগ BINARYতাদের অসম করতে হবে।
এমভিডিএস

3
পারফরম্যান্সের উদাহরণ হিসাবে: আমার ক্যোয়ারী 3,8 মিমি (নগণ্য) থেকে 1.570 মিমি (এটি প্রায় দেড় সেকেন্ড) পর্যন্ত চলে যায়, 1.8M সারি এপ্রোক্স সহ একটি সারণী জিজ্ঞাসা করছে।
Lluís Suñol

64

ক্রেগ হোয়াইট পোস্ট করা উত্তর, বড় পারফরম্যান্স পেনাল্টি আছে

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

কারণ এটি সূচকগুলি ব্যবহার করে না। সুতরাং, হয় আপনাকে এখানে উল্লেখ করার মতো টেবিলের জোট পরিবর্তন করতে হবে https://dev.mysql.com/doc/refman/5.7/en/case- حساسیت . 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 (- 5.6.43 libmysql ব্যবহার করে)
user10398534

40

= অপারেটর ব্যবহারের পরিবর্তে, আপনি লাইক বা বাইনারি পছন্দ করতে পারেন

// 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 (- 5.6.43 libmysql ব্যবহার করে)
user10398534

17

বিনারি ব্যবহারের আগে একটি সূচক ব্যবহার করতে, আপনার কাছে যদি বড় টেবিল থাকে তবে আপনি এ জাতীয় কিছু করতে পারেন।

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। অতএব সর্বাধিক দৃ solution় সমাধান হ'ল সর্বদা মানটিকে সর্বাধিক নমনীয় চরিত্রের সেটে রূপান্তর করা এবং সেই অক্ষর সংকলনের জন্য বাইনারি কোলেশন ব্যবহার করা।

কেন convertএবং collateমানটিতে এবং কলামটি নয় কেন প্রয়োগ করবেন ?

তুলনা করার আগে আপনি যখন কোনও কলামে কোনও রূপান্তরকারী ফাংশন প্রয়োগ করেন এটি যখন কলামটির জন্য উপস্থিত থাকে তবে ক্যোয়ারী ইঞ্জিনটিকে একটি সূচক ব্যবহার থেকে বাধা দেয়, যা নাটকীয়ভাবে আপনার ক্যোয়ারিকে ধীর করে দিতে পারে। অতএব যেখানেই সম্ভব তার পরিবর্তে মানটি রূপান্তর করা সর্বদা ভাল। যখন দুটি স্ট্রিং মানগুলির মধ্যে একটি তুলনা করা হয় এবং এর মধ্যে একটিতে একটি নির্দিষ্টভাবে নির্দিষ্ট কোলিশ থাকে, কোয়েরি ইঞ্জিনটি কোন মানটিতে প্রয়োগ করা হয় তা নির্বিশেষে সুস্পষ্ট সংগ্রহটি ব্যবহার করবে।

অ্যাকসেন্ট সংবেদনশীলতা

এটি লক্ষণীয় গুরুত্বপূর্ণ যে মাইএসকিএল কেবলমাত্র একটি _ciকোলেশন (যা সাধারণত ডিফল্ট) ব্যবহার করে কলামগুলির ক্ষেত্রে সংবেদনশীল নয় , তবে অ্যাকসেন্ট সংবেদনশীলও বটে। এর অর্থ 'é' = 'e'। বাইনারি কোলেশন (বা binaryঅপারেটর) ব্যবহার স্ট্রিং তুলনা অ্যাকসেন্ট সংবেদনশীল পাশাপাশি কেস সংবেদনশীল করে তুলবে।

কী utf8mb4?

utf8মাইএসকিউএল মধ্যে অক্ষর সেট উপনাম জন্য utf8mb3যা করা হয়েছে সাম্প্রতিক সংস্করণে অবচিত হয়েছে কারণ এটি 4 বাইট অক্ষর (যা মত 🐈 স্ট্রিং এনকোডিং জন্য গুরুত্বপূর্ণ) সমর্থন করে না। আপনি যদি মাইএসকিএল দিয়ে ইউটিএফ 8 অক্ষর এনকোডিং ব্যবহার করতে চান তবে আপনার চরসেটটি ব্যবহার করা উচিত utf8mb4


8

মাইএসকিউএল সংস্করণগুলির জন্য 5.5 এর সমান বা উচ্চতর নীচে রয়েছে।

/Etc/mysql/my.cnf এ যুক্ত করুন

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

অন্যান্য চেষ্টা করা সমস্ত কলিঙ্কগুলি কেস-সংবেদনশীল বলে মনে হয়েছিল, কেবল "utf8_bin" কাজ করেছিল।

এর পরে মাইএসকিএল পুনরায় চালু করতে ভুলবেন না:

   sudo service mysql restart

Http://dev.mysql.com/doc/refman/5.0/en/case- সেনসেটিভিটিভিটিএমএল অনুসারে একটি "ল্যাটিন 1_বিন" রয়েছে।

"Utf8_general_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 (- 5.6.43 libmysql ব্যবহার করে)
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;শুরুতে যুক্ত করা দরকার
অ্যাডিনাস

2

ডিবি স্তরে কোনও পরিবর্তন করার দরকার নেই, এটি আপনাকে কার্যকর করবে এসকিউএল কোয়েরিতে পরিবর্তন করতে হবে।

উদাহরণ -

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

বাইনারি কীওয়ার্ড কেসকে সংবেদনশীল করে তুলবে।


1

মাইএসকিএল ডিফল্টরূপে সংবেদনশীল নয়, ভাষা কোলেশনটিতে পরিবর্তনের চেষ্টা করুন latin1_general_cs

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.