[SQL] 어떻게 SQL Server를 사용하여 소프트웨어 버전을 비교?
SQL어떻게 SQL Server를 사용하여 소프트웨어 버전을 비교?
5.12 5.8 소프트웨어 버전을 비교하려고 할 때, 버전 5.12 그러나 수학적으로 5.12 5.8 이하이며, 새로운이다. 어떻게 두 가지 버전이 최신 버전 반환 'Y'를 수 있도록 비교까요?
SELECT CASE WHEN 5.12 > 5.8 THEN 'Y' ELSE 'N' END
가능한 해결책
해결법
-
==============================
1.
declare @v1 varchar(100) = '5.12' declare @v2 varchar(100) = '5.8' select case when CONVERT(int, LEFT(@v1, CHARINDEX('.', @v1)-1)) < CONVERT(int, LEFT(@v2, CHARINDEX('.', @v2)-1)) then 'v2 is newer' when CONVERT(int, LEFT(@v1, CHARINDEX('.', @v1)-1)) > CONVERT(int, LEFT(@v2, CHARINDEX('.', @v2)-1)) then 'v1 is newer' when CONVERT(int, substring(@v1, CHARINDEX('.', @v1)+1, LEN(@v1))) < CONVERT(int, substring(@v2, CHARINDEX('.', @v2)+1, LEN(@v1))) then 'v2 is newer' when CONVERT(int, substring(@v1, CHARINDEX('.', @v1)+1, LEN(@v1))) > CONVERT(int, substring(@v2, CHARINDEX('.', @v2)+1, LEN(@v1))) then 'v1 is newer' else 'same!' end
-
==============================
2.나는 SQL의 CLR 기능을 작성하는 것이 좋습니다 :
나는 SQL의 CLR 기능을 작성하는 것이 좋습니다 :
public partial class UserDefinedFunctions { [SqlFunction(Name = "CompareVersion")] public static bool CompareVersion(SqlString x, SqlString y) { return Version.Parse(x) > Version.Parse(y); } }
노트:
-
==============================
3.여기에 중복 질문에서 아주 좋은 해결책이 있었다 : 어떻게 .NET System.Version 클래스와 같은 홀드 버전 번호가 SQL 문자열을 비교?
여기에 중복 질문에서 아주 좋은 해결책이 있었다 : 어떻게 .NET System.Version 클래스와 같은 홀드 버전 번호가 SQL 문자열을 비교?
잠시 동안 쿼리와 함께 연주 후, 나는 4 개 이상의 부품 (버전 번호가 1.2.3.4 인 경우 말, 항상 0으로 마지막을 치료하는 것)이있을 때 마지막 부분을 비교할 수 없음을 알게 . 나는 문제뿐만 아니라 두 버전 번호를 비교하는 또 다른 기능 해낸 것을 해결했습니다.
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, @terminate as bit = 0 if @version is not null Begin Set @ret = 0 while @partsFound < @part Begin Set @end = charindex('.', @version, @start) If @end = 0 -- did not find the dot. Either it was last part or the part was missing. begin if @part - @partsFound > 1 -- also this isn't the last part so it must bail early. begin set @terminate = 1 end Set @partsFound = @part SET @end = len(@version) + 1; -- get the full length so that it can grab the whole of the final part. end else begin SET @partsFound = @partsFound + 1 end If @partsFound = @part and @terminate = 0 begin Set @ret = Convert(int, substring(@version, @start, @end - @start)) end Else begin Set @start = @end + 1 end End End return @ret End GO CREATE FUNCTION [dbo].[CompareVersionNumbers] ( @Source nvarchar(max), @Target nvarchar(max), @Parts int = 4 ) RETURNS INT AS BEGIN /* -1 : target has higher version number (later version) 0 : same 1 : source has higher version number (later version) */ DECLARE @ReturnValue as int = 0; DECLARE @PartIndex as int = 1; DECLARE @SourcePartValue as int = 0; DECLARE @TargetPartValue as int = 0; WHILE (@PartIndex <= @Parts AND @ReturnValue = 0) BEGIN SET @SourcePartValue = [dbo].[VersionNthPart](@Source, @PartIndex); SET @TargetPartValue = [dbo].[VersionNthPart](@Target, @PartIndex); IF @SourcePartValue > @TargetPartValue SET @ReturnValue = 1 ELSE IF @SourcePartValue < @TargetPartValue SET @ReturnValue = -1 SET @PartIndex = @PartIndex + 1; END RETURN @ReturnValue END
사용 / 테스트 케이스 :
declare @Source as nvarchar(100) = '4.9.21.018' declare @Target as nvarchar(100) = '4.9.21.180' SELECT [dbo].[CompareVersionNumbers](@Source, @Target, DEFAULT) -- default version parts are 4 SET @Source = '1.0.4.1' SET @Target = '1.0.1.8' SELECT [dbo].[CompareVersionNumbers](@Source, @Target, 4) -- typing out # of version parts also works SELECT [dbo].[CompareVersionNumbers](@Source, @Target, 2) -- comparing only 2 parts should be the same SET @Target = '1.0.4.1.5' SELECT [dbo].[CompareVersionNumbers](@Source, @Target, 4) -- only comparing up to parts 4 so they are the same SELECT [dbo].[CompareVersionNumbers](@Source, @Target, 5) -- now comparing 5th part which should indicate that the target has higher version number
-
==============================
4.의미 론적 버전을 기반으로 필터 SQL 행하려고 할 때 나는이 발생했습니다. 내가 구성 행이 의미 론적 버전 번호로 태그 한 후 우리의 소프트웨어의 실행 버전과 호환 행을 선택 저장하고 싶어한다는 점에서 내 솔루션은 조금 달랐다.
의미 론적 버전을 기반으로 필터 SQL 행하려고 할 때 나는이 발생했습니다. 내가 구성 행이 의미 론적 버전 번호로 태그 한 후 우리의 소프트웨어의 실행 버전과 호환 행을 선택 저장하고 싶어한다는 점에서 내 솔루션은 조금 달랐다.
가정 :
예를 들면 :
MSSQL UDF는 다음과 같습니다
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 시험은 다음과 같습니다 :
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
-
==============================
5.두 단계는 먼저 소수점의 왼쪽이 오른쪽을 비교.
두 단계는 먼저 소수점의 왼쪽이 오른쪽을 비교.
가능한 해결책:
declare @v1 varchar(100) = '5.12' declare @v2 varchar(100) = '5.8' select case when CONVERT(int, LEFT(@v1, CHARINDEX('.', @v1)-1)) < CONVERT(int, LEFT(@v2, CHARINDEX('.', @v2)-1)) then 'v2 is newer' when CONVERT(int, LEFT(@v1, CHARINDEX('.', @v1)-1)) > CONVERT(int, LEFT(@v2, CHARINDEX('.', @v2)-1)) then 'v1 is newer' when CONVERT(int, RIGHT(@v1, LEN(@v1) - CHARINDEX('.', @v1))) < CONVERT(int, RIGHT(@v2, LEN(@v2) - CHARINDEX('.', @v2))) then 'v2 is newer' when CONVERT(int, RIGHT(@v1, LEN(@v1) - CHARINDEX('.', @v1))) > CONVERT(int, RIGHT(@v2, LEN(@v2) - CHARINDEX('.', @v2))) then 'v1 is newer' else 'same!' end as 'Version Test'
-
==============================
6.당신은 HIERARCHYID 사용할 수 있습니다 어떤 당신이 마지막에 /를 넣고 문자열의 시작을 주조로 사용할 수 있습니다
당신은 HIERARCHYID 사용할 수 있습니다 어떤 당신이 마지막에 /를 넣고 문자열의 시작을 주조로 사용할 수 있습니다
EG
SELECT CASE WHEN 캐스트 ( '/ 5.12 /'HIERARCHYID 등)> 캐스팅 ( '/ 5.8 /'HIERARCHYID 등) THEN ELSE 'Y', 'N'END
즉, Y를 반환
-
==============================
7.AF 제안로서 당신은 우선은 이런 식으로 뭔가를 시도 할 수 parsename를 사용하여 할 수있는 또 하나 개의 방법이 주어진 모든 해답에서 INT 부분과 다음 소수 부분 .Apart을 비교할 수 있습니다
AF 제안로서 당신은 우선은 이런 식으로 뭔가를 시도 할 수 parsename를 사용하여 할 수있는 또 하나 개의 방법이 주어진 모든 해답에서 INT 부분과 다음 소수 부분 .Apart을 비교할 수 있습니다
case when cast(@var as int)>cast(@var2 as int) then 'Y' when cast(PARSENAME(@var,1) as int) > cast(PARSENAME(@var2,1) as int) THEN 'Y' Declare @var float Declare @var2 float set @var=5.14 set @var2=5.8 Select case when cast(@var as int)>cast(@var2 as int) then 'Y' when cast(PARSENAME(@var,1) as int)> cast(PARSENAME(@var2,1) as int) THEN 'Y' else 'N' END
-
==============================
8.문자열이 아닌 어떤 문자열에 보관하지 마십시오. 바이트와 구현 적절한 비교 로직의 순서로 버전을 저장하는 것이 - 대체 (일부 시간에 허용 C #에서) 자신의 데이터 형식을 만드는 것입니다.
문자열이 아닌 어떤 문자열에 보관하지 마십시오. 바이트와 구현 적절한 비교 로직의 순서로 버전을 저장하는 것이 - 대체 (일부 시간에 허용 C #에서) 자신의 데이터 형식을 만드는 것입니다.
-
==============================
9.당신은 질문에 그렇게 말하지 않지만, 톰톰의 대답에서 귀하의 의견은 [소수] [D]와 같은 버전 번호를 저장하는 제안합니다. 나는이 같은 테이블이 추측 :
당신은 질문에 그렇게 말하지 않지만, 톰톰의 대답에서 귀하의 의견은 [소수] [D]와 같은 버전 번호를 저장하는 제안합니다. 나는이 같은 테이블이 추측 :
CREATE TABLE ReleaseHistory ( VersionNumber DECIMAL(6,3) NOT NULL ); GO INSERT INTO ReleaseHistory ( VersionNumber ) VALUES (5.12), (5.8), (12.34), (3.14), (0.78), (1.0); GO
다음 쿼리는 그들이 출시되는 순서에 의해 순위 버전으로 시도이다 :
SELECT VersionNumber, RANK() OVER (ORDER BY VersionNumber) AS ReleaseOrder FROM ReleaseHistory;
그것은 다음과 같은 결과 집합을 생성합니다
VersionNumber ReleaseOrder --------------------------------------- -------------------- 0.780 1 1.000 2 3.140 3 5.120 4 5.800 5 12.340 6
이것은 우리가 기대하지 않습니다. 버전 5.8은 버전 5.12 이전에 릴리스 된!
제대로 버전 번호를 평가하기 위해 전공 및 부전공 구성 요소에 버전 번호를 분할합니다. 이 작업을 수행하는 한 가지 방법은 기간에 문자열 및 분할에 소수점 값을 변환하는 것입니다. 이에 대한 T-SQL 구문 (언어가 문자열 처리를 위해 설계되지 않았습니다) 못생긴 :
WITH VersionStrings AS ( SELECT CAST(VersionNumber AS VARCHAR(6)) AS VersionString FROM ReleaseHistory ), VersionNumberComponents AS ( SELECT CAST(SUBSTRING(VersionString, 1, CHARINDEX('.', VersionString) - 1) AS INT) AS MajorVersionNumber, CAST(SUBSTRING(VersionString, CHARINDEX('.', VersionString) + 1, LEN(VersionString) - CHARINDEX('.', VersionString)) AS INT) AS MinorVersionNumber FROM VersionStrings ) SELECT CAST(MajorVersionNumber AS VARCHAR(3)) + '.' + CAST(MinorVersionNumber AS VARCHAR(3)) AS VersionString, RANK() OVER (ORDER BY MajorVersionNumber, MinorVersionNumber) AS ReleaseOrder FROM VersionNumberComponents;
그러나 예상 결과를 제공합니다 :
VersionString ReleaseOrder ------------- -------------------- 0.780 1 1.0 2 3.140 3 5.120 4 5.800 5 12.340 6
톰톰 대답으로, 진수는 버전 번호를 저장하는 안 좋은 유형입니다. 두 개의 양의 정수 열, 주 버전 번호와 마이너 버전 번호를 포함하는 기타를 포함하는 하나의 버전 번호를 저장하기 위해 더 좋을 것이다.
-
==============================
10.이 SeanW의 대답을 기반으로하지만,이 솔루션은 다음과 같은 형식 [주요] 수 있습니다. [작은]. [빌드]. 그것은 아마도 SQL 2K에 사용되는 커서는 옵션이 아닌 경우.
이 SeanW의 대답을 기반으로하지만,이 솔루션은 다음과 같은 형식 [주요] 수 있습니다. [작은]. [빌드]. 그것은 아마도 SQL 2K에 사용되는 커서는 옵션이 아닌 경우.
declare @v1 varchar(100) = '1.4.020' declare @v2 varchar(100) = '1.4.003' declare @v1_dot1_pos smallint /*position - 1st version - 1st dot */ declare @v1_dot2_pos smallint /*position - 1st version - 2nd dot */ declare @v2_dot1_pos smallint /*position - 2nd version - 1st dot */ declare @v2_dot2_pos smallint /*position - 2nd version - 2nd dot */ ------------------------------------------------- -- get the pos of the first and second dots ------------------------------------------------- SELECT @v1_dot1_pos=CHARINDEX('.', @v1), @v2_dot1_pos=CHARINDEX('.', @v2), @v1_dot2_pos=charindex( '.', @v1, charindex( '.', @v1 ) + 1 ), @v2_dot2_pos=charindex( '.', @v2, charindex( '.', @v2 ) + 1 ) ------------------------------------------------- -- break down the parts ------------------------------------------------- DECLARE @v1_major int, @v2_major int DECLARE @v1_minor int, @v2_minor int DECLARE @v1_build int, @v2_build int SELECT @v1_major = CONVERT(int,LEFT(@v1,@v1_dot1_pos-1)), @v1_minor = CONVERT(int,SUBSTRING(@v1,@v1_dot1_pos+1,(@v1_dot2_pos-@v1_dot1_pos)-1)), @v1_build = CONVERT(int,RIGHT(@v1,(LEN(@v1)-@v1_dot2_pos))), @v2_major = CONVERT(int,LEFT(@v2,@v2_dot1_pos-1)), @v2_minor = CONVERT(int,SUBSTRING(@v2,@v2_dot1_pos+1,(@v2_dot2_pos-@v2_dot1_pos)-1)), @v2_build = CONVERT(int,RIGHT(@v2,(LEN(@v2)-@v2_dot2_pos))) ------------------------------------------------- -- return the difference ------------------------------------------------- SELECT Case WHEN @v1_major < @v2_major then 'v2 is newer' WHEN @v1_major > @v2_major then 'v1 is newer' WHEN @v1_minor < @v2_minor then 'v2 is newer' WHEN @v1_minor > @v2_minor then 'v1 is newer' WHEN @v1_build < @v2_build then 'v2 is newer' WHEN @v1_build > @v2_build then 'v1 is newer' ELSE '!Same' END
-
==============================
11.구현 된 솔루션 :
구현 된 솔루션 :
CREATE FUNCTION [dbo].[version_compare] ( @v1 VARCHAR(5), @v2 VARCHAR(5) ) RETURNS tinyint AS BEGIN DECLARE @v1_int tinyint, @v1_frc tinyint, @v2_int tinyint, @v2_frc tinyint, @ResultVar tinyint SET @ResultVar = 0 SET @v1_int = CONVERT(tinyint, LEFT(@v1, CHARINDEX('.', @v1) - 1)) SET @v1_frc = CONVERT(tinyint, RIGHT(@v1, LEN(@v1) - CHARINDEX('.', @v1))) SET @v2_int = CONVERT(tinyint, LEFT(@v2, CHARINDEX('.', @v2) - 1)) SET @v2_frc = CONVERT(tinyint, RIGHT(@v2, LEN(@v2) - CHARINDEX('.', @v2))) SELECT @ResultVar = CASE WHEN @v2_int > @v1_int THEN 2 WHEN @v1_int > @v2_int THEN 1 WHEN @v2_frc > @v1_frc THEN 2 WHEN @v1_frc > @v2_frc THEN 1 ELSE 0 END -- Return the result of the function RETURN @ResultVar END GO
-
==============================
12.이 재귀 쿼리는 '어떤 변환 것입니다 .- 비교 문자열로 분리 된 버전 번호는 왼쪽 패딩 10 자 따라서 또는 빌드 번호가없는 버전을 비교할 수 있도록하고 숫자가 아닌 문자를 수용 각 요소를 :
이 재귀 쿼리는 '어떤 변환 것입니다 .- 비교 문자열로 분리 된 버전 번호는 왼쪽 패딩 10 자 따라서 또는 빌드 번호가없는 버전을 비교할 수 있도록하고 숫자가 아닌 문자를 수용 각 요소를 :
WITH cte (VersionNumber) AS ( SELECT '1.23.456' UNION ALL SELECT '2.3' UNION ALL SELECT '0.alpha-3' ), parsed (VersionNumber, Padded) AS ( SELECT CAST(SUBSTRING(VersionNumber, CHARINDEX('.', VersionNumber) + 1, LEN(VersionNumber)) + '.' AS NVARCHAR(MAX)), CAST(RIGHT(REPLICATE('0', 10) + LEFT(VersionNumber, CHARINDEX('.', VersionNumber) - 1), 10) AS NVARCHAR(MAX)) FROM cte UNION ALL SELECT SUBSTRING(VersionNumber, CHARINDEX('.', VersionNumber) + 1, LEN(VersionNumber)), Padded + RIGHT(REPLICATE('0', 10) + LEFT(VersionNumber, CHARINDEX('.', VersionNumber) - 1), 10) FROM parsed WHERE CHARINDEX('.', VersionNumber) > 0 ) SELECT Padded FROM parsed WHERE VersionNumber = '' ORDER BY Padded;
Padded ------------------------------ 0000000000000alpha-3 000000000100000000230000000456 00000000020000000003
-
==============================
13.여기에 내가에 유래에서 발견 된 일부 코드를 수정하고 일부 나 자신을 써서 한 것입니다. 이 때문에 나를 어떻게 생각하는지 알려 주시기 바랍니다 코드의 버전 1입니다. 사용 예 및 테스트 케이스는 코드 주석에 있습니다.
여기에 내가에 유래에서 발견 된 일부 코드를 수정하고 일부 나 자신을 써서 한 것입니다. 이 때문에 나를 어떻게 생각하는지 알려 주시기 바랍니다 코드의 버전 1입니다. 사용 예 및 테스트 케이스는 코드 주석에 있습니다.
SQL 2016 이상을 사용하지 않는 당신이 STRING_SPLIT에 액세스 할 수없는 경우 먼저이 기능을 만듭니다
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: <Author,,Name> -- Create date: <Create Date,,> -- Description: modified from https://stackoverflow.com/questions/10914576/t-sql-split-string/42000063#42000063 -- ============================================= CREATE FUNCTION [dbo].[SplitStringToRows] ( @List VARCHAR(4000) , @Delimiter VARCHAR(50) ) RETURNS TABLE AS RETURN ( --For testing -- SELECT * FROM SplitStringToRows ('1.0.123','.') -- DECLARE @List VARCHAR(MAX) = '1.0.123', @Delimiter VARCHAR(50) = '.'; WITH Casted AS ( SELECT CAST(N'<x>' + REPLACE((SELECT REPLACE(@List,@Delimiter,N'§§Split$me$here§§') AS [*] FOR XML PATH('')),N'§§Split$me$here§§',N'</x><x>') + N'</x>' AS XML) AS SplitMe ) SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS [Index] , x.value(N'.',N'nvarchar(max)') AS Part FROM Casted CROSS APPLY SplitMe.nodes(N'/x') AS A(x) )
그런 다음이 함수를 만들 :
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO -- ============================================= -- Author: Soenhay -- Create date: 7/1/2017 -- Description: Returns -1 if VersionStringA is less than VersionStringB. -- Returns 0 if VersionStringA equals VersionStringB. -- Returns 1 if VersionSTringA is greater than VersionStringB. -- ============================================= CREATE FUNCTION dbo.CompareVersionStrings ( @VersionStringA VARCHAR(50) ,@VersionStringB VARCHAR(50) ) RETURNS TABLE AS RETURN ( --CurrentVersion should be of the form: --major.minor[.build[.revision]] --This is the same as the versioning system used in c#. --For applications the build and revision numbers will by dynamically set based on the current date and time of the build. --Example: [assembly: AssemblyFileVersion("1.123.*")]//http://stackoverflow.com/questions/15505841/the-version-specified-for-the-file-version-is-not-in-the-normal-major-minor-b --Each component should be between 0 and 65534 ( UInt16.MaxValue - 1 ) --Max version number would be 65534.65534.65534.65534 --For Testing -- SELECT * FROM dbo.CompareVersionStrings('', '') -- SELECT * FROM dbo.CompareVersionStrings('asdf.asdf', 'asdf.asdf') --returns 0 -- SELECT * FROM dbo.CompareVersionStrings('asdf', 'fdas') --returns -1 -- SELECT * FROM dbo.CompareVersionStrings('zasdf', 'fdas') --returns 1 -- SELECT * FROM dbo.CompareVersionStrings('1.0.123.123', '1.1.123.123') --Should return -1 -- SELECT * FROM dbo.CompareVersionStrings('1.0.123.123', '1.0.123.123') --Should return 0 -- SELECT * FROM dbo.CompareVersionStrings('1.1.123.123', '1.0.123.123') --Should return 1 -- SELECT * FROM dbo.CompareVersionStrings('1.0.123.123', '1.0.124.123') --Should return -1 -- SELECT * FROM dbo.CompareVersionStrings('1.0.124.123', '1.0.123.123') --Should return 1 -- SELECT * FROM dbo.CompareVersionStrings('1.0.123.123', '1.0.123.124') --Should return -1 -- SELECT * FROM dbo.CompareVersionStrings('1.0.123.124', '1.0.123.123') --Should return 1 -- SELECT * FROM dbo.CompareVersionStrings('1.0', '1.1') --Should return -1 -- SELECT * FROM dbo.CompareVersionStrings('1.0', '1.0') --Should return 0 -- SELECT * FROM dbo.CompareVersionStrings('1.1', '1.0') --Should return 1 -- Declare @VersionStringA VARCHAR(50) = '' ,@VersionStringB VARCHAR(50) = '' ; -- Declare @VersionStringA VARCHAR(50) = '1.0.123.123' ,@VersionStringB VARCHAR(50) = '1.1.123.123' ; -- Declare @VersionStringA VARCHAR(50) = '1.1.123.123' ,@VersionStringB VARCHAR(50) = '1.1.123.123' ; -- Declare @VersionStringA VARCHAR(50) = '1.2.123.123' ,@VersionStringB VARCHAR(50) = '1.1.123.123' ; -- Declare @VersionStringA VARCHAR(50) = '1.1.123' ,@VersionStringB VARCHAR(50) = '1.1.123.123' ; -- Declare @VersionStringA VARCHAR(50) = '1.1.123.123' ,@VersionStringB VARCHAR(50) = '1.1.123' ; -- Declare @VersionStringA VARCHAR(50) = '1.1' ,@VersionStringB VARCHAR(50) = '1.1' ; -- Declare @VersionStringA VARCHAR(50) = '1.2' ,@VersionStringB VARCHAR(50) = '1.1' ; -- Declare @VersionStringA VARCHAR(50) = '1.1' ,@VersionStringB VARCHAR(50) = '1.2' ; WITH Indexes AS ( SELECT 1 AS [Index] , 'major' AS Name UNION SELECT 2 , 'minor' UNION SELECT 3 , 'build' UNION SELECT 4 , 'revision' ) , SplitA AS ( SELECT * FROM dbo.SplitStringToRows(@VersionStringA, '.') ) , SplitB AS ( SELECT * FROM dbo.SplitStringToRows(@VersionStringB, '.') ) SELECT CASE WHEN major = 0 THEN CASE WHEN minor = 0 THEN CASE WHEN build = 0 THEN CASE WHEN revision = 0 THEN 0 ELSE revision END ELSE build END ELSE minor END ELSE major END AS Compare FROM ( SELECT MAX(CASE WHEN [Index] = 1 THEN Compare ELSE NULL END) AS major ,MAX(CASE WHEN [Index] = 2 THEN Compare ELSE NULL END) AS minor ,MAX(CASE WHEN [Index] = 3 THEN Compare ELSE NULL END) AS build ,MAX(CASE WHEN [Index] = 4 THEN Compare ELSE NULL END) AS revision FROM( SELECT [Index], Name, CASE WHEN A = B THEN 0 WHEN A < B THEN -1 WHEN A > B THEN 1 END AS Compare FROM ( SELECT i.[Index] ,i.Name ,ISNULL(a.Part, 0) AS A ,ISNULL(b.Part, 0) AS B FROM Indexes i LEFT JOIN SplitA a ON a.[Index] = i.[Index] LEFT JOIN SplitB b ON b.[Index] = i.[Index] ) q1 ) q2 ) q3 ) GO
-
==============================
14.I,이 함수 (상기 에바 레이스 ()에서 영감) 만들었다 :
I,이 함수 (상기 에바 레이스 ()에서 영감) 만들었다 :
CREATE or alter function dbo.IsVersionNewerThan ( @Source nvarchar(max), @Target nvarchar(max) ) RETURNS table as /* -1 : target has higher version number (later version) 0 : same 1 : source has higher version number (later version) test harness: ; WITH tmp AS ( SELECT '1.0.0.5' AS Version UNION ALL SELECT '0.0.0.0' UNION ALL SELECT '1.5.0.6' UNION ALL SELECT '2.0.0' 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 tmp.version, isGreather from tmp outer apply (select * from dbo.IsVersionNewerThan(tmp.Version, '2.0.0.0')) as IsG */ return ( select CASE when cast('/' + @Source + '/' as hierarchyid) > cast('/' + @Target + '/' as hierarchyid) THEN 1 when @Source = @Target then 0 else -1 end as IsGreather ) go
테스트 스크립트는 주석으로 포함되어 있습니다. 당신이 '1.5.06.2'(제로주의)와 같은 버전을 가지고 있지 않는 한 그것은 한 작품. SQL Server는이 기능은 성능을 잘 is_inlineable = 1, 징조를 가지고 생각합니다.
그럼 내 SQL 코드는 다음과 같을 수 있습니다 :
declare @version varchar(10) = '2.30.1.12' set @version = '2.30.1.1' if exists(select * from dbo.IsVersionNewerThan(@version,'2.30.1.12') where IsGreather >= 0) BEGIN print 'yes' end else print 'no'
-
==============================
15.난 당신이 가장 짧은 대답을 줄 수 있습니다.
난 당신이 가장 짧은 대답을 줄 수 있습니다.
with cte as ( select 7.11 as ver union all select 7.6 ) select top 1 ver from cte order by parsename(ver, 2), parsename(cast(ver as float), 1)
-
==============================
16.어쩌면 값으로 빌드 번호를 변환하는 빌드 버전 사이의 계층 구조를 이해하는 데 도움이 될 수 있습니다.
어쩌면 값으로 빌드 번호를 변환하는 빌드 버전 사이의 계층 구조를 이해하는 데 도움이 될 수 있습니다.
DECLARE @version VARCHAR(25), @dot1 AS TINYINT, @dot2 AS TINYINT, @dot3 AS TINYINT, @MaxPower AS TINYINT, @Value AS BIGINT SELECT @version = CAST(SERVERPROPERTY('ProductVersion') AS VARCHAR) --'14.0.1000.169' --'10.50.1600' SELECT @dot1 = CHARINDEX('.', @version, 1) SELECT @dot2 = CHARINDEX('.', @version, @dot1 + 1) SELECT @dot3 = CHARINDEX('.', @version, @dot2 + 1) SELECT @dot3 = CASE WHEN @dot3 = 0 THEN LEN(@version) + 1 ELSE @dot3 END SELECT @MaxPower = MAX(DotColumn) FROM (VALUES (@dot1-1), (@dot2-@dot1-1), (@dot3-@dot2-1)) AS DotTable(DotColumn) SELECT @Value = POWER(10, @MaxPower) --SELECT @version, @dot1, @dot2, @dot3, @MaxPower, @Value SELECT -- @version AS [Build], CAST(LEFT(@version, @dot1-1) AS INT) * POWER(@Value, 3) + CAST(SUBSTRING(@version, @dot1+1, @dot2-@dot1-1) AS INT) * POWER(@Value, 2) + CAST(SUBSTRING(@version, @dot2+1, @dot3-@dot2-1) AS INT) * @Value + CASE WHEN @dot3 = LEN(@version)+1 THEN CAST(0 AS INT) ELSE CAST(SUBSTRING(@version, @dot3+1, LEN(@version)-@dot3) AS INT) END AS [Value]
from https://stackoverflow.com/questions/11364242/how-to-compare-software-versions-using-sql-server by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 나는 복합 기본 키 여부를 사용해야합니까? (0) | 2020.06.11 |
---|---|
[SQL] 어떻게 T-SQL을 사용하여 문자열에서 숫자 부분을 얻으려면? (0) | 2020.06.11 |
[SQL] 최대 절전 모드 기준 API : GET n은 임의 행 (0) | 2020.06.11 |
[SQL] 저장 프로 시저에서 SQL 서버 변수 범위 (0) | 2020.06.11 |
[SQL] SQL 서버, 할 수없는 기본 키 필드에 널 (null)입니까? (0) | 2020.06.11 |