2

可能重复:
如何使用 SQL Server 比较软件版本?

我是一个完整的 sql 新手,但是今天我在工作中发现了一个非常重要的 sql 查询中的错误。所以我可以使用一些帮助:

给定一个代表产品版本的 sql 字符串

'15.0.0.0'

有没有一种万无一失的方法来排序或比较该字符串,类似于.NET 类System.Version比较实例的方式?

因此,考虑到这样一个假设的构造、功能或其他任何东西,我预计“15.5.568”会大于“15.0.0.0”。

谢谢

4

3 回答 3

5

只需添加@Gordon 的建议,这是 ParseName 的示例

; WITH tmp
AS
(
    SELECT '1.0.0.5' AS Version
    UNION ALL SELECT '1.5.0.06'
    UNION ALL SELECT '1.0.0.06'
    UNION ALL SELECT '2.0.0.0'
    UNION ALL SELECT '2.0.1.1'
    UNION ALL SELECT '15.15.1323.22'
    UNION ALL SELECT '15.15.622.55'
)
SELECT *
FROM
(
    SELECT CAST(PARSENAME(Version, 4) AS INT) AS col1
        , CAST(PARSENAME(Version, 3) AS INT) AS col2
        , CAST(PARSENAME(Version, 2) AS INT) AS col3
        , CAST(PARSENAME(Version, 1) AS INT) AS col4
    FROM tmp
) t0
ORDER BY col1, col2, col3, col4
于 2012-11-09T21:03:05.497 回答
5

假设 SQL Server 和已知的最大部件数,这里有一个用户定义的函数,其作用与 相同parsename,但适用于任意数量的部件:

Create Function dbo.VersionNthPart(@version as nvarchar(max), @part as int) returns int as
Begin

  Declare
    @ret as int = null,
    @start as int = 1,
    @end as int = 0,
    @partsFound as int = 0

  if @version is not null
  Begin
    Set @ret = 0
    while @partsFound < @part
    Begin
      Set @end = charindex('.', @version, @start)
      If @end = 0
        Set @partsFound = @part -- bail early
      else
      Begin
        Set @partsFound = @partsFound + 1
        If @partsFound = @part
          Set @ret = Convert(int, substring(@version, @start, @end - @start))
        Else
          Set @start = @end + 1
      End
    End
  End
  return @ret
End

示例用法:

With
  tmp
As (
    Select '1.0.0.5' As Version
    Union All Select '1.5.0.06'
    Union All Select '1.0.0.06'
    Union All Select '2.0.0.0'
    Union All Select '2.0.1.1'
    Union All Select '15.5.568'
    Union All Select '15.0.0.0'
    Union All Select '15.15.1323.22'
    Union All Select '15.15.622.55'
)

Select
  *
From
   tmp
Order By
  dbo.VersionNthPart(Version, 1),
  dbo.VersionNthPart(Version, 2),
  dbo.VersionNthPart(Version, 3),
  dbo.VersionNthPart(Version, 4)

http://sqlfiddle.com/#!3/e942b/3

于 2012-11-09T21:22:44.663 回答
2

如果您的小数点不超过三位,那么您可以使用 parsename。以下将两个版本号校正为具有 4 个字符的值,因此字符串比较有效。你的例子是“0015.0000.0000.0000.0000”。

select (case when (right('0000'+coalesce(parsename(v1, 4), '', 4)) +
                   right('0000'+coalesce(parsename(v1, 3), '', 4)) +
                   right('0000'+coalesce(parsename(v1, 2), '', 4)) +
                   right('0000'+coalesce(parsename(v1, 1), '', 4))
                  ) < 
                  (right('0000'+coalesce(parsename(v2, 4), '', 4)) +
                   right('0000'+coalesce(parsename(v2, 3), '', 4)) +
                   right('0000'+coalesce(parsename(v2, 2), '', 4)) +
                   right('0000'+coalesce(parsename(v2, 1), '', 4))
                  )
             then -1
             when v1 = v2
             then 0
             else 1
         end) as Comparison

请注意, parsename() 最多只能处理名称中的四个部分。

如果您只想排序,那么以下将起作用:

order by (right('0000'+coalesce(parsename(v1, 4), '', 4)) +
          right('0000'+coalesce(parsename(v1, 3), '', 4)) +
          right('0000'+coalesce(parsename(v1, 2), '', 4)) +
          right('0000'+coalesce(parsename(v1, 1), '', 4))
         )
于 2012-11-09T21:00:29.333 回答