Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Regex-Muster in der SQL-Replace-Funktion?

Sie können PATINDEX verwenden, um den ersten Index des Vorkommens des Musters (des Strings) zu finden. Verwenden Sie dann STUFF, um einen weiteren String in das passende Muster (String) zu stopfen.

Schleife durch jede Reihe. Ersetzen Sie jedes unzulässige Zeichen durch das, was Sie wollen. Ersetzen Sie in Ihrem Fall nicht numerisch durch Leerzeichen. Die innere Schleife ist, wenn Sie mehr als ein ungültiges Zeichen in einer aktuellen Zelle haben, das der Schleife.

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

Achtung:Das ist allerdings langsam! Eine varchar-Spalte kann Auswirkungen haben. Daher kann die Verwendung von LTRIM RTRIM ein wenig helfen. Trotzdem ist es langsam.

Gutschrift geht an diese StackOverFlow-Antwort.

EDITCredit geht auch an @srutzky

Bearbeiten (von @Tmdean) Anstatt jeweils eine Zeile zu bearbeiten, kann diese Antwort an eine eher satzbasierte Lösung angepasst werden. Es iteriert immer noch das Maximum der Anzahl nicht numerischer Zeichen in einer einzelnen Zeile, also ist es nicht ideal, aber ich denke, es sollte in den meisten Situationen akzeptabel sein.

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;

Sie können die Effizienz auch erheblich verbessern, wenn Sie in der Tabelle eine Bit-Spalte pflegen, die angibt, ob das Feld bereits bereinigt wurde. (NULL steht in meinem Beispiel für „Unbekannt“ und sollte der Spaltenstandard sein.)

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;

Wenn Sie Ihr Schema nicht ändern möchten, können Sie es leicht anpassen, um Zwischenergebnisse in einer Variablen mit Tabellenwert zu speichern, die am Ende auf die eigentliche Tabelle angewendet wird.