[FIXED] Regex-Muster in der SQL-Replace-Funktion?

Ausgabe

SELECT REPLACE('<strong>100</strong><b>.00 GB', '%^(^-?\d*\.{0,1}\d+$)%', '');

Ich möchte jedes Markup zwischen zwei Teilen der Zahl durch den obigen Regex ersetzen, aber es scheint nicht zu funktionieren. Ich bin mir nicht sicher, ob es sich um eine falsche Regex-Syntax handelt, da ich eine einfachere versucht habe, z. B. '%[^0-9]%'nur zum Testen, aber es hat auch nicht funktioniert. Weiß jemand wie ich das erreichen kann?

Lösung

Sie können PATINDEX verwenden
, um den ersten Index des Vorkommens des Musters (des Strings) zu finden.
Verwenden Sie dann
STUFF , um eine andere Zeichenfolge in das übereinstimmende Muster (die Zeichenfolge) 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, die der Schleife entspricht.

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. Egal, es ist langsam.

Gutschrift geht an diese StackOverFlow-Antwort.

EDIT Credit 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 einfach anpassen, um Zwischenergebnisse in einer Tabellenwertvariablen zu speichern, die am Ende auf die eigentliche Tabelle angewendet wird.


Beantwortet von –
Mukus


Antwort geprüft von –
Clifford M. (FixError Volunteer)

0 Shares:
Leave a Reply

Your email address will not be published. Required fields are marked *

You May Also Like