У меня есть функция, которая возвращает пять символов со смешанным случаем. Если я сделаю запрос в этой строке, он вернет значение независимо от случая.
Как сделать строковые запросы MySQL чувствительными к регистру?
http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html
По умолчанию набор символов и сортировка - latin1 и latin1_swedish_ci, поэтому неважные сравнения строк по умолчанию нечувствительны к регистру. Это означает, что при поиске с col_name LIKE 'a%' вы получаете все значения столбцов, начинающиеся с A или a. Чтобы сделать этот регистр чувствительным, убедитесь, что один из операндов имеет чувствительную к регистру или двоичную сортировку. Например, если вы сравниваете столбец и строку, у которой есть набор символов latin1, вы можете использовать оператор COLLATE, чтобы заставить либо операнд иметь сортировку latin1_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 * FROM `table` WHERE BINARY `column` = 'value'
Вместо использования оператора =, вы можете использовать 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'
В своем условии
это займет 'a', а не 'A'Чтобы использовать индекс перед использованием BINARY, вы можете сделать что-то подобное, если у вас большие таблицы.
SELECT
*
FROM
(SELECT * FROM `table` WHERE `column` = 'value') as firstresult
WHERE
BINARY `column` = 'value'
Подзапрос привел бы к действительно маленькому не зависящему от регистра подмножеству, из которого вы затем выбираете единственное зависящее от регистра соответствие.
Отправленный ответ Крейг Уайт, имеет большой штраф за производительность
SELECT * FROM `table` WHERE BINARY `column` = 'value'
потому что он не использует индексы. Таким образом, либо вам нужно изменить сортировку таблицы, как упоминание здесь https://dev.mysql.com/doc/refman/5.7/en/case-sensitivity.html.
ИЛИ
Самое простое исправление, вы должны использовать BINARY значения.
SELECT * FROM `table` WHERE `column` = BINARY 'value'
Eg.
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 строка в наборе (0,00 с)
Ниже приведены версии 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-sensitivity.html есть также "latin1_bin".
"utf8_general_cs" не был принят при запуске mysql. (Я читал "_cs" как "чувствительный к регистру" -???).
Вы можете использовать BINARY для чувствительности к регистру, например,
select * from tb_app where BINARY android_package='com.Mtime';
К сожалению, этот sql не может использовать индекс, вы пострадали от удара по запросам, зависящим от этого индекса
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 |
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+
Нет необходимости что-либо менять на уровне DB, просто вы должны внести изменения в SQL Query, это сработает.
Пример -
"SELECT * FROM <TABLE> where userId = '" + iv_userId + "' AND password = BINARY '" + iv_password + "'";
Двоичное ключевое слово сделает регистр чувствительным.
Как правило, так выглядит ваш запрос LIKE (вы видите, что я там сделал;-)):
SELECT * FROM WHERE LIKE '%%'
Теперь, чтобы сделать регистр без учета регистра, вы можете использовать функцию LOWER():
SELECT * FROM WHERE LOWER() LIKE LOWER ('%%');
Это поможет вам избежать попадания ваших рук в формат COLLATE и т.д. Вы знаете, что я говорю?
Отлично!
Я разделяю с вами код из функции, которая сравнивает пароли:
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;
в начале
mysql по умолчанию не чувствителен к регистру, попробуйте изменить настройку языка на latin1_general_cs