Есть ли хранимая функция mysql для создания slug из URL-адреса (или любого значения).
Итак, мой запрос может быть:
SELECT *, SLUG(url) FROM clients
Есть ли хранимая функция mysql для создания slug из URL-адреса (или любого значения).
Итак, мой запрос может быть:
SELECT *, SLUG(url) FROM clients
Это улучшенная версия ответа Роберта Росса. Это намного быстрее, поскольку позволяет избежать перебора всех допустимых символов и просто проверяет, сравнивая коды ASCII.
DROP FUNCTION IF EXISTS `slugify`;
DELIMITER ;;
CREATE DEFINER=`root`@`localhost`
FUNCTION `slugify`(dirty_string varchar(200))
RETURNS varchar(200) CHARSET latin1
DETERMINISTIC
BEGIN
DECLARE x, y , z Int;
Declare temp_string, new_string VarChar(200);
Declare is_allowed Bool;
Declare c, check_char VarChar(1);
set temp_string = LOWER(dirty_string);
Set temp_string = replace(temp_string, '&', ' and ');
Select temp_string Regexp('[^a-z0-9\-]+') into x;
If x = 1 then
set z = 1;
While z <= Char_length(temp_string) Do
Set c = Substring(temp_string, z, 1);
Set is_allowed = False;
If !((ascii(c) = 45) or (ascii(c) >= 48 and ascii(c) <= 57) or (ascii(c) >= 97 and ascii(c) <= 122)) Then
Set temp_string = Replace(temp_string, c, '-');
End If;
set z = z + 1;
End While;
End If;
Select temp_string Regexp("^-|-$|'") into x;
If x = 1 Then
Set temp_string = Replace(temp_string, "'", '');
Set z = Char_length(temp_string);
Set y = Char_length(temp_string);
Dash_check: While z > 1 Do
If Strcmp(SubString(temp_string, -1, 1), '-') = 0 Then
Set temp_string = Substring(temp_string,1, y-1);
Set y = y - 1;
Else
Leave Dash_check;
End If;
Set z = z - 1;
End While;
End If;
Repeat
Select temp_string Regexp("--") into x;
If x = 1 Then
Set temp_string = Replace(temp_string, "--", "-");
End If;
Until x <> 1 End Repeat;
If LOCATE('-', temp_string) = 1 Then
Set temp_string = SUBSTRING(temp_string, 2);
End If;
Return temp_string;
END;;
DELIMITER ;
Я взял Slugifier с http://nastyhabit.wordpress.com/2008/09/25/mysql-slug-maker-function-aka-the-slugifier/
И изменил его, чтобы не включать "-" в начале (у нас был "$" в качестве первого символа)
Вот мой результат:
DROP FUNCTION IF EXISTS `slugify`;
DELIMITER ;;
CREATE DEFINER=`root`@`localhost`
FUNCTION `slugify`(dirty_string varchar(200))
RETURNS varchar(200) CHARSET latin1
DETERMINISTIC
BEGIN
DECLARE x, y , z Int;
Declare temp_string, allowed_chars, new_string VarChar(200);
Declare is_allowed Bool;
Declare c, check_char VarChar(1);
set allowed_chars = "abcdefghijklmnopqrstuvwxyz0123456789-";
set temp_string = dirty_string;
Select temp_string Regexp('&') Into x;
If x = 1 Then
Set temp_string = replace(temp_string, '&', ' and ');
End If;
Select temp_string Regexp('[^a-z0-9]+') into x;
If x = 1 then
set z = 1;
While z <= Char_length(temp_string) Do
Set c = Substring(temp_string, z, 1);
Set is_allowed = False;
Set y = 1;
Inner_Check: While y <= Char_length(allowed_chars) Do
If (strCmp(ascii(Substring(allowed_chars,y,1)), Ascii(c)) = 0) Then
Set is_allowed = True;
Leave Inner_Check;
End If;
Set y = y + 1;
End While;
If is_allowed = False Then
Set temp_string = Replace(temp_string, c, '-');
End If;
set z = z + 1;
End While;
End If;
Select temp_string Regexp("^-|-$|'") into x;
If x = 1 Then
Set temp_string = Replace(temp_string, "'", '');
Set z = Char_length(temp_string);
Set y = Char_length(temp_string);
Dash_check: While z > 1 Do
If Strcmp(SubString(temp_string, -1, 1), '-') = 0 Then
Set temp_string = Substring(temp_string,1, y-1);
Set y = y - 1;
Else
Leave Dash_check;
End If;
Set z = z - 1;
End While;
End If;
Repeat
Select temp_string Regexp("--") into x;
If x = 1 Then
Set temp_string = Replace(temp_string, "--", "-");
End If;
Until x <> 1 End Repeat;
If LOCATE('-', temp_string) = 1 Then
Set temp_string = SUBSTRING(temp_string, 2);
End If;
Return temp_string;
END;;
DELIMITER ;
Работает хорошо, Но! Это довольно медленно. Если вы пытаетесь выбрать что-то из этого, вы добавите к запросу около 1000% времени по сравнению с выбором индексированного столбца с предварительным слаггингом.
Задержка для 500 результатов составила 0,27 секунды. Не задержка (через mysql) составила 0,00003 секунды.
Однако для вставки данных эта функция отлично подойдет! Просто вставьте отложенные данные в предварительно определенный столбец (ЭТО ИНДЕКСИРОВАНО, так почему бы вам не выбрать что-то, что отсортировано?)
Примечание. Текст, который нужно «слагифицировать», должен быть сначала в нижнем регистре, так как эта функция не обрабатывает буквы верхнего регистра (преобразует их в «-»).
Я не уверен, рекомендую ли я делать это в SQL, но вот парень, который сделал для вас функцию под названием «slugify»:
http://nastyhabit.wordpress.com/2008/09/25/mysql-slug-maker-function-aka-the-slugifier/
Я добавил несколько строк в функцию, опубликованную Робертом, чтобы убедиться, что слаг всегда уникален.
Это происходит прямо перед концом функции, как вы можете видеть ниже. Убедитесь, что вы указываете имя таблицы без скобок [].
SELECT COUNT(*) INTO i FROM [table name goes here] WHERE slug LIKE CONCAT('%',temp_string,'%');
If i > 0 Then
Set temp_string = CONCAT(temp_string,'-',i+1);
End If;
Return temp_string;
END;;
DELIMITER ;
Я реализовал свою собственную функцию slug, поддерживающую символы с диакритическими знаками, любой вклад в нее приветствуется.
https://github.com/falcacibar/mysql-routines-collection/blob/master/generate_slug.func.sql
Не стесняйтесь публиковать любые предложения, ошибки или любую проблему или вклад на github или здесь, но лучше github
tr
в вашей рутине? ах, хорошо, я нашел это, я думал, что это суть, но это репо.
- person ygaradon; 09.04.2014
Мои два цента:
CREATE FUNCTION slugify(str VARCHAR(255))
RETURNS VARCHAR(255)
LANGUAGE SQL
DETERMINISTIC
NO SQL
SQL SECURITY INVOKER
BEGIN
DECLARE slug, allowed_chars VARCHAR(255);
DECLARE current_char VARCHAR(1);
DECLARE pos, len INT;
-- Add here custom replaces
SET slug = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(LOWER(TRIM(str)), 'ú', 'u'), 'ç', 'c'), 'ğ', 'g'), ' ', '-'), 'é', 'e'), 'è', 'e'), 'ë', 'e'), 'í', 'i'), 'î', 'i'), 'ò', 'o'), 'õ', 'o'), 'ù', 'u'), 'â', 'a'), 'ã', 'a'), 'ö', 'o'), 'ş', 's'), 'ì', 'i'), 'æ', 'ae'), 'à', 'a'), 'ê', 'e'), 'ñ', 'n'), 'ý', 'y'), 'ô', 'o'), 'û', 'u'), 'ï', 'i'), 'ó', 'o'), 'ü', 'u'), 'á', 'a'), 'å', 'a'), 'ä', 'a'), '_', '-');
SET pos = 1;
SET len = CHAR_LENGTH(slug);
SET allowed_chars = 'abcdefghijklmnopqrstuvwxyz0123456789-';
-- Remove not allowed characters
WHILE pos <= len DO
SET current_char = SUBSTRING(slug, pos, 1);
IF LOCATE(current_char, allowed_chars) = 0 THEN
SET slug = REPLACE(slug, current_char, '');
END IF;
SET pos = pos + 1;
END WHILE;
-- Squish dashes
WHILE LOCATE('--', slug) > 0 DO
SET slug = REPLACE(slug, '--', '-');
END WHILE;
RETURN slug;
END;
Я использовал этот код в течение длительного времени. Публикация здесь, чтобы помнить и, возможно, помочь кому-то в наши дни
просто скопируйте/вставьте этот фрагмент на вкладку запросов MySQL и запустите его.
-- предположим, что ваш пользователь root, а хост - localhost. Если нет, измените значение пользователя root и localhost, чтобы они соответствовали вашим
CREATE DEFINER=`root`@`localhost` FUNCTION `toSlug`(
`s` NVARCHAR(500)
)
RETURNS varchar(500) CHARSET utf8
LANGUAGE SQL
DETERMINISTIC
CONTAINS SQL
SQL SECURITY DEFINER
COMMENT ''
RETURN REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(
REPLACE(REPLACE(LOWER(TRIM(s)),
':', ''), ')', ''), '(', ''), ',', ''), '\\', ''), '/', ''), '"', ''), '?', ''),
"'", ''), '&', ''), '!', ''), '.', ''), ' ', '-'), '--', '-'), '--', '-'),'ù','u'),
'ú','u'),'û','u'),'ü','u'),'ý','y'),'ë','e'),'à','a'),'á','a'),'â','a'),'ã','a'),
'ä','a'),'å','a'),'æ','a'),'ç','c'),'è','e'),'é','e'),'ê','e'),'ë','e'),'ì','i'),
'í','i'),'ě','e'), 'š','s'), 'č','c'),'ř','r'), 'ž','z'), 'î','i'),'ï','i'),'ð','o'),
'ñ','n'),'ò','o'),'ó','o'),'ô','o'),'õ','o'),'ö','o'),'ø','o'),'%', '')
Это создаст функцию, которую вы можете вызвать, например:
UPDATE my_table set my_new_slug_column = toSlug(my_any_column_id_like_to_slug);
Он получит значение my_any_column_id_like_to_slug
и перепишет/скопирует в my_new_slug_column
в таблице my_table
Вы также можете преобразовать столбец с текстом в его слаг, например:
UPDATE my_table set my_column = toSlug(my_column);
В этом случае будет обновлен сам my_column, например. «Боже мой» будет «о боже мой»