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

Modello Regex all'interno della funzione SQL Sostituisci?

È possibile utilizzare PATINDEX per trovare il primo indice dell'occorrenza del modello (stringa). Quindi usa STUFF per inserire un'altra stringa nel pattern(string) abbinato.

Passa attraverso ogni riga. Sostituisci ogni personaggio illegale con quello che vuoi. Nel tuo caso sostituisci non numerico con vuoto. Il ciclo interno è se hai più di un carattere illegale in una cella corrente quella 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

Attenzione:questo è lento però! Avere una colonna varchar può influire. Quindi l'uso di LTRIM RTRIM può aiutare un po'. In ogni caso, è lento.

Il merito va a questa risposta StackOverFlow.

EDITCredit va anche a @srutzky

Modifica (di @Tmdean) Invece di eseguire una riga alla volta, questa risposta può essere adattata a una soluzione più basata su set. Itera ancora il numero massimo di caratteri non numerici in una singola riga, quindi non è l'ideale, ma penso che dovrebbe essere accettabile nella maggior parte delle situazioni.

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;

Puoi anche migliorare notevolmente l'efficienza se mantieni una piccola colonna nella tabella che indica se il campo è stato ancora cancellato. (NULL rappresenta "Sconosciuto" nel mio esempio e dovrebbe essere l'impostazione predefinita della colonna.)

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 non desideri modificare lo schema, è facile adattarlo per memorizzare i risultati intermedi in una variabile con valore di tabella che viene applicata alla tabella effettiva alla fine.