【问题标题】:Datatype for System.Version in sql serversql server 中 System.Version 的数据类型
【发布时间】:2012-10-17 11:48:16
【问题描述】:

在 SQL Server 中存储System.Version 的最佳方式是什么?

当我使用varchar类型时,按asc排序的结果是:

1.0.0.0
11.0.0.0
12.0.0.0
2.0.0.0

【问题讨论】:

  • +1 表示好问题
  • 您还有其他相关专栏可以帮助您订购这些版本吗?
  • @V4Vendetta 不,我没有

标签: c# .net sql-server system.version


【解决方案1】:

您可以使用 varchar 列

你可以这样订购

SELECT *
FROM t_version 
ORDER BY CAST('/' + vid + '/' AS HIERARCHYID)

SQL fiddle 今天不工作,否则我可以展示一个演示

请运行它进行测试

 SELECT * FROM 
( VALUES 
        ( '1.0.0.0' ),
        ( '11.0.0.0' ),
        ('12.0.0.0'),
        ('2.0.0.0') ) AS vid ( vid ) 
ORDER BY CAST('/' + vid + '/' AS HIERARCHYID)

【讨论】:

  • 提示:您可以更轻松地使用VALUES 而不是UNION ALL 进行演示答案:SELECT * FROM ( VALUES ( '1.0.0.0' ), ( '11.0.0.0' ) ... ) AS vid ( vid ) ORDER BY ...
  • @hvd:谢谢你,这看起来更干净..我已经更新了我的答案
  • @hvd 我通常不会,除非问题被标记为sql-server-2008,或 2012
  • @RichardTheKiwi 公平点,但 HIERARCHYID 已经需要 SQL Server 2008 :)
【解决方案2】:

只需将其存储为普通 varchar,这适用于最多 4 个部分的版本,使用 PARSENAME 将字符串和顺序拆分为 4 个单独的列。

ORDER BY PARSENAME(version,4),
         PARSENAME(version,3),
         PARSENAME(version,2),
         PARSENAME(version,1)

【讨论】:

    【解决方案3】:

    为了支持混合长度版本之间的排序(例如“1.2”与“1.2.3.4”),可以执行到小数的映射(作为内联表值函数)。

    create function Common.ufn_OrderableVersion(@pVersion nvarchar(100))
    returns table
    as
    /*---------------------------------------------------------------------------------------------------------------------
        Purpose:  Provide a mapping from Versions of the form 'a.b.c.d', 'a.b.c, 'a.b', 'a', null to 
                  an orderable decimal(25, 0) 
    
                  Since Parsename() doesn't apply easily to mixed length comparisions (1.2 vs 1.2.3.4)
    
     Test Cases:
                  select * from Common.ufn_OrderableVersion(null);       -- null
                  select * from Common.ufn_OrderableVersion('0');        -- 1000000000000000000000000
                  select * from Common.ufn_OrderableVersion('1');        -- 1000001000000000000000000
                  select * from Common.ufn_OrderableVersion('1.2.3.4');  -- 1000001000002000003000004
    
                  select Version
                    from 
                       (
                          select '1.3.5.3' as Version
                          union all
                          select '1.2.5.3' as Version
                          union all
                          select '1.1.5.3' as Version
                          union all
                          select '1.3.5.2' as Version
                          union all
                          select null as Version
                          union all                      
                          select '' as Version
                          union all
                          select '2' as Version
                          union all
                          select '1.2' as Version
                          union all
                          select '1' as Version                      
                       ) v 
                   order by (select Value from Common.ufn_OrderableVersion(Version))
    
        Modified    By              Description
        ----------  --------------  ---------------------------------------------------------------------------------------
        2015.08.24  crokusek        Initial Version
      ---------------------------------------------------------------------------------------------------------------------*/
    return         
        -- 25 = 1 + VersionPositions * MaxDigitsPerSegment
        select convert(decimal(25,0), '1' + 
               stuff((select format(Value, '000000')
                        from 
                           (
                              select convert(int, Value) as Value, RowNumber 
                                  -- Support empty string and partial versions. Null maps to null
                                from Common.ufn_SplitUsingXml(@pVersion + '.0.0.0.0', '.') -- pad right
                               where RowNumber <= 4 -- trim right
                           ) as v
                       order by RowNumber
                         for xml path ('')
                    ), 1, 0, '')
               ) as Value
    go
    

    依赖:

    create function Common.ufn_SplitUsingXml
    (
       @pList       nvarchar(max),
       @pDelimiter  nvarchar(255)
    )
    returns table
    as
    /*---------------------------------------------------------------------------------------------------------------------
        Purpose:  Split an Identifier using XML as an inline table valued function.  
                  Using the SQL Server CLR (C#) capability would be the most efficient way to support this.
    
       Warnings:  Will not work if the input contains special XML characters like '<', '>' or '&'.
                  Caller must add "option (maxrecursion 0)" for lists greater than 100 (it can't be added within the ufn)                  
    
        Modified    By              Description
        ----------  --------------  ---------------------------------------------------------------------------------------
        2015.08.24  inet            http://sqlperformance.com/2012/07/t-sql-queries/split-strings
      ---------------------------------------------------------------------------------------------------------------------*/
    return 
    (  
      select Value = y.i.value('(./text())[1]', 'nvarchar(4000)'),
             row_number() over (order by (select null)) as RowNumber 
      from 
      (  
        select x = convert(XML, '<i>' 
           + replace(@pList, @pDelimiter, '</i><i>') 
           + '</i>').query('.')
      ) AS a cross apply x.nodes('i') AS y(i)
      -- option (maxrecursion 0) must be added by caller for lists greater than 100
    );
    go
    

    比较:

    alter function Common.ufn_CompareVersions
    (
       @pVersionA nvarchar(100),
       @pVersionB nvarchar(100)
    )
    returns table
    as
    /*---------------------------------------------------------------------------------------------------------------------
        Purpose:  Compare Version of the form 'A.B.C.D'.  
                  Comparing versions of different lengths is also supported 'A.B'.
    
     Test Cases:
                  select Result from Common.ufn_CompareVersions('1', null) -- 1
                  select Result from Common.ufn_CompareVersions(null, '1') -- -1
                  select Result from Common.ufn_CompareVersions('1', '1') -- 0
                  select Result from Common.ufn_CompareVersions('1', '2') -- -1
                  select Result from Common.ufn_CompareVersions('2', '1') -- 1
                  select Result from Common.ufn_CompareVersions('1', '1.2') -- -1
                  select Result from Common.ufn_CompareVersions('1.2', '1') -- 1
                  select Result from Common.ufn_CompareVersions('1.2.3.4', '1.2.3.4') -- 0
                  select Result from Common.ufn_CompareVersions('1.2.3', '1.2.3.4') -- -1
                  select Result from Common.ufn_CompareVersions('1.2.3.4', '1.2.3') -- 1
                  select Result from Common.ufn_CompareVersions('1.9.3.4', '1.2.3.4') -- 1
                  select Result from Common.ufn_CompareVersions('1.2.3.4', '1.9.3.4') -- -1
                  select Result from Common.ufn_CompareVersions('1.002', '1.2') -- 0
                  select Result from Common.ufn_CompareVersions('1.2', '1.2.0') -- 0
    
        Modified    By           Description
        ----------  -----------  ------------------------------------------------------------------------------------------
        2015.08.24  crokusek     Initial Version
      ---------------------------------------------------------------------------------------------------------------------*/
    return    
        with Compares as
        (
          select (select IsNull(Value, 0) from Common.ufn_OrderableVersion(@pVersionA)) as A,
                 (select IsNull(Value, 0) from Common.ufn_OrderableVersion(@pVersionB)) as B
        )
        select case when A > B then 1
                    when A < B then -1
                    else 0
               end as Result
          from Compares
    go
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-09
      • 2015-06-25
      • 2010-12-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-20
      • 2013-01-19
      相关资源
      最近更新 更多