Сравнение строк без учета регистра. Mysql - Как я могу искать(без учета регистра)в столбце с использованием шаблона LIKE

case-insensitive (12)

Я огляделся по сторонам и не нашел, что мне нужно, так вот.

SELECT * FROM trees WHERE trees.`title` LIKE "%elm%"

Это работает отлично, но не если дерево называется Elm или ELM и т. Д. ...

Как сделать SQL-регистр незаметным для этого поиска в wild-card?

Я использую MySQL 5 и Apache.

Answers

Я делаю что-то подобное.

Получение значений в нижнем регистре и MySQL делает все остальное

$string = $_GET["string"]; mysqli_query($con,"SELECT * FROM table_name WHERE LOWER(column_name) LIKE LOWER("%$string%")");

И для MySQL PDO Alternative:

$string = $_GET["string"]; $q = "SELECT * FROM table_name WHERE LOWER(column_name) LIKE LOWER(?);"; $query = $dbConnection->prepare($q); $query->bindValue(1, "%$string%", PDO::PARAM_STR); $query->execute();

SELECT * FROM trees WHERE trees.`title` COLLATE UTF8_GENERAL_CI LIKE "%elm%"

Фактически, если вы добавите COLLATE UTF8_GENERAL_CI в определение вашего столбца, вы можете просто опустить все эти трюки: он будет работать автоматически.

ALTER TABLE trees MODIFY COLUMN title VARCHAR(…) CHARACTER SET UTF8 COLLATE UTF8_GENERAL_CI.

Это также приведет к восстановлению любых индексов в этом столбце, чтобы они могли использоваться для запросов без указания «%»,

Вам не нужно ALTER любую таблицу. Просто используйте следующие запросы перед запросом SELECT который вы хотите использовать подстановочный знак:

Set names `utf8`; SET COLLATION_CONNECTION=utf8_general_ci; SET CHARACTER_SET_CLIENT=utf8; SET CHARACTER_SET_RESULTS=utf8;

хорошо в mysql 5.5, как и оператор, нечувствителен... поэтому, если ваша долина - это вяза или ELM или Elm или eLM или любой другой, и вы используете «% elm%», он отобразит все соответствующие значения.

Я не могу сказать о более ранних версиях mysql.

Если вы идете в Oracle, например, работайте с учетом регистра, поэтому, если вы наберете «% elm%», он пойдет только для этого и игнорирует верхние регионы.

Странно, но так оно и есть:)

Это пример простого запроса LIKE:

SELECT * FROM

WHERE LIKE "%%"

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

SELECT * FROM

WHERE LOWER() LIKE LOWER("%%")

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

Вы должны настроить правильную кодировку и сопоставление для своих таблиц.

Кодирование таблицы должно отражать фактическое кодирование данных. Какова ваша кодировка данных?

Чтобы увидеть кодировку таблицы, вы можете запустить запрос SHOW CREATE TABLE tablename

Добавить.toLowerCase() после referrer . Этот метод превращает строку в строчную строку. Затем используйте.indexOf() используя ral вместо Ral .

If (referrer.toLowerCase().indexOf("ral") === -1) {

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

If (!/Ral/i.test(referrer)) { // ^i = Ignore case flag for RegExp

Фасет ctype позволяет относительно легко организовать сравнение строк без учета регистра на основе сравнения отдельных символов. Приведенная ниже версия не оптимальна, но по крайней мере она верна. В ней используется практически тот же принцип, что и прежде: строки сравниваются алгоритмом lexicographical_ compare, а отдельные символы сравниваются после приведения к верхнему регистру. Впрочем, на этот раз вместо глобальной переменной используется объект локального контекста. Кстати говоря, сравнение после приведения обоих символов к верхнему регистру не всегда дает тот же результат, что и после приведения к нижнему регистру. Например, во французском языке в символах верхнего регистра принято опускать диакритические знаки, вследствие чего вызов toupper во французском локальном контексте может приводить к потере информации: символы "ё" и "е" преобразуются в один символ верхнего регистра "Е". В этом случае при сравнении на базе функции toupper символы "ё" и "е" будут считаться одинаковыми, а при сравнении на базе tolower они будут считаться разными. Какой из ответов правилен? Вероятно, второй, но на самом деле все зависит от языка, национальных обычаев и специфики приложения.

:public std::binary_function {

const std::ctype & ct:

lt_char(const std::ctype & c):ct(c) {}

bool operator() (char x. char y) const {

return ct.toupper(x)

std::locale loc;

const std::ctype & ct;

lt_str_l(const std::locale& L = std::locale::classic())

:loc(L),ct(std::use_facet<:ctype>(loc)) {}

bool operator()(const std::string& x, const std::string& y) const {

return std::lexicographical_compare(x.begin(),.x.end(),

y.begin(),y.end(), lt_char(ct));

Данное решение не оптимально; оно работает медленнее, чем могло бы работать. Проблема чисто техническая: функция toupper вызывается в цикле, а Стандарт С++ требует, чтобы эта функция была виртуальной. Некоторые оптимизаторы выводят вызов виртуальной функции из цикла, но чаще этого не происходит. Циклические вызовы виртуальных функций нежелательны.

В данном случае тривиального решения не существует. Возникает соблазнительная мысль - воспользоваться одной из функций объекта ctype:

const char* ctype::toupper(char* f, char* i) const

Эта функция изменяет регистр символов в интервале . К сожалению, для наших целей этот интерфейс не подходит. Чтобы воспользоваться этой функцией для сравнения двух строк, необходимо скопировать обе строки в буферы и затем преобразовать их содержимое к верхнему регистру. Но откуда возьмутся эти буферы? Они не могут быть массивами фиксированного размера (неизвестно, каким должен быть максимальный размер), а динамические массивы потребуют дорогостоящего выделения памяти.

Альтернативное решение заключается в однократном преобразовании каждого символа с кэшированием результата. Такое решение недостаточно универсально-в частности, при использовании 32-разрядных символов UCS-4 оно абсолютно неработоспособно. С другой стороны, при работе с типом char (8-разрядным в большинстве систем) идея хранения 256 байт дополнительных данных в объекте функции сравнения выглядит вполне реально.

struct lt_str_2:

public std::binary_function {

const char* tab;

lt_char(const char* t):tab(t) {}

bool operator() (char x, char y) const {

return tab

char tab;

lt_str_2(const std::locale& L = std:.-locale::classic()){

const std::ctype & ct = std::use_facet<:ctype>(L);

for(int i = CHAR_MIN;i

ct.toupper(tab. tab+(CHAR_MAX-CHAR_MIN+1));

bool operator()(const std::string& x. const std::string& y) const {

return std::lexicographical_compare(x.begin(),x.end(),

y.begin(),y.end(), lt_char(tab));

Как видите, различия между lt_str_1 и lt_str_2 не так уж велики. В первом случае используется объект функции сравнения символов, использующий фасет ctype напрямую, а во втором случае - объект функции сравнения с таблицей заранее вычисленных преобразований символов к верхнему регистру. Второе решение уступает первому, если создать объект функции lt_str_2, воспользоваться им для сравнения нескольких коротких строк и затем уничтожить. С другой стороны, при обработке больших объемов данных lt_str_2 работает значительно быстрее lt_str_1. В моих тестах превосходство было более чем двукратным: при использовании lt_str_l сортировка списка из 23 791 слова заняла 0,86 секунды, а при использовании lt_str_2 понадобилось только 0,4 секунды.

Итак, что же мы узнали?

Класс строки без учета регистра символов реализуется на неправильном уровне абстракции. Обобщенные алгоритмы стандартной библиотеки С++ параметризуются, и этот факт следует использовать.

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

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