Как я могу искать (без учета регистра) в столбце, используя подстановочный знак LIKE?


289

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

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

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

Как сделать SQL нечувствительным к регистру для этого поиска по шаблону?

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


3
Если вы наткнулись на эту страницу, но ваши настройки MySql действительно работают с этим запросом для Elm или ELM, и вы хотите, чтобы он BINARY
учитывал

Разве это не зависит от сопоставления полей / таблиц? как 'ut8_general_CI'
Юша Алеауб,

Как использовать это sequlize запрос узла?
Аш

MySQL likeдолжен быть нечувствительным к регистру по умолчанию.
Марко Боначи

Ответы:


281
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. 

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


34
На самом деле, если вы добавите COLLATE UTF8_GENERAL_CIопределение столбца, вы можете просто пропустить все эти приемы: он будет работать автоматически. ALTER TABLE trees MODIFY COLUMN title VARCHAR(…) CHARACTER SET UTF8 COLLATE UTF8_GENERAL_CI, Это также перестроит все индексы в этом столбце, чтобы их можно было использовать для запросов без начального «%».
Кассной

1
ALTER TABLE trees ИЗМЕНИТЬ КОЛОННУ title VARCHAR (…) это кажется лучшим способом, большое спасибо ... пусть sql сделает работу
Дэвид Морроу

10
Дружеское напоминание, что это MySQL ответ. Если вы используете PostgreSQL, ILike является решением вышеуказанного вопроса.
Стив

2
@ RajanRawal: пожалуйста, оставьте свой вопрос как вопрос, а не как комментарий. Спасибо.
Quassnoi

1
Это правильный ответ до тех пор, пока ваш исходный сборник был общим, а не мусорным ведром.
Гринольдман

261

Я всегда решал это с помощью ниже:

SELECT * FROM trees WHERE LOWER( trees.title ) LIKE  '%elm%'

47
и испортить использование индекса
Ваш здравый смысл

3
Есть ли в MySQL 5 оператор ILIKE?
Люк Маурер

27
хотя для поиска %% это все равно не имеет значения :)
Ваш здравый смысл

5
@Col. - Следует признать, что это не идеально для индексированных столбцов, но оно будет работать для уже существующей структуры. Я также обнаружил, что поиск без учета регистра чаще выполняется в столбцах, которые в любом случае не индексируются.
cwallenpoole

1
Сортировка по умолчанию уже CI. Итак, настоящая проблема не в этом конкретном вопросе. Но это все еще идеальный ответ в стиле SO.
Ваш здравый смысл

48

Чувствительность к регистру определяется в настройках сопоставления столбцов / таблиц / базы данных. Вы можете выполнить запрос в соответствии с определенным сопоставлением следующим образом:

SELECT *
FROM trees
WHERE trees.`title` LIKE '%elm%' COLLATE utf8_general_ci

например.

(Замените utf8_general_ciна любое сопоставление, которое вы считаете полезным). _ciОзначает нечувствительны к регистру .


1
В MySQL 5.6 я получаю ОШИБКУ 1273 (HY000): Неизвестное сопоставление: 'utf_general_ci' . Я предполагаю, что это сопоставление было удалено из MySQL? utf8_general_ciработает нормально, хотя.
Марк Амери

1
Была такая же проблема. Вы должны либо исправить свой, COLLATEлибо сделать такой простой трюк, как этот ( LOWER()обе ваши строки перед сравнением)
Менелай Коцолларис

В MySQL 5.6+ или MariaDB 10+ вам просто нужно предоставить инструкцию COLLATE перед вашим условием. Так что это работает:SELECT * FROM products WHERE name COLLATE utf8_general_ci LIKE 'AB47TU';
Stamster

41

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

SELECT * FROM <table> WHERE <key> LIKE '%<searchpattern>%'

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

SELECT * FROM <table> WHERE LOWER(<key>) LIKE LOWER('%<searchpattern>%')

3
На самом деле это очень хорошее решение, особенно когда вы сталкиваетесь с COLLATEпроблемами форматирования
Менелай Коцолларис

27

Просто используйте:

"SELECT * FROM `trees` WHERE LOWER(trees.`title`) LIKE  '%elm%'";

Или использовать

"SELECT * FROM `trees` WHERE LCASE(trees.`title`) LIKE  '%elm%'";

Обе функции работают одинаково


15

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

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

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

И для MySQL PDO Альтернатива:

        $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();

6

Я думаю, что этот запрос будет делать поиск без учета регистра:

SELECT * FROM trees WHERE trees.`title` ILIKE '%elm%';

1
Я получаю синтаксическую ошибку в MySQL 5.5 при использовании ILIKE в своих запросах
Steel Brain

18
Это работает только для PostgreSQL; не MySQL. postgresql.org/docs/current/static/functions-matching.html
Мартин Турной

Как уже отмечалось, вопрос был о MySQL, а ответ - о PostgreSQL, и, конечно же, он не работает с MySQL. Я не голосую против, но не могу не задаться вопросом, откуда взялись голоса за повышение ...
silverdr


4

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

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

2
Это очень недооцененный комментарий. Это касается вопроса в целом. Я думаю, что синтаксис alter table также важен, поскольку вопрос может потребовать, чтобы сравнение ограничивалось только одним столбцом.
Брайан Крисман

1

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

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

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

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


Это не совсем так. Это работает только в том случае, если для параметра сортировки установлено значение *_ci«без учета регистра». Поскольку это происходит по умолчанию для всех поддерживаемых наборов символов ( show character set;проверьте это), ответ частично верен :-) Только причина неверна. Это не оператор, который учитывает регистр, это сопоставление по умолчанию.
silverdr

да, я согласен с вами. Это зависит от символа и, тем не менее, если вы работаете с символом * _ci, тогда единственный вариант - использовать двоичный код до условия
where

1
SELECT name 
       FROM gallery 
       WHERE CONVERT(name USING utf8) LIKE _utf8 '%$q%' 
       GROUP BY name COLLATE utf8_general_ci LIMIT 5 

галерея - имя таблицы, имя - столбец в таблице,
user4189641

2
пожалуйста, добавьте некоторые пояснения к своему коду, показывающие, что он делает и как он помогает - это поможет другим в будущем
Наш человек в бананах

0

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

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

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


0

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


0

Вы можете использовать следующий метод

 private function generateStringCondition($value = '',$field = '', $operator = '', $regex = '', $wildcardStart = '', $wildcardEnd = ''){
        if($value != ''){
            $where = " $field $regex '$wildcardStart".strtolower($value)."$wildcardEnd' ";

            $searchArray = explode(' ', $value);

            if(sizeof($searchArray) > 1){

                foreach ($searchArray as $key=>$value){
                    $where .="$operator $field $regex '$wildcardStart".strtolower($value)."$wildcardEnd'";
                }

            }

        }else{
            $where = '';
        }
        return $where;
    }

используйте этот метод, как показано ниже

   $where =  $this->generateStringCondition($yourSearchString,  'LOWER(columnName)','or', 'like',  '%', '%');
  $sql = "select * from table $where";

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.