хранимая функция mySQL для создания слаг - PullRequest
12 голосов
/ 23 марта 2011

Существует ли хранимая функция mysql для создания слага из URL (или любого другого значения).

Так что мой запрос может быть:

SELECT *, SLUG(url) FROM clients

Ответы [ 5 ]

25 голосов
/ 07 декабря 2011

Это обновленная версия вышеуказанной функции. Это намного быстрее, поскольку позволяет избежать циклического прохождения всех разрешенных символов и просто проверяет сравнение кодов 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 ;
7 голосов
/ 23 марта 2011

Я взял 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 результатов .27 секунд Non-slugged (через mysql) было .00003 секунд

Для вставки данных эта функция будет работать отлично! Просто вставьте заблокированные данные в предварительно определенный столбец (КОТОРЫЙ ИНДЕКСИРУЕТСЯ, так как почему бы вам не выбрать что-то отключенное?)

Примечание. Текст, который должен быть «врезан», должен быть вначале должен быть в нижнем регистре, так как эта функция не обрабатывает буквы в верхнем регистре (преобразует их в «-»).

2 голосов
/ 20 мая 2013

Я реализовал свою собственную функцию slug, поддерживающую акцентированные символы, любой вклад в нее приветствуется.

https://github.com/falcacibar/mysql-routines-collection/blob/master/generate_slug.func.sql

Не стесняйтесь размещать любые предложения, ошибки или любые проблемы или вклады на github или здесь , но лучше github

2 голосов
/ 25 октября 2011

Я добавил несколько строк в функцию, которую опубликовал Роберт, чтобы убедиться, что слаг всегда уникален.

Это происходит прямо перед концом функции, как вы можете видеть ниже.Убедитесь, что вы указали имя таблицы без скобок [].

    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 ;
2 голосов
/ 23 марта 2011

Я не уверен, что рекомендую делать это в SQL, но вот парень, который сделал для вас функцию под названием «slugify»:

http://nastyhabit.wordpress.com/2008/09/25/mysql-slug-maker-function-aka-the-slugifier/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...