MySQL
case sensitivity
SQL query
database
duplicate question

MySQL case sensitive query

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Case sensitivity in MySQL is controlled mostly by collation, not by SQL syntax alone. That is why a query that looks correct can still match rows you did not intend. To write predictable filters, you need to understand when to use case-sensitive collations, the BINARY keyword, and schema-level choices that preserve index performance.

How MySQL Decides Case Sensitivity

Most MySQL installations use case-insensitive collations for text columns by default, such as utf8mb4_0900_ai_ci. In that collation name, _ci means case-insensitive. If you compare Alice and alice under _ci, MySQL treats them as equal.

You can inspect collation settings at multiple levels.

sql
1SHOW VARIABLES LIKE 'collation%';
2
3SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, COLLATION_NAME
4FROM INFORMATION_SCHEMA.COLUMNS
5WHERE TABLE_SCHEMA = 'appdb' AND TABLE_NAME = 'users';

A typical output shows each column collation, which is the setting that matters for equality and sorting of text data.

Query-Level Case-Sensitive Matching

When you need case-sensitive behavior for one query, use COLLATE or BINARY directly in the predicate.

sql
1-- Exact case-sensitive match for one comparison
2SELECT id, username
3FROM users
4WHERE username COLLATE utf8mb4_0900_as_cs = 'MarkQian';
5
6-- Another option using binary comparison
7SELECT id, username
8FROM users
9WHERE BINARY username = 'MarkQian';

COLLATE ..._as_cs is usually clearer because it makes the desired collation explicit. BINARY can be convenient, but it may be less obvious to readers why matching changed.

For pattern matching, apply collation to the expression as well.

sql
SELECT id, username
FROM users
WHERE username COLLATE utf8mb4_0900_as_cs LIKE 'Mark%';

Schema-Level Design for Consistent Behavior

If your application always requires case-sensitive comparisons for a column, update that column collation rather than repeating COLLATE in every query.

sql
ALTER TABLE users
MODIFY username VARCHAR(100)
COLLATE utf8mb4_0900_as_cs NOT NULL;

This keeps behavior consistent and reduces mistakes in application code. It also helps the optimizer use indexes more naturally than some ad hoc expression-based comparisons.

If you need both behaviors, you can keep the base column case-insensitive and add a generated column for case-sensitive lookups.

sql
1ALTER TABLE users
2ADD username_cs VARCHAR(100)
3GENERATED ALWAYS AS (username) STORED
4COLLATE utf8mb4_0900_as_cs,
5ADD INDEX idx_username_cs (username_cs);

Then query username_cs for strict matching and username for user-friendly searches.

Performance and Indexing Considerations

Case-sensitive logic is not only correctness; it can change query plans.

  1. Expression-based filters can reduce index usage.
  2. Column collation changes affect sort order and uniqueness checks.
  3. Mixed collations in joins can force implicit conversions.

Use EXPLAIN before and after changes.

sql
1EXPLAIN FORMAT=TRADITIONAL
2SELECT id
3FROM users
4WHERE username COLLATE utf8mb4_0900_as_cs = 'MarkQian';

If the optimizer stops using your index, consider a dedicated indexed column with the target collation.

End-to-End Example

This setup demonstrates both behaviors in one table.

sql
1DROP TABLE IF EXISTS demo_users;
2
3CREATE TABLE demo_users (
4  id BIGINT PRIMARY KEY AUTO_INCREMENT,
5  username_ci VARCHAR(64) COLLATE utf8mb4_0900_ai_ci NOT NULL,
6  username_cs VARCHAR(64) COLLATE utf8mb4_0900_as_cs NOT NULL,
7  INDEX idx_ci (username_ci),
8  INDEX idx_cs (username_cs)
9);
10
11INSERT INTO demo_users (username_ci, username_cs)
12VALUES ('Alice', 'Alice'), ('alice', 'alice');
13
14-- Returns both rows because ci collation ignores case
15SELECT id, username_ci
16FROM demo_users
17WHERE username_ci = 'alice';
18
19-- Returns only exact case row
20SELECT id, username_cs
21FROM demo_users
22WHERE username_cs = 'alice';

This pattern keeps intent clear at query time and avoids surprising behavior during maintenance.

Common Pitfalls

  • Assuming MySQL is globally case-insensitive or globally case-sensitive. Behavior depends on collation at server, database, table, and column levels.
  • Using LOWER(column) or UPPER(column) in predicates on large tables. That can hurt index usage and slow queries.
  • Mixing collations in joins without noticing implicit conversion costs. Standardize collations for related text keys.
  • Changing a column collation in production without checking uniqueness side effects and application expectations.
  • Relying on case-sensitive tests in development while production uses a different default collation.

Summary

  • Case sensitivity in MySQL is primarily a collation issue.
  • Use query-level COLLATE or BINARY for one-off strict comparisons.
  • Prefer column-level collation when strict behavior is a permanent requirement.
  • Validate execution plans after collation changes to protect performance.
  • Design schema and indexes so case-sensitive and case-insensitive workflows are both explicit and predictable.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.