sql >> Databasteknik >  >> RDS >> Sqlserver

Regex mönster inuti SQL Ersätt funktion?

Du kan använda PATINDEX för att hitta det första indexet för mönstrets (strängens) förekomst. Använd sedan STUFF för att stoppa in ytterligare en sträng i mönstret(strängen) som matchas.

Gå igenom varje rad. Byt ut alla olagliga tecken med vad du vill ha. Ersätt i ditt fall icke-numerisk med blank. Den inre slingan är om du har mer än ett olagligt tecken i en aktuell cell det i slingan.

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

Varning:Detta är dock långsamt! Att ha en varcharkolonn kan påverka. Så att använda LTRIM RTRIM kan hjälpa lite. Oavsett, det går långsamt.

Tack till det här StackOverFlow-svaret.

EDITCredit går också till @srutzky

Redigera (av @Tmdean)Istället för att göra en rad i taget kan det här svaret anpassas till en mer uppsättningsbaserad lösning. Den upprepar fortfarande maxtalet för antalet icke-numeriska tecken på en enda rad, så det är inte idealiskt, men jag tror att det borde vara acceptabelt i de flesta situationer.

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;

Du kan också förbättra effektiviteten ganska mycket om du behåller en bitkolumn i tabellen som anger om fältet har skurats ännu. (NULL representerar "Okänd" i mitt exempel och bör vara standardkolumnen.)

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;

Om du inte vill ändra ditt schema är detta lätt att anpassa för att lagra mellanresultat i en tabellvärderad variabel som appliceras på den faktiska tabellen i slutet.



  1. T-SQL datumtid avrundad till närmaste minut och närmaste timmar med hjälp av funktioner

  2. SOUNDEX() Funktion i Oracle

  3. Importera SQL-fil till mysql

  4. Hämta den aktuella tidszonen för servern i SQL Server (T-SQL)