2010-06-21 5 views
6

Vérification rapide pour voir si quelqu'un a ou connaît une fonction T-SQL capable de générer des slugs à partir d'une entrée nvarchar donnée. c'est à dire;Fonction T-SQL pour générer des limaces?

"Bonjour tout le monde"> "bonjour monde"
"Ceci est un test"> "this-is-un-test"

J'ai une fonction C# que j'utilise normalement pour à ces fins, mais dans ce cas, j'ai une grande quantité de données à analyser et à transformer en limaces, il est donc plus logique de le faire sur le serveur SQL plutôt que d'avoir à transférer des données sur le fil.

En aparté, je n'ai pas accès Bureau à distance pour la boîte, donc je ne peux pas exécuter du code (.net, Powershell, etc) contre

Merci à l'avance.

EDIT: selon la demande, voici la fonction que je l'utilise généralement pour générer les limaces:

public static string GenerateSlug(string n, int maxLength) 
{ 
    string s = n.ToLower();     
    s = Regex.Replace(s, @"[^a-z0-9s-]", "");    
    s = Regex.Replace(s, @"[s-]+", " ").Trim();    
    s = s.Substring(0, s.Length <= maxLength ? s.Length : maxLength).Trim();    
    s = Regex.Replace(s, @"s", "-"); 
    return s; 
} 
+0

Pouvez-vous poster votre C# slug- fonction du générateur? – Constantin

Répondre

8

C'est ce que j'ai trouvé comme solution. N'hésitez pas à corriger/modifier si nécessaire.

Je dois mentionner que la base de données que je développe actuellement est insensible à la casse d'où le LOWER (@str).

CREATE FUNCTION [dbo].[UDF_GenerateSlug] 
( 
    @str VARCHAR(100) 
) 
RETURNS VARCHAR(100) 
AS 
BEGIN 
DECLARE @IncorrectCharLoc SMALLINT 
SET @str = LOWER(@str) 
SET @IncorrectCharLoc = PATINDEX('%[^0-9a-z ]%',@str) 
WHILE @IncorrectCharLoc > 0 
BEGIN 
SET @str = STUFF(@str,@incorrectCharLoc,1,'') 
SET @IncorrectCharLoc = PATINDEX('%[^0-9a-z ]%',@str) 
END 
SET @str = REPLACE(@str,' ','-') 
RETURN @str 
END 

Mentionner à: http://blog.sqlauthority.com/2007/05/13/sql-server-udf-function-to-parse-alphanumeric-characters-from-string/ pour le code original.

+1

Il ne devrait pas être ''% [^ 0-9a-z]%' 'mais devrait être''% [^ 0-9a-z-]% '' –

9

Vous pouvez utiliser LOWER et REPLACE pour ce faire:

SELECT REPLACE(LOWER(origString), ' ', '-') 
FROM myTable 

Pour la mise à jour en gros de la colonne (le code définit la colonne slug en fonction de la valeur de la colonne origString:

UPDATE myTable 
SET slug = REPLACE(LOWER(origString), ' ', '-') 
+3

Pour slugify correctement une chaîne unicode, vous auriez besoin de beaucoup plus que cela. Au moins tous les caractères non-ascii devraient être traités. – Constantin

3

Voici une variation de la réponse de Jeremy. Cela pourrait ne pas être techniquement slugifying puisque je fais quelques choses personnalisées comme le remplacement "." avec "-dot-", et dépouillant les apostrophes. L'amélioration principale est celle-ci supprime également tous les espaces consécutifs, et ne supprime pas les tirets préexistants.

create function dbo.Slugify(@str nvarchar(max)) returns nvarchar(max) 
as 
begin 
    declare @IncorrectCharLoc int 
    set @str = replace(replace(lower(@str),'.',' dot '),'''','') 

    -- remove non alphanumerics: 
    set @IncorrectCharLoc = patindex('%[^0-9a-z -]%',@str) 
    while @IncorrectCharLoc > 0 
    begin 
     set @str = stuff(@str,@incorrectCharLoc,1,' ') 
     set @IncorrectCharLoc = patindex('%[^0-9a-z -]%',@str) 
    end 
    -- remove consecutive spaces: 
    while charindex(' ',@str) > 0 
    begin 
    set @str = replace(@str, ' ', ' ') 
    end 
    set @str = replace(@str,' ','-') 
return @str 
end 
+0

Très utile. Deux choses que j'ai remarqué que ce script ne gère pas étaient à la traîne (probablement en tête?) les entrées d'espaces qui se terminaient par une parenthèse fermante laissaient un trait d'union traînant. Pour le premier, coupez l'entrée. Pour la seconde, je ne suis pas sûr parce qu'un trait d'union traînant pourrait être exprès ... –

3

Je pris la réponse de Jeremy de quelques pas plus loin en supprimant tous les tirets consécutifs, même après les espaces sont remplacés, et retiré de premier plan et des tirets de fuite.

create function dbo.Slugify(@str nvarchar(max)) returns nvarchar(max) as 
begin 
    declare @IncorrectCharLoc int 
    set @str = replace(replace(lower(@str),'.','-'),'''','') 

    -- remove non alphanumerics: 
    set @IncorrectCharLoc = patindex('%[^0-9a-z -]%',@str) 
    while @IncorrectCharLoc > 0 
    begin 
     set @str = stuff(@str,@incorrectCharLoc,1,' ') 
     set @IncorrectCharLoc = patindex('%[^0-9a-z -]%',@str) 
    end 

    -- replace all spaces with dashes 
    set @str = replace(@str,' ','-') 

    -- remove consecutive dashes: 
    while charindex('--',@str) > 0 
    begin 
     set @str = replace(@str, '--', '-') 
    end 

    -- remove leading dashes 
    while charindex('-', @str) = 1 
    begin 
     set @str = RIGHT(@str, len(@str) - 1) 
    end 

    -- remove trailing dashes 
    while len(@str) > 0 AND substring(@str, len(@str), 1) = '-' 
    begin 
     set @str = LEFT(@str, len(@str) - 1) 
    end 
return @str 
end 
0
-- Converts a title such as "This is a Test" to an all lower case string such 
-- as "this-is-a-test" for use as the slug in a URL. All runs of separators 
-- (whitespace, underscore, or hyphen) are converted to a single hyphen. 
-- This is implemented as a state machine having the following four states: 
-- 
--  0 - initial state 
--  1 - in a sequence consisting of valid characters (a-z, A-Z, or 0-9) 
--  2 - in a sequence of separators (whitespace, underscore, or hyphen) 
--  3 - encountered a character that is neither valid nor a separator 
-- 
-- Once the next state has been determined, the return value string is 
-- built based on the transitions from the current state to the next state. 
-- 
-- State 0 skips any initial whitespace. State 1 includes all valid slug 
-- characters. State 2 converts multiple separators into a single hyphen 
-- and skips trailing whitespace. State 3 skips any punctuation between 
-- between characters and, if no additional whitespace is encountered, 
-- then the punctuation is not treated as a word separator. 
-- 
CREATE FUNCTION ToSlug(@title AS NVARCHAR(MAX)) 
RETURNS VARCHAR(MAX) 
AS 
BEGIN 
    DECLARE @retval AS VARCHAR(MAX) = ''; -- return value 
    DECLARE @i AS INT = 1;    -- title index 
    DECLARE @c AS CHAR(1);    -- current character 
    DECLARE @state AS INT = 0;   -- current state 
    DECLARE @nextState AS INT;   -- next state 
    DECLARE @tab AS CHAR(1) = CHAR(9); -- tab 
    DECLARE @lf AS CHAR(1) = CHAR(10); -- line feed 
    DECLARE @cr AS CHAR(1) = CHAR(13); -- carriage return 
    DECLARE @separators AS CHAR(8) = '[' + @tab + @lf + @cr + ' _-]'; 
    DECLARE @validchars AS CHAR(11) = '[a-zA-Z0-9]'; 

    WHILE (@i <= LEN(@title)) 
    BEGIN 
     SELECT @c = SUBSTRING(@title, @i, 1), 

     @nextState = CASE 
      WHEN @c LIKE @validchars THEN 1 
      WHEN @state = 0 THEN 0 
      WHEN @state = 1 THEN CASE 
       WHEN @c LIKE @separators THEN 2 
       ELSE 3 -- unknown character 
       END 
      WHEN @state = 2 THEN 2 
      WHEN @state = 3 THEN CASE 
       WHEN @c LIKE @separators THEN 2 
       ELSE 3 -- stay in state 3 
       END 
      END, 

     @retval = @retval + CASE 
      WHEN @nextState != 1 THEN '' 
      WHEN @state = 0 THEN LOWER(@c) 
      WHEN @state = 1 THEN LOWER(@c) 
      WHEN @state = 2 THEN '-' + LOWER(@c) 
      WHEN @state = 3 THEN LOWER(@c) 
      END, 

     @state = @nextState, 

     @i = @i + 1 
    END 
    RETURN @retval; 
END 
+0

pourriez-vous ajouter plus de commentaires? –

3

Je sais que c'est un vieux fil, mais pour les générations futures, je trouve une fonction qui traite même avec des accents here:

CREATE function [dbo].[slugify](@string varchar(4000)) 
    RETURNS varchar(4000) AS BEGIN 
    declare @out varchar(4000) 

    --convert to ASCII 
    set @out = lower(@string COLLATE SQL_Latin1_General_CP1251_CS_AS) 

    declare @pi int 
    --I'm sorry T-SQL have no regex. Thanks for patindex, MS .. :-) 
    set @pi = patindex('%[^a-z0-9 -]%',@out) 
    while @pi>0 begin 
     set @out = replace(@out, substring(@out,@pi,1), '') 
     --set @out = left(@out,@pi-1) + substring(@out,@pi+1,8000) 
     set @pi = patindex('%[^a-z0-9 -]%',@out) 
    end 

    set @out = ltrim(rtrim(@out)) 

    -- replace space to hyphen 
    set @out = replace(@out, ' ', '-') 

    -- remove double hyphen 
    while CHARINDEX('--', @out) > 0 set @out = replace(@out, '--', '-') 

    return (@out) 
END 
+0

L'utilisation de 'COLLATE SQL_Latin1_General_CP1251_CS_AS' pour supprimer les accents ne fonctionne qu'avec les variables varchar. Si vous essayez de faire la même chose avec la variable nvarchar, rien ne se passe. Si l'entrée est nvarchar, elle devra être explicitement convertie en varchar à un certain point en utilisant 'cast (@string as varchar)'. Si vous ne le faites pas, les accents resteront où ils sont. – jahu

+0

L'utilisation de la conversion avec une longueur spécifique peut également s'avérer nécessaire car SQL Server semble raccourcir votre chaîne si elle est convertie en 'varchar' dans une instruction SELECT. Par exemple 'cast (@string as varchar (500))'. – jahu

0
To slug with Vietnamese unicode  

CREATE function [dbo].[toslug](@string nvarchar(4000)) 
    RETURNS varchar(4000) AS BEGIN 
    declare @out nvarchar(4000) 
    declare @from nvarchar(255) 
    declare @to varchar(255) 
    --convert to ASCII dbo.slugify 
    set @string = lower(@string) 
    set @out = @string 
    set @from = N'ýỳỷỹỵáàảãạâấầẩẫậăắằẳẵặéèẻẽẹêếềểễệúùủũụưứừửữựíìỉĩịóòỏõọơớờởỡợôốồổỗộđ·/_,:;' 
    set @to = 'yyyyyaaaaaaaaaaaaaaaaaeeeeeeeeeeeuuuuuuuuuuuiiiiioooooooooooooooood------' 
    declare @pi int 
    set @pi = 1 
    --I'm sorry T-SQL have no regex. Thanks for patindex, MS .. :-) 
    while @pi<=len(@from) begin 
     set @out = replace(@out, substring(@from,@pi,1), substring(@to,@pi,1)) 
     set @pi = @pi + 1 
    end 
    set @out = ltrim(rtrim(@out)) 

    -- replace space to hyphen 
    set @out = replace(@out, ' ', '-') 

    -- remove double hyphen 
    while CHARINDEX('--', @out) > 0 set @out = replace(@out, '--', '-') 

    return (@out) 
END 
+1

S'il vous plaît jeter un oeil à la façon dont votre poste a rendu, et [le modifier pour corriger le formatage] (http://stackoverflow.com/posts/42667458/edit). Vous obtenez un petit aperçu pratique dans la zone de post-édition afin que vous puissiez voir à quoi cela va ressembler avant de le soumettre. – AakashM

+2

Ce lien peut vous être utile - [answer] – Tom

+0

merci @AakashM Je l'ai –

Questions connexes