LOCATE
La función LOCATE devuelve la posición de la primera aparición de una subcadena dentro de otra cadena. Es la herramienta de búsqueda de texto más flexible de MySQL, porque, a diferencia de INSTR, admite un tercer argumento para indicar desde qué posición empezar a buscar, lo que permite localizar la segunda, tercera o enésima aparición de un texto.
Hay dos detalles que conviene fijar desde el principio porque son fuente habitual de errores: las posiciones en MySQL empiezan en 1, no en 0 como en muchos lenguajes de programación, y cuando la subcadena no aparece, LOCATE devuelve 0 (no NULL ni un número negativo). En este artículo veremos su sintaxis, cómo buscar desde una posición concreta, cómo encadenar búsquedas para encontrar apariciones sucesivas y las diferencias con funciones parecidas.
Sintaxis
LOCATE tiene dos formas: una que busca desde el principio de la cadena y otra que arranca desde la posición que indiques en el tercer argumento.
-- Buscar desde el inicio
LOCATE(subcadena, cadena)
-- Buscar desde una posición específica
LOCATE(subcadena, cadena, posicion_inicio)Existe además POSITION(subcadena IN cadena), que es un alias de LOCATE(subcadena, cadena) heredado del estándar SQL y equivalente a la forma de dos argumentos.
Ejemplo básico
En su uso más simple, devuelve la posición donde empieza la subcadena buscada. Aquí 'Tutorial' comienza en el séptimo carácter:
SELECT LOCATE('Tutorial', 'MySQL Tutorial') AS posicion;| posicion |
|---|
| 7 |
Cuando el texto buscado no existe, el resultado es 0. Este valor es la forma que tiene LOCATE de indicar "no encontrado", y es importante porque permite usarlo directamente en condiciones:
SELECT LOCATE('Python', 'MySQL Tutorial') AS posicion;| posicion |
|---|
| 0 |
Buscar desde una posición
El tercer argumento es lo que distingue a LOCATE de INSTR. Indicando una posición de inicio, puedes saltarte las primeras apariciones y encontrar las siguientes. Veámoslo buscando la letra 'a' en 'banana' desde distintos puntos de partida:
-- Primera 'a' en la cadena
SELECT LOCATE('a', 'banana') AS primera;| primera |
|---|
| 2 |
Si empezamos a buscar a partir de la posición 3, la primera 'a' queda atrás y obtenemos la siguiente:
-- Buscar 'a' desde la posición 3
SELECT LOCATE('a', 'banana', 3) AS segunda;| segunda |
|---|
| 4 |
Y avanzando un poco más el punto de inicio, llegamos a la última aparición:
-- Buscar 'a' desde la posición 5
SELECT LOCATE('a', 'banana', 5) AS tercera;| tercera |
|---|
| 6 |
Encontrar la segunda aparición de un carácter
La técnica anterior se vuelve muy potente cuando se anida: usando el resultado de un LOCATE como posición de inicio de otro, se localiza la segunda aparición de un carácter. El siguiente ejemplo encuentra el primer y el segundo espacio en nombres de productos, sumando 1 a la posición del primero para que la segunda búsqueda arranque justo después:
-- Posición del segundo espacio en nombres de productos
SELECT
nombre,
LOCATE(' ', nombre) AS primer_espacio,
LOCATE(' ', nombre, LOCATE(' ', nombre) + 1) AS segundo_espacio
FROM productos
WHERE LOCATE(' ', nombre, LOCATE(' ', nombre) + 1) > 0
LIMIT 5;| nombre | primer_espacio | segundo_espacio |
|---|---|---|
| iPhone 15 Pro | 7 | 10 |
| MacBook Air M2 | 8 | 12 |
| Apple Watch Series 9 | 6 | 12 |
Este patrón es la base para extraer la segunda palabra de un texto o para dividir cadenas por su segundo separador, combinándolo con SUBSTRING.
Verificar si una cadena contiene un texto
Como LOCATE devuelve 0 cuando no encuentra nada, comprobar si un valor mayor que cero permite filtrar las filas que contienen un texto. Es una alternativa a LIKE especialmente útil cuando, además de saber si aparece, te interesa la posición de la coincidencia:
SELECT nombre, precio
FROM productos
WHERE LOCATE('Air', nombre) > 0;| nombre | precio |
|---|---|
| MacBook Air M2 | 1199.99 |
| iPad Air | 599.99 |
Eso sí, igual que ocurre con otras funciones aplicadas en el WHERE, esta comprobación no puede aprovechar un índice convencional sobre la columna, así que para tablas muy grandes y búsquedas frecuentes conviene valorar un índice de texto completo.
LOCATE con NULL
Si cualquiera de los argumentos es NULL, el resultado es NULL, no 0. Esta distinción importa: 0 significa "no encontrado", mientras que NULL significa "no se pudo determinar" porque faltaba algún dato.
SELECT LOCATE('a', NULL) AS resultado;| resultado |
|---|
| NULL |
Errores comunes
El error más frecuente es el desajuste con INSTR: aunque ambas hacen lo mismo, el orden de los argumentos está invertido. En LOCATE la subcadena va primero, LOCATE(subcadena, cadena), mientras que en INSTR va después, INSTR(cadena, subcadena). Confundirlos da resultados incorrectos sin lanzar ningún error, así que conviene tenerlo muy presente.
El segundo malentendido típico es el de la indexación basada en 1. Quien viene de lenguajes donde las posiciones empiezan en 0 tiende a restar o sumar uno de más al combinar LOCATE con SUBSTRING. Y un tercer punto: por defecto, con colaciones _ci, la búsqueda no distingue mayúsculas; si necesitas una búsqueda sensible al caso, debes forzarla con el operador BINARY sobre la cadena.
Cuándo usar LOCATE
LOCATE es la elección idónea cuando necesitas la posición de un texto dentro de otro, y resulta insustituible cuando esa búsqueda debe empezar desde un punto concreto, como al buscar apariciones sucesivas. Si solo quieres saber si una cadena contiene a otra, sin importar dónde, LIKE suele ser más legible; y para extraer la porción encontrada, LOCATE se combina de forma natural con SUBSTRING.
En el siguiente artículo veremos LPAD, que rellena una cadena por la izquierda hasta una longitud determinada.
Escrito por Eduardo Lázaro
