sql >> Database teknologi >  >> RDS >> Sqlserver

Regex-mønster inde i SQL Replace-funktionen?

Du kan bruge PATINDEX til at finde det første indeks for mønsterets (strengens) forekomst. Brug derefter STUFF til at stoppe en anden streng i det matchede mønster(streng).

Løkke gennem hver række. Erstat hver ulovlig karakter med det, du ønsker. I dit tilfælde skal du erstatte ikke-numerisk med blank. Den indre løkke er, hvis du har mere end et ulovligt tegn i en aktuel celle, det i løkken.

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

Advarsel:Det er dog langsomt! At have en varchar-søjle kan påvirke. Så brug af LTRIM RTRIM kan hjælpe lidt. Uanset hvad er det langsomt.

Kredit går til dette StackOverFlow-svar.

EDITCredit går også til @srutzky

Rediger (af @Tmdean)I stedet for at lave en række ad gangen, kan dette svar tilpasses til en mere sæt-baseret løsning. Den gentager stadig maks. antallet af ikke-numeriske tegn i en enkelt række, så det er ikke ideelt, men jeg tror, ​​det burde være acceptabelt i de fleste 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 også forbedre effektiviteten en del, hvis du fastholder en bit-kolonne i tabellen, der indikerer, om feltet er blevet skrubbet endnu. (NULL repræsenterer "Ukendt" i mit eksempel og burde være kolonnens standard.)

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;

Hvis du ikke ønsker at ændre dit skema, er dette nemt at tilpasse til at gemme mellemresultater i en tabelværdivariabel, som bliver anvendt på den faktiske tabel i slutningen.



  1. Oracle datoforskel for at få antal år

  2. Find ud af ledig plads på tablespace

  3. Hvordan Cosh() virker i PostgreSQL

  4. MariaDB JSON_EXISTS() Forklaret