Как я могу искать (без учета регистра) в столбце, используя подстановочный знак 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.