sql >> Base de Datos >  >> RDS >> Sqlserver

¿Patrón Regex dentro de la función de reemplazo de SQL?

Puede usar PATINDEX para encontrar el primer índice de la ocurrencia del patrón (cadena). Luego use STUFF para rellenar otra cadena en el patrón (cadena) coincidente.

Bucle a través de cada fila. Reemplaza cada carácter ilegal con lo que quieras. En su caso, reemplace no numérico con espacio en blanco. El ciclo interno es si tiene más de un carácter ilegal en una celda actual, el del ciclo.

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

Precaución:¡Esto es lento! Tener una columna varchar puede afectar. Entonces, usar LTRIM RTRIM puede ayudar un poco. De todos modos, es lento.

El crédito es para esta respuesta de StackOverFlow.

EDITCredit también va para @srutzky

Editar (por @Tmdean) En lugar de hacer una fila a la vez, esta respuesta se puede adaptar a una solución más basada en conjuntos. Todavía itera el número máximo de caracteres no numéricos en una sola fila, por lo que no es ideal, pero creo que debería ser aceptable en la mayoría de las situaciones.

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;

También puede mejorar bastante la eficiencia si mantiene una columna de bits en la tabla que indica si el campo ya se ha limpiado. (NULL representa "Desconocido" en mi ejemplo y debería ser la columna predeterminada).

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;

Si no desea cambiar su esquema, esto es fácil de adaptar para almacenar resultados intermedios en una variable con valor de tabla que se aplica a la tabla real al final.