How to compare software versions using SQL Server?

后端 未结 16 2183
清酒与你
清酒与你 2020-12-03 07:30

When trying to compare software versions 5.12 to 5.8, version 5.12 is newer, however mathematically 5.12 is less than 5.8. How would I compare the two versions so that a new

16条回答
  •  南方客
    南方客 (楼主)
    2020-12-03 08:17

    I encountered this when trying to filter SQL rows based on semantic versioning. My solution was a bit different, in that I wanted to store configuration rows tagged with a semantic version number and then select rows compatible with a running version of our software.

    Assumptions:

    • My software will include a configuration setting containing the current version number
    • Data-driven configuration rows will include a min version number
    • I need to be able to select configuration rows where min <= current.

    Examples:

    • Version 1.0.0 should include: 1.0.0, 1.0.0-*, 1.0.0-beta.1
    • Version 1.0.0 should exclude: 1.0.1, 1.1.0, 2.0.0
    • Version 1.1.0-beta.2 should include: 1.0.0, 1.0.1, 1.1.0-beta.1, 1.1.0-beta.2
    • Version 1.1.0-beta.2 should exclude: 1.1.0, 1.1.1, 1.2.0, 2.0.0, 1.1.1-beta.1

    The MSSQL UDF is:

    CREATE FUNCTION [dbo].[SemanticVersion] (
        @Version nvarchar(50)
    )
    RETURNS nvarchar(255)
    
    AS
    BEGIN
    
        DECLARE @hyphen int = CHARINDEX('-', @version)
        SET @Version = REPLACE(@Version, '*', ' ')
        DECLARE 
            @left nvarchar(50) = CASE @hyphen WHEN 0 THEN @version ELSE SUBSTRING(@version, 1, @hyphen-1) END,
            @right nvarchar(50) = CASE @hyphen WHEN 0 THEN NULL ELSE SUBSTRING(@version, @hyphen+1, 50) END,
            @normalized nvarchar(255) = '',
            @buffer int = 8
    
        WHILE CHARINDEX('.', @left) > 0 BEGIN
            SET @normalized = @normalized + CASE ISNUMERIC(LEFT(@left, CHARINDEX('.', @left)-1))
                WHEN 0 THEN LEFT(@left, CHARINDEX('.', @left)-1)
                WHEN 1 THEN REPLACE(STR(LEFT(@left, CHARINDEX('.', @left)-1), @buffer), SPACE(1), '0')
            END  + '.'
            SET @left = SUBSTRING(@left, CHARINDEX('.', @left)+1, 50)
        END
        SET @normalized = @normalized + CASE ISNUMERIC(@left)
            WHEN 0 THEN @left
            WHEN 1 THEN REPLACE(STR(@left, @buffer), SPACE(1), '0')
        END
    
        SET @normalized = @normalized + '-'
        IF (@right IS NOT NULL) BEGIN
            WHILE CHARINDEX('.', @right) > 0 BEGIN
                SET @normalized = @normalized + CASE ISNUMERIC(LEFT(@right, CHARINDEX('.', @right)-1))
                    WHEN 0 THEN LEFT(@right, CHARINDEX('.', @right)-1)
                    WHEN 1 THEN REPLACE(STR(LEFT(@right, CHARINDEX('.', @right)-1), @buffer), SPACE(1), '0')
                END  + '.'
                SET @right = SUBSTRING(@right, CHARINDEX('.', @right)+1, 50)
            END
            SET @normalized = @normalized + CASE ISNUMERIC(@right)
                WHEN 0 THEN @right
                WHEN 1 THEN REPLACE(STR(@right, @buffer), SPACE(1), '0')
            END
        END ELSE 
            SET @normalized = @normalized + 'zzzzzzzzzz'
    
        RETURN @normalized
    
    END
    

    SQL tests include:

    SELECT CASE WHEN dbo.SemanticVersion('1.0.0-alpha') < dbo.SemanticVersion('1.0.0-alpha.1') THEN 'Success' ELSE 'Failure' END
    SELECT CASE WHEN dbo.SemanticVersion('1.0.0-alpha.1') < dbo.SemanticVersion('1.0.0-alpha.beta') THEN 'Success' ELSE 'Failure' END
    SELECT CASE WHEN dbo.SemanticVersion('1.0.0-alpha.beta') < dbo.SemanticVersion('1.0.0-beta') THEN 'Success' ELSE 'Failure' END
    SELECT CASE WHEN dbo.SemanticVersion('1.0.0-beta') < dbo.SemanticVersion('1.0.0-beta.2') THEN 'Success' ELSE 'Failure' END
    SELECT CASE WHEN dbo.SemanticVersion('1.0.0-beta.2') < dbo.SemanticVersion('1.0.0-beta.11') THEN 'Success' ELSE 'Failure' END
    SELECT CASE WHEN dbo.SemanticVersion('1.0.0-beta.11') < dbo.SemanticVersion('1.0.0-rc.1') THEN 'Success' ELSE 'Failure' END
    SELECT CASE WHEN dbo.SemanticVersion('1.0.0-rc.1') < dbo.SemanticVersion('1.0.0') THEN 'Success' ELSE 'Failure' END
    
    
    SELECT CASE WHEN dbo.SemanticVersion('1.0.0-*') <= dbo.SemanticVersion('1.0.0') THEN 'Success' ELSE 'Failure' END
    SELECT CASE WHEN dbo.SemanticVersion('1.0.*') <= dbo.SemanticVersion('1.0.0') THEN 'Success' ELSE 'Failure' END
    SELECT CASE WHEN dbo.SemanticVersion('1.*') <= dbo.SemanticVersion('1.0.0') THEN 'Success' ELSE 'Failure' END
    SELECT CASE WHEN dbo.SemanticVersion('*') <= dbo.SemanticVersion('1.0.0') THEN 'Success' ELSE 'Failure' END
    
    SELECT CASE WHEN dbo.SemanticVersion('1.0.0-*') <= dbo.SemanticVersion('1.0.0') THEN 'Success' ELSE 'Failure' END
    SELECT CASE WHEN dbo.SemanticVersion('1.0.1-*') > dbo.SemanticVersion('1.0.0') THEN 'Success' ELSE 'Failure' END
    SELECT CASE WHEN dbo.SemanticVersion('1.0.1-*') <= dbo.SemanticVersion('1.0.1') THEN 'Success' ELSE 'Failure' END
    SELECT CASE WHEN dbo.SemanticVersion('1.1.*') > dbo.SemanticVersion('1.0.9') THEN 'Success' ELSE 'Failure' END
    SELECT CASE WHEN dbo.SemanticVersion('1.1.*') <= dbo.SemanticVersion('1.2.0') THEN 'Success' ELSE 'Failure' END
    SELECT CASE WHEN dbo.SemanticVersion('1.*') <= dbo.SemanticVersion('2.0.0') THEN 'Success' ELSE 'Failure' END
    SELECT CASE WHEN dbo.SemanticVersion('1.*') > dbo.SemanticVersion('0.9.9-beta-219') THEN 'Success' ELSE 'Failure' END
    SELECT CASE WHEN dbo.SemanticVersion('*') <= dbo.SemanticVersion('0.0.1-alpha-1') THEN 'Success' ELSE 'Failure' END
    

提交回复
热议问题