28

System.Versionを SQL Serverに格納する最良の方法は何ですか?

varchar 型を使用すると、asc による順序の結果は次のようになります。

1.0.0.0
11.0.0.0
12.0.0.0
2.0.0.0
4

3 に答える 3

11

varchar 列を使用できます

このように注文できます

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

SQL フィドルは今日は機能していません。それ以外の場合は、デモを表示できたはずです

テストのためにこれを実行してください

 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)
于 2012-10-17T11:58:28.370 に答える
7

通常の varchar として保存するだけです。これは、PARSENAME を使用して文字列を分割し、4 つの個別の列で並べ替える最大 4 つの部分のバージョンに適しています。

すなわち

ORDER BY PARSENAME(version,4),
         PARSENAME(version,3),
         PARSENAME(version,2),
         PARSENAME(version,1)
于 2012-10-17T11:58:46.483 に答える
0

長さが混在するバージョン (例: '1.2' と '1.2.3.4') 間の順序付けをサポートするために、10 進数へのマッピングを (インライン テーブル値関数として) 実行できます。

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
于 2015-08-24T22:01:01.700 に答える