REGEXP

El operador REGEXP permite filtrar filas en una cláusula WHERE usando expresiones regulares. Es la forma más directa de aplicar patrones regulares en MySQL y, junto con su sinónimo RLIKE, constituye la puerta de entrada al uso de expresiones regulares en consultas SQL.

Cuando LIKE se queda corto porque necesitas buscar patrones complejos como dígitos, alternativas, repeticiones o formatos específicos, REGEXP es la herramienta adecuada.

Sintaxis

expresion REGEXP patron
 
-- Sinónimo (idéntico comportamiento)
expresion RLIKE patron
 
-- Negación
expresion NOT REGEXP patron
expresion NOT RLIKE patron

El operador devuelve 1 si la expresión coincide con el patrón, 0 si no coincide y NULL si alguno de los operandos es NULL. A diferencia de LIKE, que exige que el patrón coincida con la cadena completa, REGEXP devuelve coincidencia si el patrón se encuentra en cualquier parte de la cadena. Si necesitas que coincida con toda la cadena, debes usar las anclas ^ y $.

Comportamiento básico

Comencemos con un ejemplo sencillo. Supón que tienes una tabla productos y quieres encontrar todos los que contienen la palabra "Pro" en su nombre:

SELECT nombre, precio
FROM productos
WHERE nombre REGEXP 'Pro';
nombreprecio
iPhone 15 Pro1299.99
iPhone 15 Pro Max1499.99
MacBook Pro 162499.00
iPad Pro 12.91199.00

Esto podría lograrse con LIKE '%Pro%', pero la ventaja de REGEXP aparece cuando los patrones se complican. Por ejemplo, buscar productos cuyo nombre contenga un número seguido de una unidad de medida:

SELECT nombre, precio
FROM productos
WHERE nombre REGEXP '[0-9]+(GB|TB|MHz|W|mm)';
nombreprecio
SSD Samsung 1TB109.99
RAM DDR5 32GB89.99
Cargador USB-C 65W35.99
Monitor 27" 144MHz349.00

Este patrón busca uno o más dígitos seguidos de una de las unidades listadas. Expresar esto con LIKE requeriría múltiples condiciones OR, y aun así no podrías asegurar que los dígitos están justo antes de la unidad.

RLIKE como sinónimo

RLIKE es un sinónimo exacto de REGEXP. MySQL lo incluye por compatibilidad con otros sistemas de bases de datos. Ambos producen exactamente el mismo resultado:

-- Estas dos consultas son idénticas
SELECT nombre FROM productos WHERE nombre REGEXP '^Mac';
SELECT nombre FROM productos WHERE nombre RLIKE '^Mac';

Elige el que te resulte más legible. En la documentación oficial y en la comunidad MySQL, REGEXP es el más utilizado.

Sensibilidad a mayúsculas y minúsculas

Por defecto, REGEXP en MySQL es insensible a mayúsculas y minúsculas cuando la collation de la columna es case-insensitive (que es el caso habitual con utf8mb4_0900_ai_ci):

SELECT nombre FROM productos WHERE nombre REGEXP 'iphone';
nombre
iPhone 15 Pro
iPhone 15 Pro Max
iPhone 14

Aunque el patrón está en minúsculas, coincide con "iPhone" porque la comparación es case-insensitive. Si necesitas forzar una comparación sensible a mayúsculas, usa la palabra clave BINARY:

-- Sensible a mayúsculas: 'iphone' NO coincide con 'iPhone'
SELECT nombre FROM productos WHERE nombre REGEXP BINARY 'iphone';

Esta consulta no devuelve resultados porque ningún nombre tiene "iphone" exactamente en minúsculas. Si cambias el patrón a 'iPhone', sí encontrarás coincidencias.

SELECT nombre FROM productos WHERE nombre REGEXP BINARY 'iPhone';
nombre
iPhone 15 Pro
iPhone 15 Pro Max
iPhone 14

NOT REGEXP

La negación NOT REGEXP es fundamental para encontrar filas que no cumplen un patrón. Esto es especialmente útil para detectar datos que no se ajustan al formato esperado:

-- Encontrar productos sin código de referencia válido
SELECT nombre, referencia
FROM productos
WHERE referencia NOT REGEXP '^[A-Z]{2,3}-[0-9]{3,5}$';
nombrereferencia
Producto de pruebatest
Oferta especialNULL
Cable genérico12345

La consulta identifica productos cuya referencia no sigue el formato estándar de dos o tres letras mayúsculas, un guion y de tres a cinco dígitos.

Caso práctico: validar emails

Uno de los usos más habituales de REGEXP es validar formatos de datos. Para filtrar clientes con emails que parecen válidos:

SELECT nombre, email
FROM clientes
WHERE email REGEXP '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$';
nombreemail
María Garcíamaria.garcia@gmail.com
Carlos Lópezcarlos.lopez@empresa.es
Ana Martíneza.martinez+trabajo@outlook.com

Y para encontrar los que tienen emails potencialmente inválidos:

SELECT nombre, email
FROM clientes
WHERE email NOT REGEXP '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$'
   OR email IS NULL;
nombreemail
Pedro Ruizpedro@@correo.com
Test Userno-es-un-email
Laura VegaNULL

Recuerda que REGEXP devuelve NULL cuando algún operando es NULL, y NOT NULL sigue siendo NULL, por lo que necesitas la condición OR email IS NULL explícita para capturar esos casos.

Caso práctico: buscar teléfonos por formato

Supón que tu tabla de clientes almacena teléfonos en distintos formatos y necesitas encontrar los que siguen el patrón español:

-- Teléfonos móviles españoles: empiezan por 6 o 7, 9 dígitos total
SELECT nombre, telefono
FROM clientes
WHERE telefono REGEXP '^(\\+34)?[67][0-9]{8}$';
nombretelefono
María García612345678
Carlos López+34678901234
Ana Martínez712345678
-- Teléfonos fijos españoles: empiezan por 9, 9 dígitos total
SELECT nombre, telefono
FROM clientes
WHERE telefono REGEXP '^(\\+34)?9[0-9]{8}$';
nombretelefono
Pedro Ruiz912345678
Laura Vega+34934567890

Estos patrones te permiten segmentar fácilmente los clientes según el tipo de teléfono que han proporcionado.

Caso práctico: buscar códigos de producto

En un sistema de inventario, los productos suelen tener códigos con formatos específicos según la categoría. Con REGEXP puedes buscar por patrones de código:

-- Productos de electrónica: código empieza por ELE seguido de 4 dígitos
SELECT nombre, codigo, precio
FROM productos
WHERE codigo REGEXP '^ELE-[0-9]{4}$';
nombrecodigoprecio
iPhone 15 ProELE-00121299.99
Samsung Galaxy S24ELE-0025899.99
MacBook Air M3ELE-01081399.00
-- Buscar productos de cualquier categoría con código de 4+ dígitos
SELECT nombre, codigo
FROM productos
WHERE codigo REGEXP '^[A-Z]{2,4}-[0-9]{4,}$'
ORDER BY codigo;
nombrecodigo
Camiseta algodónROP-1001
Pantalón vaqueroROP-1025
Balón fútbolDEP-2001
iPhone 15 ProELE-0012
Sartén antiadherenteHOG-3010

Caso práctico: validar códigos postales

Distintos países tienen formatos de código postal diferentes. Con REGEXP puedes validar según el país:

SELECT
    nombre,
    pais,
    codigo_postal,
    CASE
        WHEN pais = 'España' AND codigo_postal REGEXP '^[0-5][0-9]{4}$' THEN 'Válido'
        WHEN pais = 'México' AND codigo_postal REGEXP '^[0-9]{5}$' THEN 'Válido'
        WHEN pais = 'Argentina' AND codigo_postal REGEXP '^[A-Z][0-9]{4}[A-Z]{3}$' THEN 'Válido'
        ELSE 'Revisar'
    END AS estado_cp
FROM clientes;
nombrepaiscodigo_postalestado_cp
María GarcíaEspaña28001Válido
Juan PérezMéxico06600Válido
Roberto SilvaArgentinaC1425DKEVálido
Laura DíazEspaña99001Revisar

El código postal 99001 no es válido en España porque las provincias españolas van del 01 al 52, y el primer dígito no puede ser mayor que 5.

Manejo de NULL

Cuando la expresión o el patrón son NULL, REGEXP devuelve NULL en lugar de 0 o 1. Esto es consistente con el comportamiento de SQL ante valores nulos, pero puede causar resultados inesperados si no lo tienes en cuenta:

SELECT
    nombre,
    telefono,
    telefono REGEXP '^[0-9]+$' AS es_numerico
FROM clientes;
nombretelefonoes_numerico
María García6123456781
Carlos López+346789012340
Pedro RuizNULLNULL

Para Pedro Ruiz, el resultado es NULL, no 0. Si usas esta expresión en un WHERE, las filas con NULL no se incluirán ni con REGEXP ni con NOT REGEXP. Si necesitas incluirlas, maneja el NULL explícitamente:

SELECT nombre, telefono
FROM clientes
WHERE telefono REGEXP '^[0-9]+$'
   OR telefono IS NULL;

Combinación con otras funciones

REGEXP se combina frecuentemente con CASE, IF y funciones de agregación para analizar datos:

-- Contar clientes por tipo de email
SELECT
    COUNT(*) AS total,
    SUM(IF(email REGEXP '@gmail\\.com$', 1, 0)) AS gmail,
    SUM(IF(email REGEXP '@(outlook|hotmail)\\.com$', 1, 0)) AS microsoft,
    SUM(IF(email REGEXP '@yahoo\\.(com|es)$', 1, 0)) AS yahoo,
    SUM(IF(email NOT REGEXP '@(gmail|outlook|hotmail|yahoo)\\.', 1, 0)) AS otros
FROM clientes
WHERE email IS NOT NULL;
totalgmailmicrosoftyahoootros
24895673155

Esta consulta genera un resumen de los proveedores de email de tus clientes en una sola pasada, algo que sería mucho más verboso con condiciones LIKE.

-- Agrupar productos por patrón de código
SELECT
    CASE
        WHEN codigo REGEXP '^ELE-' THEN 'Electrónica'
        WHEN codigo REGEXP '^ROP-' THEN 'Ropa'
        WHEN codigo REGEXP '^HOG-' THEN 'Hogar'
        WHEN codigo REGEXP '^DEP-' THEN 'Deportes'
        ELSE 'Otros'
    END AS categoria,
    COUNT(*) AS cantidad,
    ROUND(AVG(precio), 2) AS precio_medio
FROM productos
GROUP BY categoria
ORDER BY cantidad DESC;
categoriacantidadprecio_medio
Electrónica45687.50
Ropa3845.20
Hogar2589.30
Deportes1862.75
Otros1233.90

En el siguiente artículo veremos REGEXP_LIKE como la función equivalente con opciones adicionales.

Escrito por Eduardo Lázaro