Searching for text within your database is one of the most common operations you’ll perform. Whether you’re looking for customer names, filtering product descriptions, or finding records that match a pattern, SQL provides powerful tools for text searching. The LIKE operator is your primary tool for pattern matching in SQL.
Throughout this guide, you’ll find interactive SQL exercises that let you practice pattern matching in your browser—no database setup required. Write queries, get instant feedback, and build your skills with real examples.
Understanding SQL Pattern Matching
SQL doesn’t have a dedicated “contains” function like some programming languages. Instead, it uses the LIKE operator combined with wildcard characters to search for patterns within text. This approach is both powerful and flexible, allowing you to match anything from simple substrings to complex patterns.
The basic syntax is:
SELECT column_name
FROM table_name
WHERE column_name LIKE 'pattern';
The Two SQL Wildcards
SQL provides two wildcard characters for pattern matching:
| Wildcard | Description | Example |
|---|---|---|
% |
Matches any sequence of characters (including zero characters) |
'%test%' matches “test”, “testing”, “latest” |
_ |
Matches exactly one character |
't_st' matches “test”, “tast”, but not “toast” |
Understanding these wildcards is the key to mastering SQL text searches.
Searching for Text That Contains a Substring
The most common text search is checking if a column contains a specific word or phrase. Use the % wildcard on both sides of your search term:
SELECT * FROM customers
WHERE company_name LIKE '%Tech%';
This query finds all customers where company_name contains “Tech” anywhere—at the beginning, middle, or end. It would match:
- “Tech Solutions Inc”
- “FinTech Corp”
- “Technology Partners”
Try it yourself:
[[ testData.title ]]
Query the products table to find all products where the name contains the word “Pro”. Return the id and name columns.
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Your Results:
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Expected Results:
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Available Tables
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Pattern Positions: Starts With, Ends With, Contains
You can control where the pattern appears by positioning your wildcards:
Starts With (Prefix Search)
SELECT * FROM products
WHERE name LIKE 'iPhone%';
Matches: “iPhone 15”, “iPhone Pro Max”
Does not match: “New iPhone Case”
Ends With (Suffix Search)
SELECT * FROM files
WHERE filename LIKE '%.pdf';
Matches: “report.pdf”, “invoice.pdf”
Does not match: “pdf_guide.txt”
Contains (Anywhere)
SELECT * FROM messages
WHERE content LIKE '%urgent%';
Matches anywhere the word “urgent” appears.
Try it yourself:
[[ testData.title ]]
Query the employees table to find all employees whose email starts with the letter ‘j’. Return id, name, and email, ordered by name.
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Your Results:
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Expected Results:
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Available Tables
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Using Underscore for Precise Matching
The underscore wildcard (_) matches exactly one character, which is useful when you know the pattern’s structure:
SELECT * FROM products
WHERE product_code LIKE 'A__-___';
This matches codes like “A12-345” or “ABC-XYZ” but not “A1-234” or “ABCD-123”.
Common use cases for underscore:
- Matching fixed-format codes (SKUs, part numbers)
- Finding values with specific character positions
- Validating data formats
Try it yourself:
[[ testData.title ]]
Query the inventory table to find all items where the sku has exactly 3 characters followed by ‘-001’. Return sku and item_name, ordered by sku.
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Your Results:
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Expected Results:
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Available Tables
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Case Sensitivity in Pattern Matching
LIKE behavior varies by database:
| Database | Default Behavior |
|---|---|
| PostgreSQL | Case-sensitive |
| MySQL | Case-insensitive (with default collation) |
| SQLite | Case-insensitive for ASCII letters |
| SQL Server | Depends on collation settings |
To ensure consistent case-insensitive searches, use the LOWER() or UPPER() function:
SELECT * FROM customers
WHERE LOWER(name) LIKE '%smith%';
This finds “Smith”, “SMITH”, “smith”, and “SmItH”.
PostgreSQL alternative: Use ILIKE for case-insensitive matching:
SELECT * FROM customers
WHERE name ILIKE '%smith%';
Try it yourself:
[[ testData.title ]]
Query the articles table to find all articles where the title contains “sql” (case-insensitive). Return id and title, ordered by id.
[[ col ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Your Results:
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Expected Results:
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ error ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
[[ testData.solution ]]
Available Tables
[[ table.name ]]
| [[ col ]] |
|---|
| [[ formatCell(cell) ]] |
Escaping Special Characters
What if you need to search for actual % or _ characters? Use the ESCAPE clause:
SELECT * FROM discounts
WHERE description LIKE '%50\%%' ESCAPE '\';
This searches for “50%” literally. The backslash tells SQL to treat the following % as a regular character, not a wildcard.
Common scenarios:
- Searching for percentage values (“50%”, “25% off”)
- Finding filenames with underscores (“report_2024”)
- Matching URLs or file paths
NOT LIKE: Excluding Patterns
Use NOT LIKE to find records that don’t match a pattern:
SELECT * FROM users
WHERE email NOT LIKE '%@gmail.com';
This finds all users who don’t have Gmail addresses. Combine with other conditions for more complex filtering:
SELECT * FROM products
WHERE name NOT LIKE '%discontinued%'
AND name NOT LIKE '%legacy%';
Combining Multiple Patterns with OR
Search for multiple patterns using OR:
SELECT * FROM products
WHERE name LIKE '%laptop%'
OR name LIKE '%notebook%'
OR name LIKE '%computer%';
This finds products matching any of these terms.
Performance Considerations
Pattern matching can be slow on large tables, especially with leading wildcards:
Slow (Cannot Use Index)
SELECT * FROM products
WHERE name LIKE '%widget%'; -- Leading wildcard
The database must scan every row because it can’t predict where “widget” might appear.
Fast (Can Use Index)
SELECT * FROM products
WHERE name LIKE 'widget%'; -- No leading wildcard
When the pattern starts with literal characters, the database can use an index to quickly find matching rows.
Optimization Tips
- Avoid leading wildcards when possible
- Create indexes on frequently searched columns
- Consider full-text search for complex text searching needs
- Limit result sets with additional WHERE conditions
SELECT * FROM products
WHERE category = 'Electronics' -- Filter first
AND name LIKE '%pro%'; -- Then pattern match
Alternative: Full-Text Search
For heavy text searching needs, consider full-text search capabilities:
PostgreSQL:
SELECT * FROM articles
WHERE to_tsvector('english', content) @@ to_tsquery('database & performance');
MySQL:
SELECT * FROM articles
WHERE MATCH(title, content) AGAINST('database performance');
Full-text search offers:
- Better performance on large text fields
- Relevance ranking
- Word stemming (finding “running” when searching “run”)
- Stop word handling
Common Patterns Quick Reference
| Goal | Pattern | Example |
|---|---|---|
| Contains “word” | '%word%' |
LIKE '%error%' |
| Starts with “word” | 'word%' |
LIKE 'Dr.%' |
| Ends with “word” | '%word' |
LIKE '%.pdf' |
| Exactly 3 characters | '___' |
LIKE '___' |
| Starts with letter, 3 digits |
'_###' (conceptual) |
LIKE 'A___' |
| Second character is ‘a’ | '_a%' |
LIKE '_a%' |
Working with Pattern Matching in Beekeeper Studio
When building complex LIKE queries, having a good SQL editor makes development much easier. Beekeeper Studio provides helpful features for working with pattern matching:
- Autocomplete: Suggests column names to avoid typos in your WHERE clauses
- Query formatting: Keeps complex multi-pattern queries readable
- Result highlighting: Easily spot matched patterns in your results
- Multi-database support: Consistent experience across PostgreSQL, MySQL, SQLite, and more
The free version includes everything you need for mastering SQL pattern matching.
Key Takeaways
SQL pattern matching with LIKE is essential for searching text in your database. Here’s what to remember:
-
Use
%to match any characters (zero or more) - this is your “contains” search -
Use
_to match exactly one character - great for fixed-format patterns -
Position wildcards strategically:
%word(ends with),word%(starts with),%word%(contains) -
Handle case sensitivity with
LOWER()or database-specific functions likeILIKE -
Escape special characters when searching for literal
%or_ - Avoid leading wildcards when possible for better performance
- Consider full-text search for complex text searching needs
Pattern matching is a fundamental SQL skill. Whether you’re filtering customer data, searching logs, or building search functionality, the LIKE operator gives you the flexibility to find exactly what you need.
Ready to practice more? Try the interactive examples above, or explore more SQL tutorials to continue building your database skills.
Beekeeper Studio Is A Free & Open Source Database GUI
Best SQL query & editor tool I have ever used. It provides everything I need to manage my database. - ⭐⭐⭐⭐⭐ Mit
Beekeeper Studio is fast, intuitive, and easy to use. Beekeeper supports loads of databases, and works great on Windows, Mac and Linux.
What Users Say About Beekeeper Studio
"Beekeeper Studio completely replaced my old SQL workflow. It's fast, intuitive, and makes database work enjoyable again."
"I've tried many database GUIs, but Beekeeper strikes the perfect balance between features and simplicity. It just works."