283

Is a MySQL SELECT query case sensitive or case insensitive by default? And if not, what query would I have to send so that I can do something like the following?

SELECT * FROM `table` WHERE `Value` = "iaresavage"

Where in actuality, the real value of Value is IAreSavage.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
rolling_codes
  • 15,174
  • 22
  • 76
  • 112
  • 54
    Ultimately it depends on filed collation - if it's '_ci' (case-insensitive) or '_cs' (case-sensitive) – Jovan Perovic Feb 28 '12 at 15:13
  • 18
    This is one poorly worded question ;). Half the answers are showing you how to do case insensitive comparison, half are aiming for case sensitive. And only 1 tells you that the default is in fact case insensitive. :) It's worth noting that case insensitivity works even when you do a comparison like `'value' in ('val1', 'val2', 'val3')` – SaltyNuts Dec 16 '13 at 20:37
  • 6
    @SaltyNuts man, reading this question 7 years later and realizing how much of a noob I was is embarrassing! I could have just read the documentation and the answer is in like the first sentence about SELECT statements... – rolling_codes Jan 02 '18 at 21:01
  • 1
    To add to what @JovanPerovic said, utf8_bin also makes it case sensitive. Not sure if that existed back then – Chiwda Apr 13 '18 at 16:13
  • @NoodleOfDeath Hi, where is the "first sentence"? I didn't find anything while searhing with "sensitive" in the doc https://dev.mysql.com/doc/refman/8.0/en/select.html . – Rick Mar 23 '22 at 09:01
  • @Rick Now that you mention it, I misspoke. I read it here (https://dev.mysql.com/doc/refman/8.0/en/case-sensitivity.html) but with the perspective of an experienced developer and realize now that the docs are most definitely not written in layman's terms nor explained in the literal first sentence regarding SELECT statements – rolling_codes Mar 23 '22 at 15:49

14 Answers14

530

They are case insensitive, unless you do a binary comparison.

rolling_codes
  • 15,174
  • 22
  • 76
  • 112
Marc B
  • 356,200
  • 43
  • 426
  • 500
  • 3
    I mostly do agree with Tim's comment, I don't think doing a "lower()" on your values everywhere is the best way to handle it, seems like a workaround. But I admit it at times it makes sense and is easier. (Colin did mention collate was better) We had historical data moved into mysql table which broke legacy logic because of certain column values having insensitive case. We needed to know the difference between "GE1234" and "ge1234", they needed to be unique and stay logged that way. We set our column in create table statement this way instead: varchar(20) CHARACTER SET utf8 COLLATE utf8_bin – gregthegeek Mar 19 '14 at 18:56
  • 36
    I don't know why so many people voted this up. It clearly states here http://dev.mysql.com/doc/refman/5.0/en/case-sensitivity.html that "...this means that for alphabetic characters, comparisons will be case sensitive." So if I look for 'DickSavagewood' it would NOT pick up 'dicksavagewood'. Doing the same with LOWER() WILL pick it up. So my answer to the question: in your particular case the SELECT is indeed case-sensitive. – Luftwaffle Aug 20 '14 at 13:38
  • 13
    @user1961753: Read again: "For binary strings (varbinary, blob)... will be case sensitive". – Marc B Aug 20 '14 at 14:40
  • @pete It looks like he WAS looking for case-insensitivity, though the wording of the question could be better. The answer seems spot-on for what he wanted to know. – fool4jesus Jan 02 '16 at 16:48
  • Indeed, I quickly remove "...AND password = ? .." from my Oracle's queries. But from other side how UNIQUE modifier for a string field works? Does it honor case sensitivity? Let me check. – Singagirl Jun 19 '16 at 19:32
  • 1
    @MarcB this link is now broken. Could you fix it? :) – Phiter Nov 01 '16 at 02:17
  • broken link in answer. no longer useful. – Funk Doc Dec 14 '16 at 16:40
  • 7
    As Jovan said, it depends on the collation, so this answer is pretty much wrong. – phil294 Mar 14 '18 at 23:05
  • Agree with @Blauhirn, it dipends by the collation, if i.e. utf8_general_ci (where CI stays for Case Insensitive). – Jackie Degl'Innocenti Feb 20 '19 at 11:15
  • The answer works fine but if you binary this in a where clause, the index on the column wont be used. – SRB Jul 22 '19 at 11:45
  • As said before, case-sensitivity depends on the collation. This answer is therefore partially incorrect (binary comparisons will result in case-sensitive operations, so that part is true). – lauxjpn Dec 25 '19 at 08:15
146

You can lowercase the value and the passed parameter:

SELECT * FROM `table` WHERE LOWER(`Value`) = LOWER("IAreSavage")

Another (better) way would be to use the COLLATE operator as said in the documentation.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Colin Hebert
  • 91,525
  • 15
  • 160
  • 151
  • 22
    How would this `SELECT` statement look using `COLLATE` then? – Yes Barry Dec 01 '11 at 22:43
  • 13
    It says, on the referred documentation page above, that "nonbinary string comparisons are case insensitive by default". – Per Quested Aronsson Oct 18 '12 at 13:22
  • 10
    Kind of terrifying how many people upvoted this answer. As @Marc explains above, comparisons *are* case-insensitive. You need to understand collations and indexes and configure those properly - using string transformations like `LOWER()` or an arbitrary `COLLATE` clause can completely bypass an index, and over time, as your table grows, this can have drastic performance implications. Likely these are usernames you're looking up? Use a case-insensitive collation and add a unique index to the column. Use `EXPLAIN` to confirm that the index is being used. – mindplay.dk Jan 14 '16 at 20:22
  • 1
    I was about to say the same as mindplay.dk... upper() and lower() bypass the index and directly affects performance on large database tables. – GTodorov Feb 15 '18 at 19:29
  • I agree both mindplay.dk and GTodorov's opinions. Be careful using some method on a target column in where clause. Index of the column can be useless. Use EXPLAIN! – traeper Jun 07 '18 at 05:19
  • Previous accidental comment won't edit but was incomplete* In my case, I needed something that would work on any user's database (when I don't know the collation). This solution means that even if the collation is set to something case sensitive, my query will still work. I tried using the COLLATE statement to force a case insensitive collation but in one case I had an "Unknown collation" error. I don't know which collations will be available on different databases. Happy to be corrected by @mindplay.dk , GTodorov or traeper. I may have missed something. – Tom Benyon Jan 27 '19 at 19:16
  • Like others have said the `SELECT` is case insensitive by default, and the use of the functions on the `WHERE` clause will cause indexing to not be respected. This drastically causes performance issues as your table grows as every time you run the query you're doing a full table scan. `EXPLAIN` is good about showing the performance of the query by giving you how many rows were used to find the record you're looking for. I.E. if you're doing login, and need your performance to be under 3secs, use of `lower` can cause this to exceed your timeout threshold, and cause login to fail. – Elias Ranz Dec 21 '19 at 13:34
82

Comparisons are case insensitive when the column uses a collation which ends with _ci (such as the default latin1_general_ci collation) and they are case sensitive when the column uses a collation which ends with _cs or _bin (such as the utf8_unicode_cs and utf8_bin collations).

Check collation

You can check your server, database and connection collations using:

mysql> show variables like '%collation%';
+----------------------+-------------------+
| Variable_name        | Value             |
+----------------------+-------------------+
| collation_connection | utf8_general_ci   |
| collation_database   | latin1_swedish_ci |
| collation_server     | latin1_swedish_ci |
+----------------------+-------------------+

and you can check your table collation using:

mysql> SELECT table_schema, table_name, table_collation 
       FROM information_schema.tables WHERE table_name = `mytable`;
+----------------------+------------+-------------------+
| table_schema         | table_name | table_collation   |
+----------------------+------------+-------------------+
| myschema             | mytable    | latin1_swedish_ci |

Change collation

You can change your database, table, or column collation to something case sensitive as follows:

-- Change database collation
ALTER DATABASE `databasename` DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;

-- or change table collation
ALTER TABLE `table` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;

-- or change column collation
ALTER TABLE `table` CHANGE `Value` 
    `Value` VARCHAR(255) CHARACTER SET utf8 COLLATE utf8_bin;

Your comparisons should now be case-sensitive.

ostrokach
  • 17,993
  • 11
  • 78
  • 90
  • 8
    This is THE answer, while others (even with more upvotes) are workarounds. – tony gil Sep 08 '20 at 21:13
  • +1 Just one more support comment. People do not understand the DB basics and place just what works for them, which is not a complete solution but a workaround. **This answer is the only valid answer to default case sensitive search in MySQL.** You define with collation what behavior your want. – elano7 May 10 '23 at 12:54
61

USE BINARY

This is a simple select

SELECT * FROM myTable WHERE 'something' = 'Something'

= 1

This is a select with binary

SELECT * FROM myTable WHERE BINARY 'something' = 'Something'

or

SELECT * FROM myTable WHERE 'something' = BINARY 'Something'

= 0

Someone
  • 635
  • 5
  • 2
  • 3
    When does it make sense to use BINARY on only one side of the = (SELECT * FROM myTable WHERE BINARY 'something' = 'Something')? – Jimmy Mar 14 '13 at 15:31
  • @Jimmy What do you mean exactly? The code works. When one side in the comparison is cast to binary the comparison is done binary. – Jori Jul 11 '14 at 13:01
  • @Jori Oh, I guess I misread -- I thought one of the two examples had BINARY on both sides of the equal. – Jimmy Jul 11 '14 at 18:19
  • I just up voted this because this really IS the right answer. According to the documentation at the MySQL website they say it is better to use the BINARY command than it is to try to typecast your words/request into a specific language because the BINARY command says to leave everything like it is and to use it exactly as it is presented. So when I came along looking for an answer - the two answers here led me to the MySQL website and to look at their documentaiton. Using BINARY is better. Translating can cause other problems. – Mark Manning Oct 25 '15 at 15:19
26

String comparison in WHERE phrase is not case sensitive. You could try to compare using

WHERE `colname` = 'keyword'

or

WHERE `colname` = 'KeyWord'

and you will get the same result. That is default behavior of MySQL.

If you want the comparison to be case sensitive, you could add COLLATE just like this:

WHERE `colname` COLLATE latin1_general_cs = 'KeyWord'

That SQL would give different result with this one: WHERE colname COLLATE latin1_general_cs = 'keyword'

latin1_general_cs is common or default collation in most database.

Ifan Iqbal
  • 3,053
  • 5
  • 28
  • 31
14

The collation you pick sets whether you are case sensitive or not.

chuck taylor
  • 2,476
  • 5
  • 29
  • 46
  • Can you elaborate? (But *** *** *** *** *** ***[without](https://meta.stackexchange.com/a/131011)*** *** *** *** *** *** "Edit:", "Update:", or similar - the answer should appear as if it was written today.) – Peter Mortensen Jul 24 '23 at 08:56
12

The default is case insensitive, but the next most important thing you should take a look at is how the table was created in the first place, because you can specify case sensitivity when you create the table.

The script below creates a table. Notice down at the bottom it says "COLLATE latin1_general_cs". That cs at the end means case sensitive. If you wanted your table to be case insensitive you would either leave that part out or use "COLLATE latin1_general_ci".

   CREATE Table PEOPLE (

       USER_ID  INTEGER UNSIGNED NOT NULL AUTO_INCREMENT,

       FIRST_NAME  VARCHAR(50) NOT NULL,
       LAST_NAME  VARCHAR(50) NOT NULL,

       PRIMARY KEY (USER_ID)

   )

   ENGINE=MyISAM DEFAULT CHARACTER SET latin1
    COLLATE latin1_general_cs AUTO_INCREMENT=0;

If your project is such that you can create your own table, then it makes sense to specify your case sensitivity preference when you create the table.

Ken Johnson
  • 425
  • 3
  • 12
4

Marc B's answer is mostly correct.

If you are using a nonbinary string (CHAR, VARCHAR, TEXT), comparisons are case-insensitive, per the default collation.

If you are using a binary string (BINARY, VARBINARY, BLOB), comparisons are case-sensitive, so you'll need to use LOWER as described in other answers.

If you are not using the default collation and you are using a nonbinary string, case sensitivity is decided by the chosen collation.

Source: B.3.4.1 Case Sensitivity in String Searches. Read closely. Some others have mistaken it to say that comparisons are necessarily case-sensitive or insensitive. This is not the case.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
A248
  • 690
  • 7
  • 17
3

Try with:

order by lower(column_name) asc;
Jako
  • 944
  • 14
  • 33
VS-java
  • 74
  • 3
3

SQL Select is not case sensitive.

This link can show you how to make is case sensitive: http://web.archive.org/web/20080811231016/http://sqlserver2000.databases.aspfaq.com:80/how-can-i-make-my-sql-queries-case-sensitive.html

Community
  • 1
  • 1
Jacob Nelson
  • 2,946
  • 5
  • 33
  • 41
2

Note also that table names are case sensitive on Linux unless you set the lower_case_table_name config directive to 1. This is because tables are represented by files which are case sensitive in Linux.

Especially beware of development on Windows which is not case sensitive and deploying to production where it is. For example:

"SELECT * from mytable" 

against table myTable will succeed in Windows but fail in Linux, again, unless the abovementioned directive is set.

Reference here: http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html

Wes Grant
  • 829
  • 7
  • 13
  • 1
    +1 - The scenario of writing case insensitive queries and then failing on Linuxes happened a lot in our project – Vic Nov 19 '13 at 09:22
  • @Vic I am having the same issue with my project. Would you please tell me how did you fix it? – Kamran Ahmed Jan 05 '14 at 14:54
  • @KamranAhmed, you need to use casing of table names exactly as they appear in creation scripts – Vic Jan 05 '14 at 19:40
  • @Vic that'd be the last resort, as I'd have to modify literally tons of queries. I was wondering, if there'd be any easy way to do it. Thanks though! – Kamran Ahmed Jan 06 '14 at 06:12
  • @KamranAhmed, try to change the `lower_case_table_name` as specified in the answer we're commenting under – Vic Jan 06 '14 at 07:23
  • @Vic actually the queries contain a mix of table names. For example, there is a table called `StockMain` and it has been referenced with `stockmain`, `Stockmain` and `StockMain`. So I dont think, that it's going to fix it. – Kamran Ahmed Jan 06 '14 at 07:29
0

You can try it.

SELECT * FROM `table` WHERE `Value` COLLATE latin1_general_cs = "IAreSavage"
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Zahid
  • 23
  • 4
  • I tried that COLLATE but got : `ERROR 1253 (42000): COLLATION 'latin1_general_cs' is not valid for CHARACTER SET 'utf8mb4'` – raddevus Aug 30 '23 at 13:06
0

String fields with the binary flag set will always be case sensitive. Should you need a case sensitive search for a non binary text field use this: SELECT 'test' REGEXP BINARY 'TEST' AS RESULT;

user2288580
  • 2,210
  • 23
  • 16
0

In my case neither BINARY nor COLLATE nor CHARACTER SET works with my UTF8 table.

I have usernames in my table like henry, Henry, susan, Susan or suSan and find the respective users by comparing the byte sequences of the names.

The following function creates the byte sequences:

function makeByteString($string){
    $tmp = "";
    for($i=0;$i<strlen($string);$i++){
        $sign = substr($string,$i,1);
        $tmp.=ord($sign);
    }
    return $tmp;
}

The SQL query finds the correct id:

$sql = "SELECT id, username FROM users WHERE `username` = ? ";
$stmt = $conn->prepare($sql);
$stmt->execute([$strUsername]); //e.g. susan, Susan or suSan
$rows = $stmt->rowCount();
if($stmt && $rows>0){
  while ($row = $stmt->fetch()) {
    if(makeByteString($strUsername) == 
                   makeByteString(trim($row["username"]))){
      $id = $row['id'];
    }
  }
}   
guenter47
  • 457
  • 5
  • 13