420

I looked around some and didn't find what I was after so here goes.

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

This works fine, but not if the tree is named Elm or ELM etc...

How do I make SQL case insensitive for this wild-card search?

I'm using MySQL 5 and Apache.

Muntasir
  • 798
  • 1
  • 14
  • 24
David Morrow
  • 8,965
  • 4
  • 29
  • 24

16 Answers16

426

I've always solved this using lower:

SELECT * FROM trees WHERE LOWER( trees.title ) LIKE  '%elm%'
cwallenpoole
  • 79,954
  • 26
  • 128
  • 166
  • 3
    Does MySQL 5 have an ILIKE operator? – Luke Maurer May 20 '10 at 18:42
  • 35
    though for the %% search it doesn't matter anyway :) – Your Common Sense May 20 '10 at 18:43
  • @Luke Mysql don't need it. As it's collation responsibility. – Your Common Sense May 20 '10 at 18:44
  • (Wait, I thought everything in MySQL is case insensitive? Or is string equality case insensitive but matching case sensitive?!) – Luke Maurer May 20 '10 at 18:44
  • (Ah. Okay, back to things I actually know anything about :-) ) – Luke Maurer May 20 '10 at 18:46
  • 6
    @Col. -- Admittedly, this is less than ideal for indexed columns, but it will work for a structure which is already in place. I've also found that case-insensitive searches are more often on columns which are not indexed anyway. – cwallenpoole May 20 '10 at 18:48
  • perfect! exactly want i wanted, i knew sql would have something like that, just didnt know. many thanks... – David Morrow May 20 '10 at 18:51
  • 1
    Default collation is already CI. So, the real problem not in this particular question. But it's still perfect SO-style answer. – Your Common Sense May 20 '10 at 18:56
  • Exactly what I wanted as well. Which trumps spoiling index use :) – Henley Jan 11 '14 at 19:01
  • 3
    Concerning Indexes, if you you really need to optimize a case-insensitive search, then you would have an extra column on your table, which contains the target field ALREADY mapped to lowercase (or uppercase), then you would create an index on that column. The downside is that you now have a larger DB which is not normalized. But your searches are fast. – Martín Valdés de León Sep 14 '16 at 13:09
  • what makes you think the data will be minor case, this is less than ideal solution – Phil Jan 12 '17 at 09:01
  • I just tried this using LOWER like this was incredibly slow went from almost no time to 0.5 seconds... – jxwd Apr 08 '22 at 13:08
  • Unfortunately, this does not work for binary data (e.g. blob with serialized data). – Jan Potužník Apr 14 '22 at 11:03
  • UPPER and LOWER have other problems as well... Read this entertaining post by SO legend Jon Skeet for more info: https://codeblog.jonskeet.uk/2009/11/02/omg-ponies-aka-humanity-epic-fail/ (Search for 'Turkey' to get to the part where he discusses issues with UPPER/LOWER) – Stijn de Witt May 03 '22 at 14:15
322
SELECT  *
FROM    trees
WHERE   trees.`title` COLLATE UTF8_GENERAL_CI LIKE '%elm%'

Actually, if you add COLLATE UTF8_GENERAL_CI to your column's definition, you can just omit all these tricks: it will work automatically.

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

This will also rebuild any indexes on this column so that they could be used for the queries without leading '%'

Amr Eladawy
  • 4,193
  • 7
  • 34
  • 52
Quassnoi
  • 413,100
  • 91
  • 616
  • 614
  • that works too, is this more correct way of doing things? there is a possibility this will be localized so is using the encoding better than lower? – David Morrow May 20 '10 at 18:55
  • 37
    Actually, if you add `COLLATE UTF8_GENERAL_CI` to your column's definition, you can just omit all these tricks: it will work automatically. `ALTER TABLE trees MODIFY COLUMN title VARCHAR(…) CHARACTER SET UTF8 COLLATE UTF8_GENERAL_CI`. This will also rebuild any indexes on this column so that they could be used for the queries without leading '%'. – Quassnoi May 20 '10 at 18:58
  • 1
    ALTER TABLE trees MODIFY COLUMN title VARCHAR(…) this seems the best way, thanks much... let sql do the work – David Morrow May 20 '10 at 19:10
  • 14
    Friendly reminder that this is a mysql answer. If you're using PostgreSQL, ILike is the solution to the above question. – Steve Sep 06 '13 at 05:57
  • `latin1_general_ci` for `latin1` see https://dev.mysql.com/doc/refman/5.0/en/charset-mysql.html – Sergiy Salyuk Jul 28 '15 at 20:03
  • 1
    This is correct answer as long, as your original collate was general, not bin. – greenoldman Aug 06 '16 at 11:48
  • How if latin1_general_ci ?, this work or not ? – M. Pancadewa Mar 18 '21 at 00:04
  • @MPancadewa: I'm not quite sure what it is your asking, but `_ci` in the collation name means "case insensitive". – Quassnoi Mar 18 '21 at 01:57
  • Unfortunately, this does not work for binary data (e.g. blob with serialized data). – Jan Potužník Apr 14 '22 at 11:04
  • 2
    **IMPORTANT** MySQL's `UTF8` is **NOT** UTF8. It's a broken, MySQL proprietary encoding that has max 3 bytes. Real UTF8 supports [up to 4 bytes](https://stijndewitt.com/2014/08/09/max-bytes-in-a-utf-8-char/). Do **NOT** use any MySQL 'UTF8' encodings or collations ever! Instead, use `UTF8MB4`, which MySQL added later to represent the encoding the rest of the world calls `UTF8`. Confusing, I know. But this WILL come to haunt you! Research this or be bitten by it. Quick test: Try to insert an emoji like ❤️. If you use MySQL `UTF8` it will fail. If you use MySQL `UTF8MB4` it works as intended. – Stijn de Witt May 03 '22 at 14:27
54

This is the example of a simple LIKE query:

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

Now, case-insensitive using LOWER() func:

SELECT * FROM <table> WHERE LOWER(<key>) LIKE LOWER('%<searchpattern>%')
  • 4
    Actually this is a pretty nice solution especially when you are faced with `COLLATE` format issues – Menelaos Kotsollaris Sep 18 '15 at 15:03
  • Great! I was about to write this answer :) It is important to use the same function on both sides, since collation make break things, so this assures, both sides are processed in the same manner (it does not matter how, it is only important that both are the same!) – estani Aug 01 '22 at 15:43
54

The case sensitivity is defined in the columns / tables / database collation settings. You can do the query under a specific collation in the following way:

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

for instance.

(Replace utf8_general_ci with whatever collation you find useful). The _ci stands for case insensitive.

Martin Tournoij
  • 26,737
  • 24
  • 105
  • 146
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • 1
    In MySQL 5.6 I get *ERROR 1273 (HY000): Unknown collation: 'utf_general_ci'*. I'd guess this collation has been removed from MySQL? `utf8_general_ci` works fine, though. – Mark Amery Apr 22 '14 at 13:48
  • 1
    Had the same issue. You either have to fix your `COLLATE` or do a simple trick like [this one](http://stackoverflow.com/a/24844856/1373465)(`LOWER()` both of your strings before comparison) – Menelaos Kotsollaris Sep 18 '15 at 15:06
  • 1
    In MySQL 5.6+ or MariaDB 10+ you just need to supply COLLATE instruction before your condition. So this works: `SELECT * FROM products WHERE name COLLATE utf8_general_ci LIKE 'AB47TU';` – stamster Jul 17 '17 at 10:58
50

Simply use :

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

Or Use

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

Both functions works same

Vi8L
  • 958
  • 10
  • 12
17

I'm doing something like that.

Getting the values in lowercase and MySQL does the rest

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

And For 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();
Dave Doga Oz
  • 1,238
  • 1
  • 10
  • 19
13

use ILIKE

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

it worked for me !!

ABS zarzis
  • 187
  • 2
  • 7
11

Non-binary string comparisons (including LIKE) are case insensitive by default in MySql: https://dev.mysql.com/doc/refman/en/case-sensitivity.html

Marko Bonaci
  • 5,622
  • 2
  • 34
  • 55
8

I think this query will do a case insensitive search:

SELECT * FROM trees WHERE trees.`title` ILIKE '%elm%';
Paulo Tomé
  • 1,910
  • 3
  • 18
  • 27
cgupta
  • 307
  • 3
  • 4
  • 1
    I get syntax error on mysql 5.5 while using ILIKE in my queries – Steel Brain May 04 '14 at 13:49
  • 24
    This works only for PostgreSQL; not MySQL. http://www.postgresql.org/docs/current/static/functions-matching.html – Martin Tournoij Jun 30 '14 at 06:45
  • 1
    As noted already, the question was about MySQL and the answer is about PostgreSQL and sure as hell doesn't work with MySQL. I don't down-vote it but can't help wondering where the up-votes come from... – silverdr Jan 24 '18 at 10:30
6

You don't need to ALTER any table. Just use the following queries, prior to the actual SELECT query that you want to use the wildcard:

    set names `utf8`;
    SET COLLATION_CONNECTION=utf8_general_ci;
    SET CHARACTER_SET_CLIENT=utf8;
    SET CHARACTER_SET_RESULTS=utf8;
Lopofsky
  • 518
  • 6
  • 15
  • 2
    This is a very underrated comment. It addresses the question most generally. I do think the alter table syntax is important too, as the question may want the comparison limited to only that one column. – Brian Chrisman Aug 10 '18 at 19:39
3

well in mysql 5.5 , like operator is insensitive...so if your vale is elm or ELM or Elm or eLM or any other , and you use like '%elm%' , it will list all the matching values.

I cant say about earlier versions of mysql.

If you go in Oracle , like work as case-sensitive , so if you type like '%elm%' , it will go only for this and ignore uppercases..

Strange , but this is how it is :)

simplifiedDB
  • 164
  • 9
  • 2
    This isn't entirely true. It works that way only if the collation is set to `*_ci`, which stands for "case insensitive". As this happens to be default for all supported character sets (issue `show character set;` to check this) - the answer is partially true :-) Only the reason is incorrect. It is not the operator that is case insensitive, it is the default collation that is. – silverdr Jan 24 '18 at 10:45
  • 1
    yes m agree with you . It depends on character and still if you are in production with *_ci character then only option is to use binary before where clause – simplifiedDB Jan 27 '18 at 11:38
2
SELECT name 
       FROM gallery 
       WHERE CONVERT(name USING utf8) LIKE _utf8 '%$q%' 
       GROUP BY name COLLATE utf8_general_ci LIMIT 5 
Vojtěch Dohnal
  • 7,867
  • 3
  • 43
  • 105
1

You must set up proper encoding and collation for your tables.

Table encoding must reflect the actual data encoding. What is your data encoding?

To see table encoding, you can run a query SHOW CREATE TABLE tablename

Your Common Sense
  • 156,878
  • 40
  • 214
  • 345
1

I've always solved like this:

SELECT * FROM trees WHERE LOWER( trees.title ) LIKE  LOWER('%elm%');
Shadi
  • 35
  • 3
0

When I want to develop insensitive case searchs, I always convert every string to lower case before do comparasion

Rbacarin
  • 707
  • 6
  • 12
0

For example if you want to search name like Raja not raja, Royal not royal etc, add BINARY before column name in WHERE clause.

SELECT name FROM person_tbl
WHERE BINARY name LIKE "R%";
Billu
  • 2,733
  • 26
  • 47