Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Modèle Regex dans la fonction SQL Replace ?

Vous pouvez utiliser PATINDEX pour trouver le premier index de l'occurrence du modèle (chaîne). Utilisez ensuite STUFF pour insérer une autre chaîne dans le modèle (chaîne) correspondant.

Faites une boucle dans chaque rangée. Remplacez chaque caractère illégal par ce que vous voulez. Dans votre cas, remplacez non numérique par un espace. La boucle interne est si vous avez plus d'un caractère illégal dans une cellule actuelle celle de la boucle.

DECLARE @counter int

SET @counter = 0

WHILE(@counter < (SELECT MAX(ID_COLUMN) FROM Table))
BEGIN  

    WHILE 1 = 1
    BEGIN
        DECLARE @RetVal varchar(50)

        SET @RetVal =  (SELECT Column = STUFF(Column, PATINDEX('%[^0-9.]%', Column),1, '')
        FROM Table
        WHERE ID_COLUMN = @counter)

        IF(@RetVal IS NOT NULL)       
          UPDATE Table SET
          Column = @RetVal
          WHERE ID_COLUMN = @counter
        ELSE
            break
    END

    SET @counter = @counter + 1
END

Attention :c'est lent cependant ! Avoir une colonne varchar peut avoir un impact. Donc, utiliser LTRIM RTRIM peut aider un peu. Quoi qu'il en soit, c'est lent.

Le crédit revient à cette réponse StackOverFlow.

EDITCredit va également à @srutzky

Modifier (par @Tmdean)Au lieu de faire une ligne à la fois, cette réponse peut être adaptée à une solution plus basée sur un ensemble. Il itère toujours le maximum du nombre de caractères non numériques dans une seule ligne, donc ce n'est pas idéal, mais je pense que cela devrait être acceptable dans la plupart des situations.

WHILE 1 = 1 BEGIN
    WITH q AS
        (SELECT ID_Column, PATINDEX('%[^0-9.]%', Column) AS n
        FROM Table)
    UPDATE Table
    SET Column = STUFF(Column, q.n, 1, '')
    FROM q
    WHERE Table.ID_Column = q.ID_Column AND q.n != 0;

    IF @@ROWCOUNT = 0 BREAK;
END;

Vous pouvez également améliorer considérablement l'efficacité si vous maintenez une colonne de bits dans le tableau qui indique si le champ a déjà été nettoyé. (NULL représente "Inconnu" dans mon exemple et devrait être la colonne par défaut.)

DECLARE @done bit = 0;
WHILE @done = 0 BEGIN
    WITH q AS
        (SELECT ID_Column, PATINDEX('%[^0-9.]%', Column) AS n
        FROM Table
        WHERE COALESCE(Scrubbed_Column, 0) = 0)
    UPDATE Table
    SET Column = STUFF(Column, q.n, 1, ''),
        Scrubbed_Column = 0
    FROM q
    WHERE Table.ID_Column = q.ID_Column AND q.n != 0;

    IF @@ROWCOUNT = 0 SET @done = 1;

    -- if Scrubbed_Column is still NULL, then the PATINDEX
    -- must have given 0
    UPDATE table
    SET Scrubbed_Column = CASE
        WHEN Scrubbed_Column IS NULL THEN 1
        ELSE NULLIF(Scrubbed_Column, 0)
    END;
END;

Si vous ne souhaitez pas modifier votre schéma, il est facile de l'adapter pour stocker les résultats intermédiaires dans une variable de table qui est appliquée à la table réelle à la fin.