Search code examples
sqlsql-serverstringt-sqlregexp-replace

Reverse only numerical parts of string in sql server


With T-SQL, I'm trying to find the easiest way to reverse numbers in string. so for string like Test123Hello have Test321Hello.

[Before]           [After]
Test123Hello       Test321Hello
Tt143 Hello        Tt341 Hello
12Hll              21Hll
Tt123H3451end      Tt321H1543end

Solution

  • Just make use of PATINDEX for searching, append to the result string part by part:

    CREATE FUNCTION [dbo].[fn_ReverseDigits]
    (
        @Value nvarchar(max)   
    )
    RETURNS NVARCHAR(max)
    AS
    BEGIN
    
        IF @Value IS NULL
            RETURN NULL
    
        DECLARE 
            @TextIndex int = PATINDEX('%[^0-9]%', @Value), 
            @NumIndex int = PATINDEX('%[0-9]%', @Value), 
            @ResultValue nvarchar(max)  = ''
    
        WHILE LEN(@ResultValue) < LEN(@Value)
        BEGIN
    
            -- Set the index to end of the string if the index is 0
            SELECT @TextIndex = CASE WHEN @TextIndex = 0 THEN LEN(@Value) + 1 ELSE LEN(@ResultValue) + @TextIndex END
            SELECT @NumIndex = CASE WHEN @NumIndex = 0 THEN LEN(@Value) + 1 ELSE LEN(@ResultValue) + @NumIndex END
    
            IF @NumIndex < @TextIndex
                SELECT @ResultValue = @ResultValue + REVERSE(SUBSTRING(@Value, @NumIndex, @TextIndex -@NumIndex))
            ELSE
                SELECT @ResultValue = @ResultValue + (SUBSTRING(@Value, @TextIndex, @NumIndex - @TextIndex))
    
            -- Update index variables
            SELECT
                @TextIndex = PATINDEX('%[^0-9]%', SUBSTRING(@Value, LEN(@ResultValue) + 1, LEN(@Value) - LEN(@ResultValue))), 
                @NumIndex = PATINDEX('%[0-9]%', SUBSTRING(@Value, LEN(@ResultValue) + 1, LEN(@Value) - LEN(@ResultValue)))
    
        END
    
    
        RETURN @ResultValue
    END
    

    Test SQL

    declare @Values table (Value varchar(20))
    INSERT @Values VALUES
    ('Test123Hello'),
    ('Tt143 Hello'),
    ('12Hll'), 
    ('Tt123H3451end'),
    (''),
    (NULL)
    
    SELECT Value, dbo.fn_ReverseDigits(Value) ReversedValue FROM @Values
    

    Result

    Value                ReversedValue
    -------------------- --------------------
    Test123Hello         Test321Hello
    Tt143 Hello          Tt341 Hello
    12Hll                21Hll
    Tt123H3451end        Tt321H1543end
    
    NULL                 NULL