Как я могу сделать строковое сравнение SQL-запросов на MySQL?

У меня есть функция, которая возвращает пять символов со смешанным случаем. Если я сделаю запрос в этой строке, он вернет значение независимо от случая.

Как сделать строковые запросы MySQL чувствительными к регистру?

Ответ 1

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

Если вы хотите, чтобы столбец всегда обрабатывался с учетом регистра чувствительности к регистру, объявите его с помощью чувствительной к регистру или двоичной сортировки.

Ответ 2

Хорошей новостью является то, что если вам нужно сделать запрос с учетом регистра, это очень легко сделать:

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

Ответ 3

Вместо использования оператора =, вы можете использовать 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'

Ответ 4

Отправленный ответ Крейг Уайт, имеет большой штраф за производительность

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 с)

Ответ 5

Чтобы использовать индекс перед использованием BINARY, вы можете сделать что-то подобное, если у вас большие таблицы.

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

Подзапрос привел бы к действительно маленькому не зависящему от регистра подмножеству, из которого вы затем выбираете единственное зависящее от регистра соответствие.

Ответ 6

Ниже приведены версии 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" как "чувствительный к регистру" -???).

Ответ 7

Вы можете использовать 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 |
+----+-------------+--------+------------+------+---------------------------+---------------------------+---------+-------+------+----------+-----------------------+  

Ответ 8

Отлично!

Я разделяю с вами код из функции, которая сравнивает пароли:

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;

Ответ 9

Нет необходимости что-либо менять на уровне DB, просто вы должны внести изменения в SQL Query, это сработает.

Пример -

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

Двоичное ключевое слово сделает регистр чувствительным.

Ответ 10

mysql по умолчанию не чувствителен к регистру, попробуйте изменить настройку языка на latin1_general_cs

Ответ 11

Как правило, так выглядит ваш запрос LIKE (вы видите, что я там сделал;-)):

SELECT * FROM WHERE LIKE '%%'

Теперь, чтобы сделать регистр без учета регистра, вы можете использовать функцию LOWER():

SELECT * FROM WHERE LOWER() LIKE LOWER ('%%');

Это поможет вам избежать попадания ваших рук в формат COLLATE и т.д. Вы знаете, что я говорю?

Ответ 12

Самый правильный способ выполнить сравнение строк с учетом регистра без изменения параметров сортировки запрашиваемого столбца - это явно указать набор символов и параметры сопоставления для значения, с которым сравнивается столбец.

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

Почему бы не использовать binary?

Использование binary оператора нецелесообразно, поскольку он сравнивает фактические байты кодированных строк. Если вы сравните фактические байты двух строк, закодированных с использованием разных наборов символов, две строки, которые следует считать одинаковыми, могут быть не равны. Например, если у вас есть столбец, который использует набор символов latin1, а ваш набор символов сервера/сеанса имеет значение utf8mb4, то при сравнении столбца со строкой, содержащей акцент, такой как 'café', он не будет совпадать со строками, содержащими эту же строку ! Это связано с тем, что в latin1 кодируется как байт 0xE9 а в utf8 это два байта: 0xC3A9.

Зачем использовать convert а также collate?

Сопоставления должны соответствовать набору символов. Поэтому, если ваш сервер или сеанс настроен на использование набора символов latin1 вы должны использовать collate latin1_bin но если ваш набор символов - utf8mb4 вы должны использовать collate utf8mb4_bin. Поэтому наиболее надежное решение - всегда преобразовывать значение в наиболее гибкий набор символов и использовать двоичное сопоставление для этого набора символов.

Зачем применять convert и collate для значения, а не столбца?

Когда вы применяете любую функцию преобразования к столбцу перед выполнением сравнения, он не позволяет обработчику запросов использовать индекс, если он существует для столбца, что может значительно замедлить ваш запрос. Поэтому всегда лучше преобразовывать значение, где это возможно. Когда сравнение выполняется между двумя строковыми значениями, и одно из них имеет явно заданное сопоставление, механизм запросов будет использовать явное сопоставление независимо от того, к какому значению оно применяется.

Акцент Чувствительность

Важно отметить, что MySql не только нечувствителен к регистру столбцов, использующих _ci сортировки _ci (как правило, по умолчанию), но также нечувствителен к акценту. Это означает, что 'é' = 'e'. Использование двоичного сопоставления (или binary оператора) сделает сравнения строк чувствительными к акценту, а также к регистру.

Что такое utf8mb4?

Набор символов utf8 в MySql - это псевдоним utf8mb3 который в последних версиях устарел, поскольку он не поддерживает 4-байтовые символы (что важно для кодирования строк типа 🐈). Если вы хотите использовать кодировку символов UTF8 с MySql, вам следует использовать кодировку utf8mb4.