Extracting and replacing text with MySQL regular expressions
Entre las múltiples carencias de MySQL se encuentran (en parte) las expresiones regulares. Tiene el operador REGEXP que permite saber si una cadena casa con una expresión regular concreta, pero no permite extraer fragmentos de esa cadena ni reemplazar la cadena encontrada con otro texto.
Esta es una función para MySQL que hace precisamente eso valiéndose del propio operador REGEXP.
Es una chapuza rápida, probablemente no sea conveniente utilizarlo en determinados casos ya que debería ser bastante lenta (hace una llamada a REGEXP por cada subcadena contenida dentro de la cadena a buscar , por ejemplo, para buscar en ‘abc’, comprobaría la expresión regular con:
a
ab
abc
b
bc
c
Si llamas a esta función dentro del select o el where de una consulta con muchos registros puede ser realmente ineficiente. He añadido DETERMINISTIC ya que la función es determinista, y en algunos casos de esta manera se puede ahorrar bastante tiempo de proceso.
Uso:
Devuelve la cadena más grande dentro de ‘cadena’ que coincida con ‘re’, por ejemplo
SELECT substring_regexp(‘jket5657twr’, ‘[0-9]+’, NULL) –> 5657
En este caso hay varias cadenas que coinciden con [0-9]+, por ejemplo 565, 5 , 657, … He decidido hacerlo de forma que devuelva la mayor de ellas.
Para sustituir, se pasa como parámetro la cadena de sustitución, en vez de NULL:
SELECT substring_regexp(‘jket5657twr’, ‘[0-9]+’, ‘HOLA’) –> jketHOLAtwr
Código:
DELIMITER $$
DROP FUNCTION IF EXISTS `substring_regexp` $$
CREATE FUNCTION `substring_regexp`(cadena text, re text, sustitucion text) RETURNS text CHARSET latin1 DETERMINISTIC
BEGIN
declare a, b, tam int;
declare subcadena, retorno text;
set tam = 0;
set retorno = '';
set a = 1;
inicio: WHILE a <= length(cadena) DO
set b = a;
final: WHILE b <= length(cadena) DO
set subcadena = substring(cadena, a, b-a+1);
if subcadena regexp concat('^', re, '$') and length(subcadena) > tam then
set tam = length(subcadena);
if sustitucion is null then
set retorno = subcadena;
else
set retorno = replace(cadena, subcadena, sustitucion);
end if;
end if;
set b = b+1;
END WHILE final;
set a = a+1;
END WHILE inicio;
return retorno;
END $$
DELIMITER ;