Cómo generar slugs únicos con un trigger en mysql

Trigger para crear slug únicos en MySQL automáticamente

A la hora de crear bases de datos, muchas veces terminamos echando mano de las ids como identificador. Pero qué pasaría si pudieras utilizar un string directamente para encontrar un registro en la base de datos y que pudieras generar slugs únicos en mysql con un trigger que lo hiciera por tí al insertar algo.

Lo primero, un trigger es una acción que se ejecuta antes o después de insertar o actualizar un registro en la base de datos. Estos son bastante útiles, ya que son como funciones, en las que puedes indicar coger algunos datos insertados, procesarlos y añadirlos a una de las celdas por ejemplo.

Hablaré más a fondo sobre los triggers en mysql un poco más adelante.

Cómo generar slugs únicos en Mysql automáticamente

Si lo has hecho alguna vez, es posible que hayas terminado echando mano de algún script, clase o función que revise si ese mismo valor existe en la base de datos, lo procese, y te devuelva el siguiente valor.

En este caso la idea es crear cadenas de carácteres basadas en una de las celdas que insertemos, pero que a su vez sean únicas y no se solapen si ponemos el mismo título en dos filas.

El ejemplo es el siguiente, supón que quieres guardar nombres, y quieres que cada nombre se convierta en una url. Si dos personas se llaman María García lo que quieres es esto:

  • maria-garcia
  • maria-garcia-1
  • maria-garcia-2

Y por supuesto que se ejecute en base al nombre que estás insertando, y se guarde solo en la columna slug.

La función para insertar en mysql sería la siguiente:

declare new_slug varchar(255);  
declare slug_counter int;
set slug_counter = 1;
set new_slug = new.title;
SET new_slug = LOWER(TRIM(new_slug));
SET new_slug = REPLACE(new_slug, ':', '');
SET new_slug = REPLACE(new_slug, ')', '');
SET new_slug = REPLACE(new_slug, '(', '');
SET new_slug = REPLACE(new_slug, ',', '');
SET new_slug = REPLACE(new_slug, '', ');
SET new_slug = REPLACE(new_slug, "?", ');
SET new_slug = REPLACE(new_slug, '', '');
SET new_slug = REPLACE(new_slug, '&', '');
SET new_slug = REPLACE(new_slug, '!', '');
SET new_slug = REPLACE(new_slug, '.', '');
SET new_slug = REPLACE(new_slug, '€', '');
SET new_slug = REPLACE(new_slug, 'euro;', '');
SET new_slug = REPLACE(new_slug, ' ', '-');
SET new_slug = REPLACE(new_slug, '--', '-');
SET new.slug = new_slug;

while exists (select true from test where slug = new.slug) do
set new.slug = concat(new_slug, '-', slug_counter);
set slug_counter = slug_counter + 1;
end while;

 

Léete también  JOINS en MySQL bien explicado. Todo lo que necesitas saber

Como ves, lo que hacemos es sustituir algunos carácteres que podrían aparecer en el campo, para que no se vuelva loco y quite lo que sobra.

En un principio el script no es perfecto, y seguramente se pueden añadir más optimizaciones a la hora de generar strings dependiendo de lo que necesites. Te invito a que dejes tu sugerencia para mejorarlo en los comentarios.

La explicación es sencilla

  • Al principio definimos la variable new_slug le damos un formato de celda, y por último le damos el valor del campo que queremos convertir con el =columna.
  • Lo siguiente es crear una variable slug_counter para llevar la cuenta de las veces que aparece, y luego indicamos que el contador empieza en 1 (para evitar errores al contar).
  • Lo siguiente es reemplazar todos los carácteres que nos sobran del string que estamos insertando y limpiar la cadena con el formato que nos interesa.
  • Por último, en el while revisamos si el slug que nos da después de la limpieza ya existe, y si es así, le sumamos uno al contador y volvemos a probar a insertarlo.

Esta última función while, estará intentando insertarlo hasta que de con el primer valor que no exista ya. Esto significa que si tienes por ejemplo 5, y borras el 3, el siguiente ocupará este lugar.

Para que no te hagas mucho lío, te dejo aquí el script sql que puedes ejecutar directamente sobre la base de datos, pero recuerda cambiar el nombre de la tabla, y también el title por la celda a convertir.

CREATE TRIGGER `slugify` BEFORE INSERT ON `nombres` FOR EACH ROW BEGIN
declare new_slug varchar(255);  
declare slug_counter int;
set slug_counter = 1;
set new_slug = new.title;
SET new_slug = LOWER(TRIM(new_slug));
SET new_slug = REPLACE(new_slug, ':', '');
SET new_slug = REPLACE(new_slug, ')', '');
SET new_slug = REPLACE(new_slug, '(', '');
SET new_slug = REPLACE(new_slug, ',', '');
SET new_slug = REPLACE(new_slug, '.', '');
SET new_slug = REPLACE(new_slug, "?", '');
SET new_slug = REPLACE(new_slug, ';', '');
SET new_slug = REPLACE(new_slug, '&', '');
SET new_slug = REPLACE(new_slug, '!', '');
SET new_slug = REPLACE(new_slug, '.', '');
SET new_slug = REPLACE(new_slug, '€', '');
SET new_slug = REPLACE(new_slug, 'euro;', '');
SET new_slug = REPLACE(new_slug, ' ', '-');
SET new_slug = REPLACE(new_slug, '--', '-');
SET new_slug = REPLACE(new_slug, '--', '-');
SET new_slug = REPLACE(new_slug, '--', '-');
SET new.slug = new_slug;

while exists (select true from test where slug = new.slug) do
set new.slug = concat(new_slug, '-', slug_counter);
set slug_counter = slug_counter + 1;
end while;
END
;

Puedes ejecutarlo directamente en tu tabla teniendo en cuenta tener la columna slug creada, o guardarlo como .sql y usarlo desde algún script.

Léete también  Cómo solucionar MySQL Error 1153 - Got a packet bigger than 'max_allowed_packet' bytes

También te lo dejo en mi repositorio de git de querys mysql por si quieres hacer alguna aportación directamente ahí.

Como ves es la mar de sencillo, y lo mejor es que se irán generando cada vez que insertes algo, por lo que dará igual del lenguaje que uses para gestionar la base de datos, y no te tendrás que preocupar por duplicados ni nada.

¿Tienes algún método mejor o alguna actualización para el script? Deja un comentario y lo pongo.


AYUDANOS a poder seguir dando respuestas. Te podemos echar una mano y tú también a nosotros, símplemente dale a me gusta.