MySQL LIKE
The LIKE operator matches text against a pattern instead of an exact value. Use it for searches such as "names starting with Ra", "emails at corp.example" or "phone numbers beginning +91". Patterns are built from ordinary characters plus two wildcards.
1. The Two Wildcards
% stands for any sequence of characters, _ for exactly one. Matching is case-insensitive with the default collation, so '%esh%' matches Eshwar.| Pattern | Meaning | Matches | Doesn't match |
|---|---|---|---|
'Ra%' | starts with Ra | Ra, Rahul, Raman | Kiran |
'%an' | ends with an | Raman, Kiran | Anand |
'%esh%' | contains esh | Mahesh, Eshwar | Rahul |
'_a%' | second letter a | Rahul, Mahesh | Kiran |
'____' | exactly 4 characters | Sana | Rahul |
2. Starts With, Ends With, Contains
SELECT name FROM contacts WHERE name LIKE 'Ra%';
Result: 2 rows
| name |
|---|
| Rahul Verma |
| Raman Gill |
SELECT name, email FROM contacts WHERE email LIKE '%@corp.example';
Result: 3 rows
| name | |
|---|---|
| Raman Gill | raman@corp.example |
| Mahesh Iyer | mahesh@corp.example |
| Sana Khan | sana_k@corp.example |
SELECT name FROM contacts WHERE name LIKE '%esh%';
Result: 2 rows
| name |
|---|
| Mahesh Iyer |
| Eshwar Rao |
SELECT name FROM contacts WHERE name LIKE '_a%'; -- second letter is 'a'
Result: 4 rows
| name |
|---|
| Rahul Verma |
| Raman Gill |
| Mahesh Iyer |
| Sana Khan |
3. NOT LIKE
SELECT name, phone FROM contacts WHERE phone NOT LIKE '+91%';
Result: 1 row
| name | phone |
|---|---|
| Eshwar Rao | +1 415 555 0101 |
NULL never matches LIKE or NOT LIKE. Kiran's note is NULL, so he appears in neither of these:
SELECT COUNT(*) AS has_discount FROM contacts WHERE note LIKE '%discount%';
Result: 1 row
| has_discount |
|---|
| 2 |
SELECT COUNT(*) AS no_discount FROM contacts WHERE note NOT LIKE '%discount%';
Result: 1 row
| no_discount |
|---|
| 3 |
4. Searching for % or _ Themselves
To find a literal % or _, escape it with a backslash (or choose your own escape character with ESCAPE):
SELECT name, note FROM contacts WHERE note LIKE '%\\%%'; -- notes containing a % sign
Result: 2 rows
| name | note |
|---|---|
| Raman Gill | 50% discount client |
| Sana Khan | 5% discount |
SELECT name, email FROM contacts WHERE email LIKE '%!_%' ESCAPE '!'; -- emails containing an underscore
Result: 2 rows
| name | |
|---|---|
| Kiran Shetty | kiran_s@mail.example |
| Sana Khan | sana_k@corp.example |
Without escaping, _ matches any character, so this matches every email:
SELECT COUNT(*) AS matches FROM contacts WHERE email LIKE '%_%';
Result: 1 row
| matches |
|---|
| 6 |
5. Case Sensitivity
With the default utf8mb4_0900_ai_ci collation LIKE ignores case (and accents):
SELECT name FROM contacts WHERE name LIKE 'ra%';
Result: 2 rows
| name |
|---|
| Rahul Verma |
| Raman Gill |
For a case-sensitive match, use a binary or case-sensitive collation:
SELECT name FROM contacts WHERE name LIKE 'ra%' COLLATE utf8mb4_0900_as_cs;
Result: Empty set (0 rows)
| name |
|---|
| No rows |
SELECT name FROM contacts WHERE name LIKE 'Ra%' COLLATE utf8mb4_0900_as_cs;
Result: 2 rows
| name |
|---|
| Rahul Verma |
| Raman Gill |
6. LIKE on Numbers and Dates
LIKE converts its operand to text, so it works on numbers and dates, but a range condition is better: it is clearer and can use an index.
SELECT id, name FROM contacts WHERE id LIKE '%5%';
Result: 1 row
| id | name |
|---|---|
| 5 | Eshwar Rao |
7. LIKE and Indexes
A pattern with a fixed start ('Ra%') can use an index like a range search. A leading wildcard ('%an') can't, so MySQL reads every row:
CREATE INDEX idx_name ON contacts (name);
EXPLAIN SELECT id FROM contacts WHERE name LIKE 'Ra%';
EXPLAIN SELECT id FROM contacts WHERE name LIKE '%an';
'Ra%': index range
| type | key | Extra |
|---|---|---|
| range | idx_name | Using where; Using index |
'%an': index fully scanned
| type | key | Extra |
|---|---|---|
| index | idx_name | Using where; Using index |
FULLTEXT index with MATCH … AGAINST is much faster than LIKE '%word%' on big tables.8. When LIKE Isn't Enough: REGEXP
REGEXP (or RLIKE) supports full regular expressions, for example "Indian mobile numbers starting with 98":
SELECT name, phone FROM contacts WHERE phone REGEXP '^\\+91 98';
Result: 4 rows
| name | phone |
|---|---|
| Rahul Verma | +91 98450 11223 |
| Raman Gill | +91 98140 22334 |
| Kiran Shetty | +91 98860 33445 |
| Sana Khan | +91 98200 55667 |
SELECT name, email FROM contacts WHERE email REGEXP '^[a-z]+\\.[a-z]+@'; -- first.last@ style
Result: 2 rows
| name | |
|---|---|
| Rahul Verma | rahul.v@mail.example |
| Eshwar Rao | eshwar.rao@mail.example |
| Tool | Use for |
|---|---|
= | Exact match (fastest) |
LIKE | Simple prefix / suffix / contains patterns |
REGEXP | Complex patterns: digits, alternatives, repetition |
FULLTEXT | Searching words in large text |
9. LIKE from Java (Safely)
Bind the pattern as a parameter, and escape wildcards typed by the user so they are searched literally:
String userInput = "50%";
String escaped = userInput.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_");
try (PreparedStatement ps = con.prepareStatement("SELECT name FROM contacts WHERE note LIKE ?")) {
ps.setString(1, "%" + escaped + "%"); // contains the literal text 50%
try (ResultSet rs = ps.executeQuery()) { /* ... */ }
}
10. Practice Exercises
Exercise 1: Contacts whose city ends with 'uru'.
SELECT name, city FROM contacts WHERE city LIKE '%uru';
Result: 2 rows
| name | city |
|---|---|
| Rahul Verma | Bengaluru |
| Kiran Shetty | Mangaluru |
Exercise 2: Names that have exactly two words where the first word has 4 letters.
SELECT name FROM contacts WHERE name LIKE '____ %' AND name NOT LIKE '% % %';
Result: 1 row
| name |
|---|
| Sana Khan |
11. Summary
LIKEmatches patterns:%= any characters,_= one character.- Starts with
'x%', ends with'%x', contains'%x%'. - Escape literal % and _ with
\or a custom ESCAPE character. - Case-insensitive by default; use a
_csor_bincollation for exact case. - Leading wildcards can't use indexes; consider FULLTEXT or REGEXP for richer searches.