- 1 1. Introducción
- 2 2. Sintaxis básica y comportamiento de la función FIND_IN_SET
- 3 3. Ejemplos de uso práctico
- 4 4. Comparación de la Función FIND_IN_SET con Otros Métodos de Búsqueda
- 5 5. Precauciones y Mejores Prácticas
- 6 6. Preguntas frecuentes (FAQ)
- 6.1 ¿Puede la función FIND_IN_SET usar índices?
- 6.2 ¿Funciona correctamente incluso si se mezclan números y cadenas?
- 6.3 ¿Existe alguna forma de buscar varios valores a la vez?
- 6.4 El uso de FIND_IN_SET degrada el rendimiento. ¿Cuáles son las contramedidas?
- 6.5 ¿FIND_IN_SET se volverá obsoleto en el futuro?
- 7 Resumen
1. Introducción
Desafíos al buscar datos separados por comas en MySQL
Al trabajar con bases de datos, puede encontrar casos donde múltiples valores se almacenan en una sola columna, separados por comas. Por ejemplo, hay una columna que almacena una cadena como "1,3,5", y desea extraer solo los registros que incluyan el valor 3. En tales casos, el operador = habitual o la cláusula IN a menudo no arrojan los resultados esperados. Esto se debe a que la cadena separada por comas se trata como una «cadena única», por lo que se evalúa como una coincidencia con toda la cadena en lugar de una coincidencia parcial con el valor.
¿Qué es la función FIND_IN_SET?
Aquí es donde entra en juego la función MySQL FIND_IN_SET. Esta función le permite determinar fácilmente si un valor especificado está incluido en una cadena separada por comas. Por ejemplo, considere el siguiente SQL:
SELECT * FROM users WHERE FIND_IN_SET('3', favorite_ids);
Esta consulta extrae los registros donde la cadena separada por comas en favorite_ids (por ejemplo, "1,2,3,4") incluye el valor "3".
Propósito de este artículo y lectores objetivo
En este artículo, explicaremos cómo usar la función FIND_IN_SET desde los conceptos básicos en detalle. Desde la sintaxis básica hasta ejemplos prácticos, diferencias con otros métodos de búsqueda, precauciones y preguntas frecuentes, nuestro objetivo es proporcionar conocimientos prácticos útiles en el trabajo real cubriendo un amplio espectro.
Los lectores objetivo incluyen lo siguiente:
- Ingenieros web y desarrolladores backend que utilizan MySQL a diario
- Aquellos que necesiten trabajar con sistemas existentes que manejan datos separados por comas
- Principiantes en SQL que luchan con métodos de búsqueda de coincidencia parcial para datos
2. Sintaxis básica y comportamiento de la función FIND_IN_SET
Sintaxis de FIND_IN_SET
FIND_IN_SET es una función en MySQL que determina si un valor específico está contenido dentro de una cadena separada por comas. La sintaxis básica es la siguiente:
FIND_IN_SET(search_value, comma_separated_string)
Por ejemplo, se utiliza de la siguiente manera.
SELECT FIND_IN_SET('3', '1,2,3,4'); -- Result: 3
En este ejemplo, ya que el valor "3" está en la tercera posición, se devuelve el valor numérico 3.
Reglas de valor de retorno
FIND_IN_SET opera de acuerdo con las siguientes reglas.
Condition | Result |
|---|---|
El valor de búsqueda existe en la lista | Posición en la lista (comenzando desde 1) |
El valor de búsqueda no existe | 0 |
Cualquiera de los argumentos es NULL | NULL |
Ejemplo de uso (devolución de posición)
SELECT FIND_IN_SET('b', 'a,b,c'); -- Result: 2
Ejemplo de uso (cuando el valor no existe)
SELECT FIND_IN_SET('d', 'a,b,c'); -- Result: 0
Ejemplo de uso (cuando se incluye NULL)
SELECT FIND_IN_SET(NULL, 'a,b,c'); -- Result: NULL
Ejemplo de uso en la cláusula WHERE
Normalmente, se usa a menudo para filtrar dentro de la cláusula WHERE.
SELECT * FROM users WHERE FIND_IN_SET('admin', roles);
En este ejemplo, solo se extraen las filas donde la columna roles contiene la cadena "admin". Si la columna contiene un valor como "user,editor,admin", coincidirá.
Notas sobre números y cadenas
FIND_IN_SET realiza una comparación de cadenas, por lo que se comporta de la siguiente manera:
SELECT FIND_IN_SET(3, '1,2,3,4'); -- Result: 3
SELECT FIND_IN_SET('3', '1,2,3,4'); -- Result: 3
Funciona tanto con cadenas como con números, pero si el tipo de datos no está claro, puede provocar un comportamiento inesperado, por lo que es deseable manejarlo explícitamente tanto como sea posible.
3. Ejemplos de uso práctico
Búsqueda en columnas con cadenas separadas por comas
En la práctica, existen casos en los que múltiples valores (como identificadores o permisos) se almacenan en una sola columna, separados por comas. Por ejemplo, considere una tabla users como la siguiente.
id | name | favorite_ids |
|---|---|---|
1 | Taro | 1,3,5 |
2 | Hanako | 2,4,6 |
3 | Jiro | 3,4,5 |
Cuando desea recuperar usuarios que incluyan "3", la función FIND_IN_SET es muy útil.
SELECT * FROM users WHERE FIND_IN_SET('3', favorite_ids);
La ejecución de este SQL extraerá los registros de "Taro" y "Jiro".
Funciona bien incluso con tipos numéricos
Aunque favorite_ids parezca contener números como en la sección anterior, FIND_IN_SET realiza una comparación basada en cadenas, por lo que es más seguro pasar los argumentos como cadenas entre comillas.
-- OK
SELECT * FROM users WHERE FIND_IN_SET('5', favorite_ids);
-- It works but not strictly recommended
SELECT * FROM users WHERE FIND_IN_SET(5, favorite_ids);
Para mantener la legibilidad y predictibilidad de la consulta, se recomienda especificar explícitamente los valores como cadenas.
Búsquedas Dinámicas (Marcadores de Posición o Variables)
Al emitir SQL dinámicamente desde aplicaciones web, etc., es común usar variables o parámetros enlazados.
Al usar variables dentro de MySQL, la sintaxis es la siguiente.
SET @target_id = '3';
SELECT * FROM users WHERE FIND_IN_SET(@target_id, favorite_ids);
Al enlazar desde aplicaciones como PHP, Python o Node.js, se puede manejar de manera similar usando marcadores de posición.
Consejos para Buscar Múltiples Valores
Desafortunadamente, FIND_IN_SET solo puede buscar un valor.
Si deseas recuperar registros que incluyan «3 o 4», necesitas escribir múltiples condiciones usando OR.
SELECT * FROM users
WHERE FIND_IN_SET('3', favorite_ids) OR FIND_IN_SET('4', favorite_ids);
Alternativamente, si las condiciones se vuelven más complejas, deberías considerar construir dinámicamente la sentencia SQL en el lado de la aplicación o migrar a una tabla separada normalizada.
4. Comparación de la Función FIND_IN_SET con Otros Métodos de Búsqueda
Métodos de Búsqueda Comúnmente Comparados: Cláusula IN y Cláusula LIKE
Para verificar si un valor específico está incluido en MySQL, además de FIND_IN_SET, se pueden usar la cláusula IN o la cláusula LIKE. Sin embargo, cada una tiene casos de uso y comportamientos distintos, y usarlas incorrectamente puede resultar en no obtener los resultados de búsqueda correctos.
Aquí, aclaremos las diferencias con FIND_IN_SET y los puntos clave para distinguir su uso.
Comparación con la Cláusula IN
IN se usa típicamente para verificar coincidencias con múltiples valores constantes.
-- Example of IN clause (this does not search for records where favorite_ids matches "3")
SELECT * FROM users WHERE favorite_ids IN ('3');
En este caso, solo se afectarán los registros donde favorite_ids coincida exactamente con ‘3’. Es decir, valores como ‘1,3,5’ no coincidirán, y solo se apuntará a la cadena ‘3’.
En cambio, FIND_IN_SET determina la posición de un elemento dentro de una lista separada por comas en lugar de una coincidencia parcial, por lo que puede extraer con precisión los «registros que contienen 3» con un uso similar al siguiente.
SELECT * FROM users WHERE FIND_IN_SET('3', favorite_ids);
✅Puntos clave para distinguir el uso:
IN: usar con tablas normalizadas (por ejemplo,SELECT * FROM posts WHERE category_id IN (1, 3, 5))FIND_IN_SET: usar con cadenas separadas por comas desnormalizadas
Comparación con la Cláusula LIKE
Aunque es técnicamente posible usar la cláusula LIKE para determinar coincidencias parciales, existen las siguientes limitaciones.
-- Example of a common mistake with LIKE clause
SELECT * FROM users WHERE favorite_ids LIKE '%3%';
Esta consulta no solo apunta a «contener 3», sino a todas las cadenas que incluyan el carácter ‘3’, por lo que también puede coincidir con ’13’, ’23’, ’30’, etc.
Esto no puede detectar casos en los que 3 se incluya como un valor independiente.
✅Puntos clave para distinguir el uso:
LIKE: efectivo para búsquedas de cadenas difusas pero no reconoce delimitadores de valorFIND_IN_SET: puede confirmar con precisión coincidencias de valores independientes dentro de listas separadas por comas
Diferencias desde la Perspectiva del Rendimiento
Objetivo de comparación | Index Usage | Objetivo en proceso | Velocidad |
|---|---|---|---|
IN | Disponible | Valor numérico o único | ◎ Muy rápido |
LIKE | Depende del patrón | Búsqueda de texto completo | △ Puede ser lento según las condiciones |
FIND_IN_SET | No disponible | Escaneo completo de la tabla | × Posiblemente lento |
Especialmente, FIND_IN_SET no puede utilizar índices y tiende a resultar en búsquedas completas. Al manejar grandes volúmenes de datos, es necesario revisar la estructura.
5. Precauciones y Mejores Prácticas
Los valores que contienen comas no son compatibles
La función FIND_IN_SET asume una lista de valores simples separada por comas. Por lo tanto, si los elementos individuales en la lista contienen comas por sí mismos, no funcionará como se espera.
Ejemplo de lo que NO se debe hacer:
SELECT FIND_IN_SET('1,2', '1,2,3,4'); -- Result: 1
Usarlo de esta forma hará que la cadena completa coincida incorrectamente, por lo que sólo úselo en estructuras donde pueda garantizar que los valores no contengan comas.
Problemas de rendimiento
FIND_IN_SET no puede usar índices y realiza un escaneo completo de todos los registros de la tabla (escaneo completo de la tabla). Por lo tanto, usarlo en tablas grandes puede resultar en velocidades de búsqueda extremadamente lentas.
Soluciones alternativas:
- En lugar de datos separados por comas, normalice las relaciones y gestionelas en una tabla separada.
- En entornos críticos de rendimiento, considere expansión de tabla temporal o estrategias de JOIN .
Ejemplo: Si crea y gestiona una tabla intermedia como user_favorites, puede realizar búsquedas de alta velocidad utilizando índices de la siguiente manera.
SELECT users.*
FROM users
JOIN user_favorites ON users.id = user_favorites.user_id
WHERE user_favorites.favorite_id = 3;
Desde la perspectiva de legibilidad y mantenibilidad
Aunque FIND_IN_SET puede parecer conveniente a primera vista, presenta los siguientes problemas:
- La consulta no es intuitiva (devuelve posiciones)
- Agregar o eliminar valores es difícil
- Es difícil garantizar la integridad de los datos (al colocar múltiples significados en una sola columna)
Por lo tanto, al priorizar la mantenibilidad del sistema y la integridad de los datos, revisar la propia estructura puede ser la «mejor práctica» en muchos casos.
Cuando realmente necesite usar FIND_IN_SET
También existen situaciones en las que debe manejar columnas separadas por comas, como en sistemas existentes o estructuras de datos de productos de terceros. En tales casos, tome las siguientes medidas.
- Aplique filtros primero para reducir el número de objetivos de búsqueda
- Evite errores de formato de cadena (comas dobles o espacios al inicio o final)
- Si es posible, realice procesamiento auxiliar en el lado de la aplicación
6. Preguntas frecuentes (FAQ)
¿Puede la función FIND_IN_SET usar índices?
No, la función FIND_IN_SET no puede usar índices. Esta función divide internamente la cadena y realiza una búsqueda, por lo que no puede beneficiarse de la optimización de índices de MySQL. Por lo tanto, al usarla en tablas grandes, existe la posibilidad de que la velocidad de búsqueda disminuya. En sistemas donde se requiere rendimiento, considere revisar la estructura o la normalización.
¿Funciona correctamente incluso si se mezclan números y cadenas?
Básicamente funciona, pero dado que las comparaciones se realizan como cadenas, mezclar números y cadenas puede dar lugar a un comportamiento no deseado. Por ejemplo, en los siguientes casos, ambos coincidirán con 3:
SELECT FIND_IN_SET(3, '1,2,3,4'); -- Result: 3
SELECT FIND_IN_SET('3', '1,2,3,4'); -- Result: 3
Sin embargo, en casos como FIND_IN_SET('03', '01,02,03'), las cadenas con ceros a la izquierda pueden no coincidir, por lo que es más seguro unificar los formatos de valor.
¿Existe alguna forma de buscar varios valores a la vez?
FIND_IN_SET solo acepta un valor de búsqueda único, así que si desea buscar registros que contengan «3 o 4», debe llamarlo varias veces con OR de la siguiente manera.
SELECT * FROM users
WHERE FIND_IN_SET('3', favorite_ids)
OR FIND_IN_SET('4', favorite_ids);
Alternativamente, para condiciones más complejas, considere construir dinámicamente declaraciones SQL en el lado de la aplicación o migrar a una tabla separada normalizada.
El uso de FIND_IN_SET degrada el rendimiento. ¿Cuáles son las contramedidas?
Las siguientes medidas son efectivas:
- Cambiar a un diseño de tabla normalizado
- Aplicar primero las condiciones de filtro para limitar los objetivos de búsqueda
- Utilícelo solo de forma limitada cuando el volumen de datos sea pequeño
- Considere migrar a representaciones de datos más estructuradas, como búsqueda de texto completo o tipo JSON
En MySQL moderno, la gestión de datos mediante el tipo JSON también es una opción. Por ejemplo, si gestionas la columna roles como un array JSON, puedes buscar de forma flexible y rápida con JSON_CONTAINS().
¿FIND_IN_SET se volverá obsoleto en el futuro?
Actualmente (MySQL 8.0), no hay indicios de que la función FIND_IN_SET esté obsoleta. Sin embargo, dado que la estructura de datos no normalizada (columnas separadas por comas) en sí no se recomienda, se espera que las oportunidades de uso disminuyan en el futuro. Si existe la posibilidad de revisar el diseño de la base de datos, es ideal diseñar asumiendo la normalización o la utilización del tipo JSON.
Resumen
Confirmando las características y ventajas de FIND_IN_SET
La función FIND_IN_SET es una función muy conveniente para buscar cadenas separadas por comas en MySQL. Es especialmente útil cuando deseas extraer registros que contengan un valor específico de una única columna que almacena múltiples valores. Se puede usar con una sintaxis sencilla, y su mayor fortaleza es la capacidad de comprobar una coincidencia exacta como un único valor, lo cual es difícil de lograr con cláusulas LIKE o IN.
Precauciones al usar
Por otro lado, existen limitaciones y precauciones como las siguientes, por lo que es importante no abusar de ella de forma casual.
- Los índices no funcionan (= las búsquedas se vuelven lentas)
- No es compatible con valores que contienen comas
- Asume una estructura no normalizada
- Solo puede buscar un valor único (para búsquedas múltiples se requieren condiciones
OR)
Comprender estas características es esencial para usarla en situaciones adecuadas.
Cuándo usarla y cuándo no
Situation | ¿Se debe usar? | Razón |
|---|---|---|
Datos de pequeña escala, pocas ocurrencias de búsqueda | ✅ OK para usar | Fácil de implementar y de bajo costo |
Estructura dependiente de los sistemas existentes | ✅ Usa de forma limitada | Efectivo cuando las modificaciones son difíciles |
Datos a gran escala, acceso de alta frecuencia | ❌ No recomendado | La degradación del rendimiento es significativa. |
Puede cambiar a una estructura normalizada | ❌ No recomendado | JOIN o tablas intermedias son más eficientes |
Cómo aplicarla en la práctica
- Conócela como una técnica para responder de manera flexible asumiendo la estructura de BD existente
- Úsala como base para decidir adoptar un diseño de datos normalizados en el futuro
- En lugar de usarla como solución temporal, comprende con precisión “qué hace esta función”
En particular, para quienes buscan un estilo de desarrollo que enfatice la mantenibilidad y legibilidad, es útil recordarla como una función que se usa temporalmente pero que se eliminará eventualmente.


