sql >> Database >  >> RDS >> Sqlserver

Regex-patroon in de functie SQL Replace?

U kunt PATINDEX gebruiken om de eerste index van het voorkomen van het patroon (tekenreeks) te vinden. Gebruik dan STUFF om een ​​andere string in het overeenkomende patroon(string) te proppen.

Loop door elke rij. Vervang elk illegaal karakter door wat je wilt. Vervang in uw geval niet-numeriek door spatie. De binnenste lus is als je meer dan één ongeldig teken in een huidige cel hebt, die van de lus.

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

Let op:dit gaat wel langzaam! Het hebben van een varchar-kolom kan van invloed zijn. Dus het gebruik van LTRIM RTRIM kan een beetje helpen. Hoe dan ook, het is traag.

Krediet gaat naar dit StackOverFlow-antwoord.

EDITCredit gaat ook naar @srutzky

Bewerken (door @Tmdean) In plaats van één rij tegelijk te doen, kan dit antwoord worden aangepast aan een meer set-gebaseerde oplossing. Het herhaalt nog steeds het maximum van het aantal niet-numerieke tekens in een enkele rij, dus het is niet ideaal, maar ik denk dat het in de meeste situaties acceptabel zou moeten zijn.

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;

Je kunt de efficiëntie ook behoorlijk verbeteren als je een bitkolom in de tabel aanhoudt die aangeeft of het veld al is geschrobd. (NULL staat in mijn voorbeeld voor "Onbekend" en zou de standaardkolom moeten zijn.)

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;

Als u uw schema niet wilt wijzigen, is dit eenvoudig aan te passen om tussentijdse resultaten op te slaan in een tabelwaardevariabele die aan het einde op de eigenlijke tabel wordt toegepast.



  1. Automatische verhoging voor Oracle

  2. Oracle INSERT in twee tabellen in één query

  3. MySql werkt twee tabellen tegelijk bij

  4. Hoe lege tabellen in Oracle te exporteren