MySQL LOCATE() Function: Syntax, Start Position, and Examples
Use MySQL LOCATE() to find a substring, set a starting position, handle missing matches, and compare it with INSTR() and POSITION().
On this page
MySQL LOCATE(substr, str[, pos]) returns the 1-based position of the first occurrence of substr in str. It returns 0 if there is no match and NULL if an argument is NULL. The optional pos argument starts the search later in the string; see the MySQL LOCATE() reference.
The Anatomy of LOCATE()
The LOCATE() function comes in two flavors:
LOCATE(substr, str)
LOCATE(substr, str, pos)
Parameters Explained:
substr: The needle you’re searching forstr: The haystack where you’re searchingpos(optional): Where to start searching (1-based index)
Key Behavior:
- Returns the position of the first occurrence
- Returns 0 if the substring isn’t found
- String matching follows the arguments’ collation. A binary argument makes matching case-sensitive.
Basic Example:
SELECT LOCATE('base', 'Database'); -- Returns 5
Everyday Search Scenarios
Finding Domain Names in Emails
SELECT
email,
LOCATE('@', email) AS at_position,
SUBSTRING(email, LOCATE('@', email) + 1) AS domain
FROM users;
Validating String Formats
-- Check for properly formatted product codes (XX-999)
SELECT product_code
FROM products
WHERE LOCATE('-', product_code) = 3
AND LENGTH(product_code) = 6;
Multi-occurrence Searching
-- Find second occurrence of 'error' in log
SELECT
log_text,
LOCATE('error', log_text, LOCATE('error', log_text) + 1) AS second_occurrence
FROM system_logs;
LOCATE() vs Other Search Functions
How LOCATE() compares to similar functions:
-
INSTR(): Same search with the string and substring arguments reversed
LOCATE('needle', 'haystack') -- Same as: INSTR('haystack', 'needle') -
POSITION(): SQL-standard spelling for the two-argument search
POSITION('needle' IN 'haystack') -
LIKE: Better for pattern matching than exact position finding
-
REGEXP: More powerful but more complex for simple searches
For a concise comparison of the three substring-position forms, see 3 ways to find a substring’s position in MySQL.
Advanced Positioning Techniques
Nested Searching
-- Find text between parentheses
SELECT
SUBSTRING(
description,
LOCATE('(', description) + 1,
LOCATE(')', description) - LOCATE('(', description) - 1
) AS parenthetical
FROM product_descriptions;
Case-Sensitive Searching
For nonbinary strings, the collation determines whether letter case matters. This example makes the pattern binary so the comparison is case-sensitive:
-- Force case-sensitive search regardless of collation
SELECT LOCATE(CAST('mysql' AS BINARY), 'MySQL Database'); -- Returns 0
CAST(... AS BINARY) avoids the deprecated BINARY expr operator. See MySQL’s CAST reference and SQLiz’s MySQL warning 1287 guide.
Dynamic Position Calculation
-- Extract text after last slash in path
SELECT
path,
SUBSTRING(path,
LOCATE('/', REVERSE(path)) + 1
) AS filename
FROM file_records;
Performance Considerations
While LOCATE() is generally efficient, watch for:
- Large text columns: Scanning long TEXT/BLOB fields can be slow
- Repeated searches: Consider storing positions if frequently needed
- Index usage: Functions in WHERE clauses often prevent index usage
Optimization Example:
-- Less efficient (can't use index):
SELECT * FROM documents WHERE LOCATE('confidential', content) > 0;
-- Better for full-text search:
ALTER TABLE documents ADD FULLTEXT(content);
SELECT * FROM documents WHERE MATCH(content) AGAINST('confidential');
Real-World Use Cases
URL Processing
-- Extract query parameters
SELECT
url,
SUBSTRING(url, LOCATE('?', url) + 1) AS query_string
FROM web_requests
WHERE LOCATE('?', url) > 0;
Data Cleaning
-- Remove trailing semicolons
UPDATE imported_data
SET raw_value = SUBSTRING(raw_value, 1, LOCATE(';', raw_value) - 1)
WHERE LOCATE(';', raw_value) > 0;
Conditional Logic
-- Categorize based on content presence
SELECT
message,
CASE
WHEN LOCATE('urgent', message) > 0 THEN 'High Priority'
WHEN LOCATE('review', message) > 0 THEN 'Needs Attention'
ELSE 'Normal'
END AS priority
FROM notifications;
Handling Edge Cases
LOCATE() gracefully handles special situations:
-
Empty strings:
SELECT LOCATE('', 'text'); -- Returns 1 -
NULL values:
SELECT LOCATE('needle', NULL); -- Returns NULL -
Position overflow:
SELECT LOCATE('text', 'search', 100); -- Returns 0 -
Zero-length substr:
SELECT LOCATE('', 'text', 3); -- Returns 3
Summary
Use LOCATE() for an exact substring search that returns a character position. Use its optional pos argument to continue searching from a later point, and choose LIKE or a regular expression when you need pattern matching.