ฟังก์ชั่น mySQL Stored เพื่อสร้างตัวบุ้ง

มีฟังก์ชั่น mysql ที่เก็บไว้เพื่อสร้างกระสุนจาก url (หรือค่าใด ๆ จริงๆ)

ดังนั้นคำถามของฉันอาจเป็น:

SELECT *, SLUG(url) FROM clients

person Robert Ross    schedule 23.03.2011    source แหล่งที่มา
comment
อาจซ้ำกันของ stackoverflow.com/ คำถาม/3690432/   -  person Brad    schedule 23.03.2011
comment
ที่ทำงานได้ในหลายภาษาโดยอาศัยการทับศัพท์ stackoverflow.com/questions/30570865/   -  person juslintek    schedule 02.06.2015


คำตอบ (7)


นี่เป็นคำตอบของ Robert Ross รุ่นปรับปรุง เร็วกว่ามากเนื่องจากหลีกเลี่ยงการวนซ้ำอักขระที่อนุญาตทั้งหมด และเพียงตรวจสอบโดยการเปรียบเทียบรหัส 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 ;
person Gregg    schedule 07.12.2011
comment
ขอบคุณ นี่เร็วกว่ามาก! คุณมีวิธีแก้ปัญหาที่เร็วกว่าสำหรับคำตอบด้านล่างเพื่อตรวจสอบดูว่าทากมีลักษณะเฉพาะหรือไม่ - person Brad; 24.02.2012
comment
พระเจ้าช่วย! เพื่อน ถ้าคุณเป็นผู้หญิง ฉันจะแต่งงานกับคุณ! อันนี้เจ๋งมาก! ทำได้ดีมาก ทำได้ดีมาก! ขอบคุณมาก! - person Nikola Svitlica; 23.11.2015

ฉันใช้ 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 ;

ทำงานได้ดี แต่! มันค่อนข้างช้า หากคุณกำลังพยายามเลือกบางอย่างนอกเหนือจากนี้ คุณจะเพิ่มเวลาประมาณ 1,000% ในการสืบค้น เมื่อเทียบกับการเลือกคอลัมน์ที่ใส่ไว้ล่วงหน้าที่มีการจัดทำดัชนีไว้

Slugged สำหรับผลลัพธ์ 500 รายการคือ .27 วินาที Non-slugged (ผ่าน mysql) คือ .00003 วินาที

สำหรับการแทรกข้อมูล ฟังก์ชั่นนี้จะใช้งานได้ดีมาก! เพียงแทรกข้อมูลที่กระสุนเข้าไปในคอลัมน์ที่กำหนดไว้ล่วงหน้า (นั่นคือ INDEXED เพราะเหตุใดคุณจึงไม่เลือกสิ่งที่กระสุน?)

หมายเหตุ: ข้อความที่จะ 'slugified' จะต้องเป็นตัวพิมพ์เล็กก่อน เนื่องจากฟังก์ชันนี้ไม่รองรับตัวอักษรตัวพิมพ์ใหญ่ (แปลงเป็น '-')

person Robert Ross    schedule 23.03.2011
comment
ได้รับข้อผิดพลาดกับต้นฉบับ - อันนี้ใช้งานได้ทันทีโดยไม่ต้องคัดลอก/วาง ยิ้ม - ขอบคุณ - person Alvin; 03.09.2011
comment
มันจะลบอักขระตัวแรกสำหรับฉัน - person Dennis; 26.09.2011
comment
ฟังก์ชั่นข้างต้นจะมีปัญหาเมื่อมีการส่งคำสองคำเข้าไป ( นิวซีแลนด์ ) กลายเป็น ew-ealand ฟังก์ชั่นที่จัดทำโดย Greg ด้านล่างไม่มีปัญหานี้ - person Tim; 02.05.2012
comment
ยังคงช้าอยู่ - หนึ่งชั่วโมงครึ่งเพื่อให้ได้ทาก 50,000 แถว - person Dave Hilditch; 02.07.2015
comment
การเปลี่ยนชุด temp_string = Dirt_string; เพื่อตั้งค่า temp_string = LCASE(dirty_string); มีประโยชน์กับฉัน - person John Corry; 11.11.2016

ฉันไม่แน่ใจว่าฉันอยากจะแนะนำให้ทำเช่นนี้ใน SQL หรือไม่ แต่นี่คือผู้ชายที่สร้างฟังก์ชันให้คุณที่เรียกว่า "slugify":

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

person Brad    schedule 23.03.2011
comment
ฉันพบสิ่งนั้นและวิธีแก้ปัญหาของเขาดูไม่น่าดึงดูด... บางทีฉันอาจนำแนวคิดบางอย่างไปใช้ได้ ทำไมคุณไม่แนะนำมันล่ะ? - person Robert Ross; 23.03.2011
comment
ฉันคิดว่ามันจะง่ายกว่าถ้านำไปใช้กับเลเยอร์แอปพลิเคชันของสิ่งต่าง ๆ ใน PHP ในกรณีของคุณ อย่างน้อยก็สำหรับฉัน ฉันไม่ใช่คนหวือหวา SQL สำหรับการจัดรูปแบบข้อมูล (ซึ่งก็คือสิ่งนี้) ฉันชอบปล่อยให้สิ่งนั้นขึ้นอยู่กับผู้บริโภคของข้อมูล คุณควรทำการทดสอบความเร็วเพื่อดูว่าวิธีใดมีประสิทธิภาพมากกว่า ฉันคิดว่านั่นจะเป็นตัวกำหนดว่าวิธีใดเหมาะสมกับกรณีของคุณ - person Brad; 23.03.2011
comment
ใช่แล้ว นั่นคือสิ่งที่ฉันกำลังทำอยู่ พยายามค้นหาตัวเลขมาตรฐานและตัดสินใจจากตรงนั้น - person Robert Ross; 23.03.2011
comment
บางทีตรรกะอาจไม่ได้อยู่ใน PHP หรือ Wordpress และนี่คือการจัดการ SQL จำนวนมาก การสร้างรูทีน PHP ทีละบรรทัดเพื่อจุดประสงค์นี้คงจะเป็นเรื่องที่น่าอึดอัดใจ - person Orden; 18.12.2018

ฉันได้เพิ่มบรรทัดบางบรรทัดในฟังก์ชันที่ Robert โพสต์เพื่อให้แน่ใจว่าทากจะไม่ซ้ำกันเสมอ

สิ่งนี้ดำเนินไปก่อนที่จะสิ้นสุดฟังก์ชัน ดังที่คุณเห็นด้านล่าง ตรวจสอบให้แน่ใจว่าคุณระบุชื่อตารางโดยไม่มีวงเล็บ []

    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 ;
person Eduardo J Garcia    schedule 25.10.2011

ฉันได้ใช้ฟังก์ชันกระสุนของตัวเองเพื่อสนับสนุนอักขระที่มีสำเนียง ยินดีต้อนรับการมีส่วนร่วมใดๆ

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

อย่าลังเลที่จะโพสต์ข้อเสนอแนะ ข้อบกพร่อง หรือปัญหาใดๆ หรือการสนับสนุนบน GitHub หรือที่นี่ แต่ GitHub ที่ดีกว่า

person Felipe Buccioni    schedule 20.05.2013
comment
แล้วตัวอักษรรัสเซียล่ะ? - person Rafael Herscovici; 12.06.2013
comment
ขออภัยในความไม่รู้ แต่ฉันไม่รู้เกี่ยวกับตัวอักษรรัสเซียมากนัก แต่คุณมีส่วนร่วมได้หากต้องการ คุณสามารถเพิ่มกรณี =) หรือส่งอักขระที่เทียบเท่ามาให้ฉันก็ได้ - person Felipe Buccioni; 13.06.2013
comment
แน่นอนว่ามันไม่ได้รองรับทุกคลาส มันถูกสร้างขึ้นเพื่อแก้ปัญหาความต้องการเฉพาะ ได้รับการพัฒนาเพื่อแก้ปัญหาสำเนียง latin1 และประเด็นของฉันคือคุณสามารถมีส่วนร่วมในการจัดการกับกรณีต่างๆ ได้มากขึ้น - person Felipe Buccioni; 13.06.2013
comment
@FelipeAlcacibar tr ฟังก์ชั่นในรูทีนของคุณคืออะไร? อ่า โอเค ฉันเจอแล้ว ฉันคิดว่ามันเป็นส่วนสำคัญ แต่มันคือการซื้อคืน - person ygaradon; 09.04.2014
comment
@ygaradon ใน repo เดียวกัน - person Felipe Buccioni; 10.04.2014
comment
เฮ้ ฟังก์ชั่นดี แต่ในใจฉันมีปัญหา 2 ประการ: 1. ต้นฉบับ - ถูกลบออก พวกเขาต้องคงอยู่ 2. ' ถูกลบออกแทนที่จะแทนที่ด้วย - - person sHaDeoNeR; 19.11.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;
person Pioz    schedule 05.03.2021
comment
นั่นเป็นทางออกที่ชัดเจน - person hkaraoglu; 22.06.2021

ฉันใช้รหัสนี้มานานแล้ว โพสไว้ที่นี่เพื่อจดจำและอาจช่วยเหลือใครซักคนในสมัยนี้

เพียงคัดลอก/วางข้อมูลโค้ดนี้ในแท็บแบบสอบถาม MySQL ของคุณแล้วเรียกใช้

-- สมมติว่าผู้ใช้ของคุณคือ root และโฮสต์คือ localhost ถ้าไม่ ให้เปลี่ยนผู้ใช้รูทและค่า 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 เองเช่น 'โอ้พระเจ้า' จะเป็น 'โอ้พระเจ้า'

person Felipe Lima    schedule 05.08.2020