00:00

MySQL LIKE

Last updated: 5 min read

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

How LIKE patterns matchFour patterns tested on names: 'Ra%' matches names starting with Ra; '%an' matches names ending in an; '%esh%' matches names containing esh; '_a%' matches names whose second letter is a.'Ra%'starts with RaRahul ✔Raman ✔Kiran ✘'%an'ends with anRaman ✔Kiran ✔Rahul ✘'%esh%'contains eshMahesh ✔Eshwar ✔Rahul ✘'_a%'2nd letter is aRahul ✔Mahesh ✔Kiran ✘% = any number of characters (even none) _ = exactly one character
Figure 1: % stands for any sequence of characters, _ for exactly one. Matching is case-insensitive with the default collation, so '%esh%' matches Eshwar.
PatternMeaningMatchesDoesn't match
'Ra%'starts with RaRa, Rahul, RamanKiran
'%an'ends with anRaman, KiranAnand
'%esh%'contains eshMahesh, EshwarRahul
'_a%'second letter aRahul, MaheshKiran
'____'exactly 4 charactersSanaRahul

2. Starts With, Ends With, Contains

query.sql
SELECT name FROM contacts WHERE name LIKE 'Ra%';

Result: 2 rows

name
Rahul Verma
Raman Gill
query.sql
SELECT name, email FROM contacts WHERE email LIKE '%@corp.example';

Result: 3 rows

nameemail
Raman Gillraman@corp.example
Mahesh Iyermahesh@corp.example
Sana Khansana_k@corp.example
query.sql
SELECT name FROM contacts WHERE name LIKE '%esh%';

Result: 2 rows

name
Mahesh Iyer
Eshwar Rao
query.sql
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

query.sql
SELECT name, phone FROM contacts WHERE phone NOT LIKE '+91%';

Result: 1 row

namephone
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:

query.sql
SELECT COUNT(*) AS has_discount FROM contacts WHERE note LIKE '%discount%';

Result: 1 row

has_discount
2
query.sql
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):

query.sql
SELECT name, note FROM contacts WHERE note LIKE '%\\%%';   -- notes containing a % sign

Result: 2 rows

namenote
Raman Gill50% discount client
Sana Khan5% discount
query.sql
SELECT name, email FROM contacts WHERE email LIKE '%!_%' ESCAPE '!';   -- emails containing an underscore

Result: 2 rows

nameemail
Kiran Shettykiran_s@mail.example
Sana Khansana_k@corp.example

Without escaping, _ matches any character, so this matches every email:

query.sql
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):

query.sql
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:

query.sql
SELECT name FROM contacts WHERE name LIKE 'ra%' COLLATE utf8mb4_0900_as_cs;

Result: Empty set (0 rows)

name
No rows
query.sql
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.

query.sql
SELECT id, name FROM contacts WHERE id LIKE '%5%';

Result: 1 row

idname
5Eshwar 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:

explain.sql
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

typekeyExtra
rangeidx_nameUsing where; Using index

'%an': index fully scanned

typekeyExtra
indexidx_nameUsing where; Using index
For word searches inside long text ("contains discount"), a 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":

query.sql
SELECT name, phone FROM contacts WHERE phone REGEXP '^\\+91 98';

Result: 4 rows

namephone
Rahul Verma+91 98450 11223
Raman Gill+91 98140 22334
Kiran Shetty+91 98860 33445
Sana Khan+91 98200 55667
query.sql
SELECT name, email FROM contacts WHERE email REGEXP '^[a-z]+\\.[a-z]+@';   -- first.last@ style

Result: 2 rows

nameemail
Rahul Vermarahul.v@mail.example
Eshwar Raoeshwar.rao@mail.example
ToolUse for
=Exact match (fastest)
LIKESimple prefix / suffix / contains patterns
REGEXPComplex patterns: digits, alternatives, repetition
FULLTEXTSearching 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:

LikeSearch.java
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'.
solution.sql
SELECT name, city FROM contacts WHERE city LIKE '%uru';

Result: 2 rows

namecity
Rahul VermaBengaluru
Kiran ShettyMangaluru
Exercise 2: Names that have exactly two words where the first word has 4 letters.
solution.sql
SELECT name FROM contacts WHERE name LIKE '____ %' AND name NOT LIKE '% % %';

Result: 1 row

name
Sana Khan

11. Summary

  • LIKE matches 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 _cs or _bin collation for exact case.
  • Leading wildcards can't use indexes; consider FULLTEXT or REGEXP for richer searches.