Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Padrão Regex dentro da função SQL Replace?


Você pode usar PATINDEX para encontrar o primeiro índice da ocorrência do padrão (string). Em seguida, use STUFF para inserir outra string no padrão (string) correspondente.

Faça um loop em cada linha. Substitua cada caractere ilegal pelo que você deseja. No seu caso, substitua não numérico por branco. O loop interno é se você tiver mais de um caractere ilegal em uma célula atual do loop.
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

Cuidado:Isso é lento embora! Ter uma coluna varchar pode impactar. Portanto, usar LTRIM RTRIM pode ajudar um pouco. Independentemente disso, é lento.

O crédito vai para esta resposta do StackOverFlow.

EDITCredit também vai para @srutzky

Editar (por @Tmdean) Em vez de fazer uma linha de cada vez, esta resposta pode ser adaptada a uma solução mais baseada em conjuntos. Ele ainda itera o máximo do número de caracteres não numéricos em uma única linha, então não é o ideal, mas acho que deve ser aceitável na maioria das situações.
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;

Você também pode melhorar bastante a eficiência se mantiver uma coluna de bits na tabela que indica se o campo já foi depurado. (NULL representa "Desconhecido" no meu exemplo e deve ser o padrão da coluna.)
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;

Se você não quiser alterar seu esquema, é fácil adaptá-lo para armazenar resultados intermediários em uma variável com valor de tabela que é aplicada à tabela real no final.