Saya memiliki fungsi yang mengembalikan lima karakter dengan case campuran. Jika saya melakukan kueri pada string ini, ia akan mengembalikan nilai terlepas dari kasusnya.
Bagaimana cara membuat MySQL string kueri case sensitif?
Saya memiliki fungsi yang mengembalikan lima karakter dengan case campuran. Jika saya melakukan kueri pada string ini, ia akan mengembalikan nilai terlepas dari kasusnya.
Bagaimana cara membuat MySQL string kueri case sensitif?
Jawaban:
http://dev.mysql.com/doc/refman/5.0/id/case-sensitivity.html
Kumpulan karakter dan susunan default adalah latin1 dan latin1_swedish_ci, jadi perbandingan string non-biner tidak peka huruf besar-kecil. Ini berarti bahwa jika Anda mencari dengan col_name LIKE 'a%', Anda mendapatkan semua nilai kolom yang dimulai dengan A atau a. Untuk menjadikan case pencarian ini sensitif, pastikan bahwa salah satu operan memiliki collation case sensitive atau binary. Misalnya, jika Anda membandingkan kolom dan string yang keduanya memiliki set karakter latin1, Anda dapat menggunakan operator COLLATE untuk menyebabkan salah satu operan memiliki susunan latin1_general_cs atau 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
Jika Anda ingin kolom selalu diperlakukan dengan case-sensitive, mendeklarasikannya dengan case-sensitive atau binary collation.
SELECT 'email' COLLATE utf8_bin = 'Email'
Berita baiknya adalah jika Anda perlu membuat kueri yang peka terhadap huruf besar-kecil, mudah dilakukan:
SELECT * FROM `table` WHERE BINARY `column` = 'value'
convert(char(0x65,0xcc,0x88) using utf8)
(yaitu e
dengan ¨
ditambahkan) dan convert(char(0xc3,0xab) using utf8)
(yaitu ë
), tetapi menambahkan BINARY
akan membuat mereka tidak sama.
Jawaban yang diposting oleh Craig White, memiliki penalti kinerja yang besar
SELECT * FROM `table` WHERE BINARY `column` = 'value'
karena tidak menggunakan indeks. Jadi, Anda harus mengubah susunan tabel seperti disebutkan di sini https://dev.mysql.com/doc/refman/5.7/id/case-sensitivity.html .
ATAU
Perbaikan termudah, Anda harus menggunakan BINARY dari nilai.
SELECT * FROM `table` WHERE `column` = BINARY 'value'
Misalnya.
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 |
+----+-------------+--------+------+---------------+------+---------+------+--------+-------------+
VS
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 baris dalam set (0,00 dtk)
Alih-alih menggunakan operator =, Anda mungkin ingin menggunakan LIKE atau 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'
Ini akan mengambil 'a' dan bukan 'A' dalam kondisinya
Untuk menggunakan indeks sebelum menggunakan BINARY, Anda bisa melakukan sesuatu seperti ini jika Anda memiliki tabel besar.
SELECT
*
FROM
(SELECT * FROM `table` WHERE `column` = 'value') as firstresult
WHERE
BINARY `column` = 'value'
Subquery akan menghasilkan subset case-insensitive yang sangat kecil yang kemudian Anda pilih satu-satunya yang cocok dengan case-sensitive.
Cara paling benar untuk melakukan perbandingan string peka huruf besar-kecil tanpa mengubah susunan kolom yang ditanyakan adalah dengan secara eksplisit menentukan rangkaian karakter dan susunan untuk nilai yang dibandingkan dengan kolom tersebut.
select * from `table` where `column` = convert('value' using utf8mb4) collate utf8mb4_bin;
binary
?Menggunakan binary
operator tidak disarankan karena membandingkan byte aktual dari string yang disandikan. Jika Anda membandingkan byte sebenarnya dari dua string yang disandikan menggunakan karakter yang berbeda, set dua string yang harus dianggap sama mereka mungkin tidak sama. Sebagai contoh jika Anda memiliki kolom yang menggunakan latin1
set karakter, dan set karakter server / sesi Anda utf8mb4
, maka ketika Anda membandingkan kolom dengan string yang mengandung aksen seperti 'café' itu tidak akan cocok dengan baris yang berisi string yang sama! Hal ini karena di latin1
é dikodekan sebagai byte 0xE9
tetapi utf8
itu adalah dua byte: 0xC3A9
.
convert
juga collate
?Collations harus cocok dengan set karakter. Jadi jika server atau sesi Anda diatur untuk menggunakan latin1
set karakter yang harus Anda gunakan collate latin1_bin
tetapi jika set karakter utf8mb4
Anda harus Anda gunakan collate utf8mb4_bin
. Oleh karena itu solusi yang paling kuat adalah dengan selalu mengubah nilai menjadi set karakter yang paling fleksibel, dan menggunakan susunan biner untuk set karakter itu.
convert
dan collate
ke nilai dan bukan kolom?Ketika Anda menerapkan fungsi transformasi apa pun ke kolom sebelum membuat perbandingan, itu mencegah mesin kueri dari menggunakan indeks jika ada untuk kolom, yang secara dramatis dapat memperlambat permintaan Anda. Oleh karena itu selalu lebih baik untuk mengubah nilai daripada jika memungkinkan. Ketika perbandingan dilakukan antara dua nilai string dan salah satunya memiliki susunan yang ditentukan secara eksplisit, mesin kueri akan menggunakan susunan eksplisit, terlepas dari nilai mana itu diterapkan.
Penting untuk dicatat bahwa MySql tidak hanya case-insensitive untuk kolom menggunakan _ci
collation (yang biasanya merupakan default), tetapi juga accent insensitive. Ini artinya 'é' = 'e'
. Menggunakan susunan biner (atau binary
operator) akan membuat perbandingan string menjadi peka aksen dan juga peka huruf besar-kecil.
utf8mb4
?Set utf8
karakter di MySql adalah alias utf8mb3
yang sudah tidak digunakan lagi dalam versi terbaru karena tidak mendukung karakter 4 byte (yang penting untuk pengkodean string seperti 🐈). Jika Anda ingin menggunakan pengkodean karakter UTF8 dengan MySql maka Anda harus menggunakan utf8mb4
charset.
Berikut ini untuk versi MySQL yang sama dengan atau lebih tinggi dari 5.5.
Tambahkan ke /etc/mysql/my.cnf
[mysqld]
...
character-set-server=utf8
collation-server=utf8_bin
...
Semua pemeriksaan lain yang saya coba tampaknya tidak peka huruf besar-kecil, hanya "utf8_bin" yang berfungsi.
Jangan lupa untuk me-restart mysql setelah ini:
sudo service mysql restart
Menurut http://dev.mysql.com/doc/refman/5.0/id/case-sensitivity.html ada juga "latin1_bin".
"Utf8_general_cs" tidak diterima oleh startup mysql. (Saya membaca "_cs" sebagai "case-sensitive" - ???).
Anda dapat menggunakan BINARY untuk case sensitif seperti ini
select * from tb_app where BINARY android_package='com.Mtime';
sayangnya sql ini tidak dapat menggunakan indeks, Anda akan mengalami masalah kinerja pada kueri yang bergantung pada indeks itu
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 |
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+
Untungnya, saya punya beberapa trik untuk menyelesaikan masalah ini
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 |
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+
Luar biasa!
Saya berbagi dengan Anda, kode dari fungsi yang membandingkan kata sandi:
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;
di awal
Tidak perlu mengubah apa pun pada tingkat DB, cukup Anda harus mengubah SQL Query itu akan berhasil.
Contoh -
"SELECT * FROM <TABLE> where userId = '" + iv_userId + "' AND password = BINARY '" + iv_password + "'";
Kata kunci biner akan membuat case sensitif.