Skip to main content

How to Make a MySQL Text Comparison Case-Sensitive

· 5 min read
Jagdish Kumawat
Founder @ Dewiride

In MySQL, 'usb' = 'USB' is true, and so is 'cafe' = 'café'. That comes from the collation, the rule that decides how text compares. Add COLLATE to a comparison to change the rule for that one query. This guide shows the default on MySQL 9.7, and three other rules you can ask for.

Prerequisites​

Step 1: See the Default​

mysql
SELECT 'usb' = 'USB', 'cafe' = 'café', 'résumé' = 'resume';
Output
+---------------+------------------+-----------------------+
| 'usb' = 'USB' | 'cafe' = 'café' | 'résumé' = 'resume' |
+---------------+------------------+-----------------------+
| 1 | 1 | 1 |
+---------------+------------------+-----------------------+
1 row in set (0.000 sec)

All three are true, so case and accents are both ignored. Look at a column's collation with SHOW FULL COLUMNS:

mysql
SHOW FULL COLUMNS FROM products LIKE 'Name';
Output
+-------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
| Field | Type | Collation | Null | Key | Default | Extra | Privileges | Comment |
+-------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
| Name | varchar(200) | utf8mb4_0900_ai_ci | NO | | NULL | | select,insert,update,references | |
+-------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
1 row in set (0.002 sec)

The name tells you the rule:

Part of utf8mb4_0900_ai_ciMeans
utf8mb4The character set
0900The Unicode version the sorting follows: 9.0.0
aiAccent-insensitive: e matches é
ciCase-insensitive: a matches A

Step 2: Choose a Rule for One Comparison​

COLLATE after a value applies that collation to the comparison:

mysql
SELECT 'usb' COLLATE utf8mb4_bin = 'USB', 'cafe' COLLATE utf8mb4_0900_as_cs = 'café', 'usb' COLLATE utf8mb4_0900_as_ci = 'USB';
Output
+-----------------------------------+---------------------------------------------+------------------------------------------+
| 'usb' COLLATE utf8mb4_bin = 'USB' | 'cafe' COLLATE utf8mb4_0900_as_cs = 'café' | 'usb' COLLATE utf8mb4_0900_as_ci = 'USB' |
+-----------------------------------+---------------------------------------------+------------------------------------------+
| 0 | 0 | 1 |
+-----------------------------------+---------------------------------------------+------------------------------------------+
1 row in set (0.000 sec)
CollationCaseAccentsThe result above
utf8mb4_binMattersMatterusb and USB differ: 0
utf8mb4_0900_as_csMattersMattercafe and café differ: 0
utf8mb4_0900_as_ciIgnoredMatterusb and USB match: 1

MySQL's case sensitivity page gives the same advice: "you can use the COLLATE operator to cause either operand to have the utf8mb4_0900_as_cs or utf8mb4_bin collation".

Step 3: Use It in a Query​

The default finds uppercase names from a lowercase search:

mysql
SELECT Name FROM products WHERE Name LIKE 'usb%';
Output
+------------------------+
| Name |
+------------------------+
| USB-C cable, 2 m |
| USB-C cable, 1 m |
| USB-C charger, 20 W |
| USB-C charger, 65 W |
| USB-C to USB-A adapter |
+------------------------+
5 rows in set (0.000 sec)

With COLLATE, the same search finds nothing:

mysql
SELECT Name FROM products WHERE Name COLLATE utf8mb4_bin LIKE 'usb%';
Output
Empty set (0.000 sec)

And the right case finds them:

mysql
SELECT Name FROM products WHERE Name COLLATE utf8mb4_bin LIKE 'USB%';
Output
+------------------------+
| Name |
+------------------------+
| USB-C cable, 2 m |
| USB-C cable, 1 m |
| USB-C charger, 20 W |
| USB-C charger, 65 W |
| USB-C to USB-A adapter |
+------------------------+
5 rows in set (0.000 sec)

A terminal with three searches: LIKE usb% finds five rows, COLLATE utf8mb4_bin LIKE usb% finds none, and COLLATE utf8mb4_bin LIKE USB% finds five rows.

This is what EF Core's StartsWith does on Oracle's provider, which is why it finds nothing for lowercase text.

For One Query or for the Column?​

COLLATE in a query changes the rule for that comparison. If a column should always compare exactly, for example a code where a1 and A1 are different things, set the column's collation instead, with ALTER TABLE or through your migrations. A column's unique index follows its collation as well, which is why Cables and cables count as the same name here.

Common Mistakes​

MistakeWhat happensDo this instead
Expecting = to be exactusb matches USB by defaultUse COLLATE, or change the column
COLLATE on a column in WHERE, on a big tableAn index with a different collation can't be usedChange the column's collation if it's common
Mixing collations in one comparisonMySQL reports an illegal mix of collationsName one with COLLATE
Forgetting accentscafe also matches café under _ai_Use _as_

FAQ​

Which should I pick, utf8mb4_bin or utf8mb4_0900_as_cs?​

Both tell usb from USB. utf8mb4_bin compares raw values, and the _as_cs collation follows Unicode's rules, so it sorts more naturally. For a plain exact match, either works.

Does this change how the text is stored?​

No. Stored text keeps its case and accents. The collation only decides how it compares and sorts.

Conclusion​

A column's collation decides how its text compares, and the default utf8mb4_0900_ai_ci ignores case and accents. Add COLLATE utf8mb4_bin or COLLATE utf8mb4_0900_as_cs to compare exactly in one query, or change the column if it should always work that way.

Additional Resources​

Stay Updated

Subscribe to our newsletter for the latest tutorials, tech insights, and developer news.

By subscribing, you agree to our privacy policy. Unsubscribe at any time.