Як я можу шукати (нечутливий до регістру) у стовпці, використовуючи підстановку LIKE?


289

Я озирнувся навколо деяких і не знайшов того, що я був, тому так іде.

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

Це добре працює, але не, якщо дерево названо Elm або ELM тощо.

Як зробити так, щоб регістр SQL був нечутливим для цього пошукового запиту?

Я використовую MySQL 5 та Apache.


3
Якщо ви натрапили на цій сторінці , але ваші налаштування MySql DO роботи по цьому запиту для Elm або ELM , і ви хочете, щоб це було відчутно до регістру, см , BINARYнаприклад , як тут: stackoverflow.com/questions/7857669 / ...
joshuahedlund

Чи не це залежить від порівняння поля / таблиці? як 'ut8_general_CI'
Yousha Aleayoub

Як використовувати його послідовний запит на вузол?
Аш

likeЗа замовчуванням MySQL має бути нечутливим до регістру.
Марко Боначі

Відповіді:


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. Це також відновить будь-які індекси в цьому стовпці, щоб їх можна було використовувати для запитів, не ведучи "%".
Quassnoi

1
АЛЬТЕР ТАБЛИВА ДРУГИ МОДИФІКАЦІЯ СТОЛІН ВАРХАР (…) це здається найкращим способом, спасибі велике ... дозвольте sql виконати роботу
Девід Морроу

10
Дружнє нагадування, що це відповідь mysql. Якщо ви використовуєте PostgreSQL, ILike - це рішення вищезазначеного питання.
Стів

2
@RajanRawal: будь ласка, опублікуйте своє питання як питання, а не коментар. Дякую.
Quassnoi

1
Це правильна відповідь до тих пір, оскільки ваш оригінальний помірник був загальним, а не бін.
greenoldman

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 я отримую ERROR 1273 (HY000): Невідоме зіставлення: 'utf_general_ci' . Я б здогадався, що це порівняння було видалено з MySQL? utf8_general_ciпрацює добре, хоча.
Марк Амері

1
Мав те саме питання. Вам або доведеться виправити COLLATEабо зробити такий простий трюк, як цей ( LOWER()обидва ваші рядки перед порівнянням)
Menelaos Kotsollaris,

У 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%')");

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

        $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. Я не голосую за це, але не можу не
задатися

5

використання ILIKE

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

це працювало для мене !!


9
MySQL не підтримує ILIKE.
ttarchala

3
Це працює для PostgreSQL, питання стосувалося MySQL.
Telmo Trooper

4

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

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

2
Це дуже занижений коментар. Це питання стосується найбільш загального характеру. Я думаю, що синтаксис таблиці змін також є важливим, оскільки питання може вимагати порівняння, обмеженого лише одним стовпцем.
Брайан Крісман

1

добре в mysql 5.5, як оператор нечутливий ... так що, якщо вашою долею є в'яз або ELM, або Elm або eLM або будь-який інший, і ви використовуєте як "% elm%", він перерахує всі відповідні значення.

Я не можу сказати про більш ранні версії mysql.

Якщо ви переходите в Oracle, ви хочете працювати як з урахуванням регістру, тому якщо ви введете на зразок '% elm%', він піде лише на це і проігнорує великі регістри.

Дивно, але так воно і є :)


Це не зовсім так. Це працює таким чином, лише якщо встановлено порівняння *_ci, яке означає "нечутливий до регістру". Оскільки це за замовчуванням для всіх підтримуваних наборів символів (питання, show character set;щоб перевірити це) - відповідь частково правдива :-) Тільки причина невірна. Не оператор є нечутливим до регістру, це зіставлення за замовчуванням.
сріблодр

так, я з вами згоден Це залежить від характеру, і все-таки, якщо ви працюєте з символом * _ci, тоді єдиним варіантом є використання двійкового перед тим, де стаття
user21546

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.